Reduce a set of objects by a common field in Java-8

I have a list of objects Obdefined as

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;
    }
}

I get objects like

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

which I have to combine as

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

How can I use a thread for this. Reduces help? The stream that can be used is

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();

Updated question with Ruben solution. There is no need to remove duplicates, but this can be done using the set in Ob for the outfit. The current solution works flawlessly.

+4
source share
2 answers

You can compile toMap with a merge function that merges lists

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

groupingBy, , Ob, Ob, type.

, Rubens , . , , 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 + ">";
    }
}
+3

Source: https://habr.com/ru/post/1609832/


All Articles