Reputation: 7581
How to combine consecutive similar objects that are in a Java Stream?
Till now I could not find a good solution, so I hope you can help.
Suppose we have a class like the following:
class Someclass {
String type;
int count;
}
When having a Stream { "a", 1 }, { "a", 2}, { "b", 4}, { "b", "5" } and that needs to be processed as { "a", 3 }, { "b", 9 }.
Combining means of course, adding the counts for the objects with the same type.
How to do?
Upvotes: 0
Views: 152
Reputation: 40034
Assume you had a list of maps as in your example.
entrySets
into a single stream.key/value
pair(a,b)->a+b
merge function to add values for duplicate keys.List<Map<String, Integer>> maps = List.of(Map.of("a", 1),
Map.of("a", 2), Map.of("b", 4), Map.of("b", 5));
Map<String, Integer> result =
maps.stream().flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey,
Entry::getValue, (a, b) -> a + b));
System.out.println(result);
Prints
{a=3, b=9}
If you had an array of objects, you could do it as follows.
The compute
method puts the value there if it isn't present, or adds to the existing one if it is present.
Object[] values = {"a",1,"b",4,"a",2,"b",5};
Map<String,Integer> map1 = new HashMap<>();
for (int i = 0; i < values.length-1; i+=2) {
Integer val = (Integer)values[i+1];
map1.compute((String)values[i], (k,v)->v == null ? val : v +val);
}
System.out.println(map1);
Upvotes: 2
Reputation: 79035
You can use Collectors.toMap
to collect the stream into the desired Map
.
Demo:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class MyType {
String type;
int count;
public MyType(String type, int count) {
this.type = type;
this.count = count;
}
public String getType() {
return type;
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
List<MyType> list = List.of(new MyType("a", 1),
new MyType("a", 2),
new MyType("b", 4),
new MyType("b", 5));
Map<String, Integer> map = list.stream()
.collect(Collectors.toMap(MyType::getType, MyType::getCount, Integer::sum));
System.out.println(map);
}
}
Output:
{a=3, b=9}
Upvotes: 2