2015-10-01 46 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 + ">"; 
    } 
}