2015-11-03 117 views
3

我在物料清單的對象List<BoM>的名單我有一個List<BoMLine>,現在我已經通過減少在一個方法返回一個排序列表BoMLine屬性的一個排序BoM列表,如何使用java 8中的reduce對列表進行排序?

public static List<BoM> sortBoms() { 
    List<BoM> sortedBomList = new ArrayList<>(); 
    BoM bomn = new BoM(); 
    sortedBomList.add(bomList.parallelStream().reduce(bomn, 
      (bom1, bom2) -> sortBoM(bom1, bom2))); 
    System.out.println(sortedBomList.size()); 
    return sortedBomList; 
} 

bomList 2是BOM清單和sortBoM方法:

private static BoM sortBoM(BoM bom1, BoM bom2) { 
    bom2.getLine().stream() 
      .sorted((l1, l2) -> l1.getLineNum().compareTo(l2.getLineNum())); 
    bom1 = bom2; 
    return bom1; 
} 

物料清單類:

public class BoM implements Domain { 

private String BomCode; 
private List<BoMLine> line = new ArrayList<BoMLine>(); 

public String getBomCode() { 
    return BomCode; 
} 

public void setBomCode(String bomCode) { 
    BomCode = bomCode; 
} 

public List<BoMLine> getLine() { 
    return line; 
} 

public void setLine(List<BoMLine> line) { 
    this.line = line; 
} 

public void addLine(BoMLine bomLine) { 
    bomLine.setbOM(this); 
    line.add(bomLine); 
}} 

和BoML ine類:

public class BoMLine implements Domain { 

private Long lineNum; 
private String material; 
private BigDecimal Qty; 
private BoM bOM; 

public Long getLineNum() { 
    return lineNum; 
} 

public void setLineNum(Long lineNum) { 
    this.lineNum = lineNum; 
} 

public String getMaterial() { 
    return material; 
} 

public void setMaterial(String material) { 
    this.material = material; 
} 

public BigDecimal getQty() { 
    return Qty; 
} 

public void setQty(BigDecimal qty) { 
    Qty = qty; 
} 

public BoM getbOM() { 
    return bOM; 
} 

public void setbOM(BoM bOM) { 
    this.bOM = bOM; 
} 

public String getBoMCode() { 
    return bOM.getBomCode(); 
} 

@Override 
public String toString() { 
    return "BoMLine [ bOM=" + bOM.getBomCode() + ", lineNum=" + lineNum 
      + ", material=" + material + ", Qty=" + Qty + "]"; 
}} 

我必須通過BoMLine lineNum訂購BoM列表。 但它只是返回bomList.Any幫助的一個對象?

+0

你能發表一個輸入和想要的輸出的例子嗎?我不確定我瞭解每個「BoM」應該如何排序。 – Tunaki

+0

編輯帖子,請看看 – Nazila

+0

我還是不明白'BoM'對象應該如何排序。您可以通過行號對'List '進行排序,但這無助於將兩個「BoM」進行比較。 – Tunaki

回答

2

您可以通過創建使用Comparator.comparing定製Comparator行號的升序每個BoMLine排序:

List<BoM> sortedBomList = new ArrayList<>(); 
sortedBomList.forEach(bom -> bom.getLine().sort(comparing(BoMLine::getLineNum))); 

注意,這會產生變異的List<BoMLine>List<BoM>這可能不是一個好主意。

一個更好的方式是去不變性和創建一個構造函數取BOM編碼和BOM錶行:

List<BoM> sortedBomList = 
     bomList.stream() 
       .map(bom -> new BoM(
           bom.BomCode, 
           bom.getLine().stream() 
              .sorted(comparing(BoMLine::getLineNum)) 
              .collect(toList()) 
          ) 
       ) 
       .collect(toList()); 
+0

不,我必須使用減少 – Nazila

+1

@nazila你什麼意思,你「必須使​​用減少」做些什麼的問題?您無法使用reduce對列表進行排序,這不是該方法的用途。你真的想在這裏做什麼? – Tunaki

+0

你可以實現所有這些方法的減少,但我不知道如何 – Nazila

0

