Basil Bourque
Basil Bourque

Reputation: 340040

Using streams to sum a collection of immutable `Duration` objects, in Java

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

Answers (3)

Jacob G.
Jacob G.

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

armani
armani

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

Naman
Naman

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

Related Questions