Search code examples
javajava-stream

java Group by color and Summing all Properties to produce a map


There is list of widgets i want to group them by color while adding other similar properties and produce a map , something like this .

        class Widget {
            String colour;
            Double legs;
            Double arms;
          
        }
        
        List<Widget> widList = new ArrayList();
        Widget wid1 =  new Widget();
        wid1.setColor("Yello");
        wid1.setLeg(10);
        wid1.setArms(10);
        
        Widget wid2 =  new Widget();
        wid2.setColor("Yello");
        wid2.setLeg(20);
        wid2.setArms(30);
        
        Widget wid2 =  new Widget();
        wid2.setColor("White");
        wid2.setLeg(20);
        wid2.setArms(30);
        
        
        widgets.stream().collect(groupingBy(Widget::getColour, AllLegstotal(wid1.legs+wid2.legs) and AllArmstotal(wid1.arms+wid2.arms));
        
        

result should be

"Yello" : Legs(10+20) , Arms(10+30) "White" : Legs(20) , Arms(30)

        widgets.stream().collect(groupingBy(Widget::getColour, Collectors.summingDouble(All Legs , All Arms));

Solution

  • You can achieve this by using the toMap collector.

    toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) Returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements.

    Map<String, Widget> result = widgets.stream().collect(
            Collectors.toMap(
                Widget::getColor, // keyMapper
                Function.identity(), // valueMapper
                    (w1, w2) -> new Widget( // mergeFunction
                            w1.getColor(),
                            w1.getLegs() + w2.getLegs(),
                            w1.getArms() + w2.getArms()
                    )
            )
    );
    

    The mergeFunction is a BinaryOperator that is used to combine the values of two elements with the same key.
    The example above creates a new Widget object with the same color, but with the total number of legs and arms calculated as the sum of legs and arms of w1 and w2.

    To print out the result:

    result.forEach((key, value) ->
                System.out.printf("\"%s\": Legs(%.0f), Arms(%.0f)%n", key, value.getLegs(), value.getArms()));
    

    Result: "White": Legs(20), Arms(30) "Yellow": Legs(30), Arms(40)