您將無法獲得與減少排序列表。爲了得到一個排序列表,你必須使用sortBoms()方法中的排序,然後是一個返回列表的收集邏輯。

修改後的代碼看起來像下面的片段:

sortedBomList.add(bomList.parallelStream().sorted(byBoMLineProperty).collect(Collectors.toList()); 

這也將需要執行byBoMLineProperty比較器通過其BoMLine屬性兩個物料清單進行比較。

+0

我必須使用reduce。 – Nazila

-2

通過發佈大量不相關的代碼,您已經大大地過分複雜化了您的問題。你所問的是如何使用reduce對數字列表進行排序,因此整個問題可以有效地簡化爲實現方法List<Integer> sorted(List<Integer> list)

請注意,雖然這是可能的,但效率低下,推薦使用Tunaki顯示的解決方案。我想這是大學任務的一部分。

import org.junit.Test; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.PriorityQueue; 

import static java.util.Arrays.asList; 
import static java.util.Collections.singleton; 
import static junit.framework.Assert.assertEquals; 

public class ReductionSortingTest { 

    @Test 
    public void sortsTheList() { 
     List<Integer> list =  asList(5, 3, 9, 8, 15, -4, 9); 
     List<Integer> expected = asList(-4, 3, 5, 8, 9, 9, 15); 

     List<Integer> sorted = sorted(list); 

     assertEquals(expected, sorted); 
    } 

    private static List<Integer> sorted(List<Integer> list) { 
     PriorityQueue<Integer> pq = list.stream() 
       .map((Integer n) -> new PriorityQueue<>(singleton(n))) 
       .reduce(new PriorityQueue<>(), (pq1, pq2) -> { 
        pq1.addAll(pq2); 
        return pq1; 
       }); 

     List<Integer> result = new ArrayList<>(); 
     while (!pq.isEmpty()) { 
      result.add(pq.poll()); 
     } 
     return result; 
    } 

} 

的Java缺乏一個排序列表,所以我決定去與PriorityQueue,閱讀更多關於它在this question。根據元素的自然順序,PriorityQueue保證頂層元素(通過peek(),poll()方法訪問)最低。無法保證其迭代器返回的元素順序,因此爲什麼我們必須使用poll()方法清空隊列 - 您可能需要實現自己的SortedList類。

編輯:

這裏是一個排序列表的解決方案。請記住,雖然沒有最終的迭代,並且它使用二分搜索,但其效率遠非簡單排序(我們正在談論的可能大約是O(n^3))。

private List<Integer> sorted(List<Integer> list) { 
    return list.stream() 
      .map(SortedIntList::new) 
      .reduce(new SortedIntList(), (a, b) -> { 
       a.addAll(b); 
       return a; 
      }); 
} 

private static class SortedIntList extends ArrayList<Integer> { 

    public SortedIntList() {} 

    public SortedIntList(int element) { 
     super(singletonList(element)); 
    } 

    @Override 
    public boolean add(Integer integer) { 
     int insertionPoint = Collections.binarySearch(this, integer); 
     if (insertionPoint < 0) { 
      insertionPoint = -insertionPoint - 1; 
     } 
     super.add(insertionPoint, integer); 
     return true; 
    } 

    @Override 
    public boolean addAll(Collection<? extends Integer> c) { 
     c.forEach(this::add); 
     return true; 
    } 

} 
+2

您正在使用'reduce'不排序,你只是添加元素的內在有序集合,這是,順便說一句,一個無效的使用reduce'的',因爲它的變異的輸入值。 – Holger

+0

@Holger 1.據我瞭解的問題,任務是使用'流()排序減少(...)',而不是'流()排序()' - 。我們都知道它不這很有意義,Tunaki詳細解釋了它。 2.我使用'reduce'的方式絕對有效。我決定改變輸入值,而不是每次都創建新的集合,因爲它們的效率很高,但是所有這些優先級隊列僅在本方法內部使用。 –

+3

也許你想讀作[文件](http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Reduction)第一和理解之間的「差異減少「和」可變減少「。對於後者,有一種專用的方法,使用「collect」來代替濫用「reduce」。你不是決定使用是否「絕對有效」的人,這取決於API設計者決定什麼是正確的用法,他們已經做到了。 – Holger