Java 8 - How to sum an entire list item on a list map

I have a list map of a specific object, and I want to add all list items based on a specific instance variable.

My object:

class Risk{ Integer id, riskValue, totRisk=0; String name; Integer getId(){ return id; } Risk(Object[] result){ id=(Integer)result[0]; riskValue=(Integer)result[1]; name=(String)result[3]; } } 

I get from the database a list of arrays of an object of type:

 List< Object[] > results=getResults(); 

I use Java 8 to group my data by ID, because I want SUM on riskValue all objects of type Risk with the same id .

This is what I do:

 List<Risk> risks=results.stream().map(Risk::new).collect(Collectors.toList()); Map<Integer, List<Risk>> byId=risks.stream.collect(Collectors.groupingBy(Risk::getId)); 

At this point, I have all the risk objects grouped by ID. And I want each list to summarize all riskValue objects and have a total number in the totRisk variable

How to calculate the total number of riskValue variables in each list in the riskValue variable?

Note1: I want to do this using Java 8, I know how to do it using Java 7 and below.

Note2: It may also be possible to do this at a time without having the first group by identifier. What I want to achieve is to sum all the objects with the same identifier in the original List<Object[]> results . If this can be done with just one statement, even better.

+5
source share
1 answer

You must know that you can combine Collector s. See Collectors.groupingBy(Function,Collector)

 Map<Integer, Integer> byId=risks.stream.collect( Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue))); 

You can also combine it with the first operation:

 Map<Integer, Integer> byId=results.stream().map(Risk::new).collect( Collectors.groupingBy(Risk::getId, Collectors.summingInt(Risk::getRiskValue))); 

Note that I assume that you have the getRiskValue() method in your Risk class, otherwise you need to replace Risk::getRiskValue lambda expression r -> r.riskValue to access the field, however, it is always recommended to use getter methods.

Result displays from id to total.


After reviewing the question again, I noticed that you really want to summarize riskValue and store it in totRisk for each (?) Risk instance. This is a bit more complicated as it does not fit the general usage pattern:

 Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect( Collectors.groupingBy(Risk::getId, Collectors.collectingAndThen( Collectors.toList(), l-> { int total=l.stream().collect(Collectors.summingInt(r -> r.riskValue)); l.forEach(r->r.totRisk=total); return l; }))); 

at this point, we really need to switch to using import static java.util.stream.Collectors.*; :

 Map<Integer, List<Risk>> byId=results.stream().map(Risk::new).collect( groupingBy(Risk::getId, collectingAndThen(toList(), l-> { int total=l.stream().collect(summingInt(r -> r.riskValue)); l.forEach(r->r.totRisk=total); return l; }))); 
+7
source

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


All Articles