Is it possible to sum and average and transform to a new object from a stream . I have an object
public class Foo {
private String code;
private double price;
....
}
Now I want to get the average and sum this object list ( sum price by code and average price by code as well)
foos = Arrays.asList(
new Foo("MTN" , 200 ),
new Foo("MTN" , 210 ),
new Foo("MTN" , 205 ),
new Foo("OMT" , 300 ),
new Foo("OMT" , 320 ),
new Foo("OMT" , 310 ),
new Foo("AAA" , 650 ),
new Foo("AAA" , 680 ),
new Foo("AAA" , 600 ));
I would then want to create a new Object (FooB
public class FooB {
private String code;
private double total;
private double average;
....
}
This is what I have now it works but I go through the stream twice . I want a method where I can do this by going through the stream once .
Map<String, Double> averagePrices = foos.stream()
.collect(
Collectors.groupingBy(
Foo::getCode,Collectors.averagingDouble(Foo::getPrice)));
Map<String, Double> totalPrices = foos.stream()
.collect(
Collectors.groupingBy(
Foo::getCode,
Collectors.summingDouble(Foo::getPrice)));
List<FooB > fooBs = new ArrayList<>();
averagePrices.forEach((code, averageprice)-> {
FooB fooB = new FooB (code , totalPrices.get(code) , averageprice);
fooBs.add(fooB );
});
fooBs.forEach(e -> System.out.println(e.toString()));
Is there a better way of doing this without repeating this . Thanks
You could use DoubleSummaryStatistics
to hold both results before mapping to FooB
:
Map<String, DoubleSummaryStatistics> data = foos.stream()
.collect(Collectors.groupingBy(Foo::getCode,
Collectors.summarizingDouble(Foo::getPrice)));
List<FooB> fooBs = data.entrySet().stream()
.map(e -> new FooB(e.getKey(), e.getValue().getSum(), e.getValue().getAverage()))
.collect(toList());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With