2015-10-01 49 views
4

我定義爲減少公共字段對象的集合中的Java-8

class Ob { 
    private String type; 
    private List<String> attire; 
    // standard getter and setters 

    public Ob (String type){ 
     this.type=type; 
    } 

    public Ob addAttrire(String att){ 
     if(attire == null){ 
      attire = new ArrayList<>(); 
     } 
     attire.add(att); 
     return this; 
    } 
} 

我接收對象爲

[{ 
"type" : "upper" 
attires : [{"t1","t2"}] 
}, 
{ 
"type" : "upper" 
attires : ["t3","t4"] 
}, 
{ 
"type" : "lower" 
attires : ["l1","l2"] 
}] 

對象Ob的名單,我必須爲

結合
[{ 
"type" : "upper" 
attires : ["t1","t2","t3","t4"] 
},{ 
"type" : "lower" 
attires : ["l1","l2"] 
}] 

如何使用流來做到這一點。是否減少幫助? 一個可以使用的流是

List<Ob> coll = new ArrayList<>(); 


coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 



Collection<Ob> values = coll.stream() 
       .collect(toMap(Ob::getType, Function.identity(), (o1, o2) -> { 
        o1.getAttire().addAll(o2.getAttire()); 
        return o1; 
       })).values(); 

更新與魯的溶液的問題。沒有要求刪除重複項,但可以使用Ob中的set for set裝完成。目前的解決方案完美無缺。

+0

關於魯本斯回答您的評論是合併函數「*什麼在這樣的情況下,性能的影響*推薦的方式」:我認爲在運行時性能沒有太大的區別。如果性能在這裏成爲一個問題,我認爲最好用循環重寫代碼,這會給你更多的控制權。我認爲魯本斯解決方案具有優勢,因爲它更短,更簡單。我認爲我有一個優勢,因爲它不會修改原來的「Ob」,因此更具有功能風格。 – Lii

回答

3

你可以收集toMap與合併列表

Collection<Ob> values = coll.stream() 
    .collect(toMap(Ob::getType, Function.identity(), (o1, o2) -> { 
     o1.getAttire().addAll(o2.getAttire()); 
     return o1; 
    })).values(); 
+0

這不會刪除重複的裝飾字符串,它會返回一個由'toMap'中'HashMap'實例支持的集合,所以我認爲它不會回答這個問題。否則它很聰明! – Lii

+1

@Lii刪除重複項可能是_rohit_想要的,但在問題中無法看到,所以我已經將其刪除。該代碼不會返回'HashMap',而是'Collection'(參見末尾的'.values()')。 – Ruben

+0

哦,實際上沒有關於刪除問題中的重複內容!我似乎早先誤解了這個例子,對此感到遺憾。關於集合,我的意思是'values'方法返回一個由'toMap'創建的映射*支持的集合。 – Lii

3

該解決方案使用的groupingBy集電極,然後,創建一個新的Ob彙集所有的Ob s表示具有相同type的結果的單獨步驟。

我認爲魯本斯解決方案比這個答案有優勢,因爲它有點短而且簡單。我認爲這個答案有一個優勢,因爲它不會修改原來的Ob,因此更具有功能性。

public static void testTrickyStreamSet() { 
    Stream<Ob> s = Stream.of(
     new Ob("a", "1", "2"), 
     new Ob("b", "1", "4"), 
     new Ob("a", "1", "3"), 
     new Ob("b", "1", "5")); 

    List<Ob> os = s.collect(groupingBy(o -> o.type)) 
     .entrySet().stream() 
     .map(e -> new Ob(e.getKey(), 
      e.getValue().stream().flatMap(o -> o.attire.stream()).collect(toList()))) 
     .collect(toList()); 

    // Prints [<Ob type=a, attire=[1, 2, 3]>, <Ob type=b, attire=[1, 4, 5]>] 
    System.out.println(os); 
} 

public static class Ob { 
    public String type; 
    public List<String> attire; 

    public Ob(String type, String... attire) { 
     this.type = type; 
     this.attire = Arrays.asList(attire); 
    } 

    public Ob(String type, List<String> attire) { 
     this.type = type; 
     this.attire = new ArrayList<>(attire); 
    } 

    @Override 
    public String toString() { 
     return "<Ob type=" + type + ", attire=" + attire + ">"; 
    } 
}