Reputation: 340040
The java.time.Duration
class built into Java 8 and later represents a span of time unattached to the timeline on the scale of hour-minutes-seconds. The class offers a plus
method to sum two such spans of time.
The java.time classes use immutable objects. So the Duration::plus
method returns a new third Duration
object as a result rather than altering (mutating) either of the input objects.
The conventional syntax to sum a collection of Duration
objects would be the following.
Duration total = Duration.ZERO;
for ( Duration duration : durations )
{
total = total.plus( duration );
}
Can streams be used in place of this for
loop?
Upvotes: 7
Views: 1864
Reputation: 29720
Stream#reduce
This can be achieved using the overloaded Stream#reduce
method that accepts an identity:
durations.stream().reduce(Duration.ZERO, Duration::plus)
The following snippet provides an example:
var durations = List.of(Duration.ofDays(1), Duration.ofHours(1));
System.out.println(durations.stream().reduce(Duration.ZERO, Duration::plus));
As expected, the output is:
PT25H
Upvotes: 13
Reputation: 156
Here is a fully working example with sample inputs. You need to use the reduce function in java streams. Here is a short tutorial that I used.
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class DurationTest {
public static void main(String [] args){
List<Duration> durations = IntStream
.rangeClosed(1, 10)
.mapToObj( n -> Duration.ofSeconds(n) )
.collect(Collectors.toList());
int sumOfSeconds = (10 * (1 + 10) ) / 2;
Duration total = durations.stream().reduce( Duration.ZERO, (t, d) -> t = t.plus(d) );
System.out.printf("actual = %s, expected = %s", total.getSeconds(), sumOfSeconds);
}
}
Upvotes: 2
Reputation: 32036
Yes, you can make use of reduce
operation with identity element as
Duration total = durations.stream()
.reduce(Duration.ZERO, Duration::plus);
Upvotes: 8