I am trying to create a map that holds an activity and the total duration of that activity, knowing that the activity appears more times with different durations.
Normally, I would have solved it like this:
Map<String,Duration> result2 = new HashMap<String,Duration>();
for(MonitoredData m: lista)
{
if(result2.containsKey(m.getActivity())) result2.replace(m.getActivity(),result2.get(m.getActivity()).plus(m.getDuration()));
else result2.put(m.getActivity(), m.getDuration());
}
But I am trying to do this with a stream, but I can't figure out how to put the sum in there.
Function<Duration, Duration> totalDuration = x -> x.plus(x);
Map<String, Duration> result2 = lista.stream().collect(
Collectors.groupingBy(MonitoredData::getActivity,
Collectors.groupingBy(totalDuration.apply(), Collectors.counting()))
);
I tried in various ways to group them, to map them directly, or to sum them directly in the brackets, but i'm stuck.
Introduction Stream map () is an intermediate operation used to apply one given function to the elements of a stream. It takes one function as its argument and applies it to each value of the stream and returns one fresh stream. In this tutorial, we will learn how to use the Java Streams map function with different examples.
An IntStream has a sum method to sum all the elements in the stream (which are primitive integers). Note: List.of method was added in Java 9 as part of the many Collection factory methods. If you are using Java 8 or less, use Arrays.asList in place of it. In the above example, calling stream returns a stream of integers ( Stream<Integer> ).
mapToDouble takes a ToDoubleFunction. The ToDoubleFunction has a single method called applyAsDouble to map an element to a primitive double. The second way by which we can sum a stream of numbers is to use the reduce method on the stream.
To calculate the sum of values of a Map<Object, Integer> data structure, first we create a stream from the values of that Map. Next we apply one of the methods we used previously. For instance, by using IntStream.sum (): Integer sum = map.values ().stream ().mapToInt (Integer::valueOf).sum ();
Use the 3-argument version of toMap
collector:
import static java.util.stream.Collectors.toMap;
Map<String,Duration> result = lista.stream()
.collect(toMap(MonitoredData::getActivity, MonitoredData::getDuration, Duration::plus));
Also, note that Map
interface got some nice additions in Java 8. One of them is merge. With that, even your iterative for loop can be rewritten to be much cleaner:
for (MonitoredData m: lista) {
result.merge(m.getActivity(), m.getDuration(), Duration::plus);
}
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