I think I learning streams I have a huge case of brain fart...
I am trying to solve the following: given a list of objects, each object with multiple properties, like so:
class Data{
int prop1;
int prop2;
...
List<Data> data;//list of Data object
i am trying, in a 'one shot' like operation, to stream the list, such that the end result will be an generic object or a data object where each prop get its own sum/max/min etc. so, for example, given 2 data objects as follows:
{1,2},{3,4} if I apply max to the first prop and sum to the second the result is {3,6}
thanks for helping!
CodePudding user response:
I am trying, in a 'one shot' like operation
You are looking for the Teeing Collector introduced in Java 12. Given a list of Data, where a Data class is something like:
@AllArgsConstructor
@Getter
@ToString
public class Data {
int prop1;
int prop2;
}
and a list:
List<Data> data = List.of(
new Data(1,10),
new Data(2,20),
new Data(3,30),
new Data(4,40)
);
the end result will be an generic object or a data object
if I apply max to the first prop and sum to the second
You can use Collectors.teeing
to get a new Data object with the result of your operations
Data result =
data.stream().collect(Collectors.teeing(
Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Data::getProp1))),
Collectors.summingInt(Data::getProp2),
(optionalMax, sum) -> new Data(optionalMax.get().getProp1(), sum)
));
Or something else, for example a Map<String,Integer>
Map<String,Integer> myMap =
data.stream().collect(Collectors.teeing(
Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Data::getProp1))),
Collectors.summingInt(Data::getProp2),
(optionalMax, sum) -> {
HashMap<String, Integer> map = new HashMap();
map.put("max_prop1", optionalMax.get().getProp1());
map.put("sum_prop2", sum);
return map;
}
));
CodePudding user response:
It sounds like you're trying to retrieve some statistics from a stream of elements.
I am trying [...] to stream the list, such that the end result will be a generic object or a data object where each prop get its own sum/max/min etc.
For this purpose, there is already the IntSummaryStatistics
class which includes a set of statistics gathered from a set of int elements. To obtain this information, you just need to stream your elements and invoke the collect
operation by supplying Collectors.summarizingInt()
; this will return the statistics of your elements. Moreover, Java also provides LongSummaryStatistics
and DoubleSummaryStatistics
to retrieve statistics of long and double types.
List<Integer> list = new ArrayList<>(List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
IntSummaryStatistics stats = list.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("Count: " stats.getCount());
System.out.println("Sum: " stats.getSum());
System.out.println("Min Value: " stats.getMin());
System.out.println("Max Value: " stats.getMax());
System.out.println("Average: " stats.getAverage());
//In case Data had not been designed in place of IntSummaryStatistics and it's an actual needed class,
//then you could set up the properties you need from the IntSummaryStatistics
Data d = new Data();
d.setMinProp(stats.getMin());
d.setMaxProp(stats.getMax());
d.setSumProp(stats.getSum());
//... setting any other needed property ...
Data class
class Data {
private int minProp, maxProp, sumProp;
//... rest of the implementation ...
public void setMinProp(int minProp) {
this.minProp = minProp;
}
public void setMaxProp(int maxProp) {
this.maxProp = maxProp;
}
public void setSumProp(int sumProp) {
this.sumProp = sumProp;
}
}
Output
Count: 10
Sum: 45
Min Value: 0
Max Value: 9
Average: 4.5