我有一个对象Ob
列表,定义为
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"]
}]
我必须合并为
[{
"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();
用Ruben解决方案更新了问题。不需要删除重复项,但可以使用Ob中的set来完成重复项。目前的解决方案运作完美。
答案 0 :(得分:3)
此解决方案使用groupingBy
收集器,然后使用单独的步骤创建新的Ob
,这是合并具有相同Ob
的所有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 + ">";
}
}
答案 1 :(得分:3)
您可以使用合并列表的合并函数收集toMap
Collection<Ob> values = coll.stream()
.collect(toMap(Ob::getType, Function.identity(), (o1, o2) -> {
o1.getAttire().addAll(o2.getAttire());
return o1;
})).values();