Java 8 Streams - collect multiple Integer fields from list of objects

Viewed 574

For example I have a class:

public class Period {
    private Integer from;
    private Integer to;
}

And there is a list of objects in JSON format:

[
    {
        "from": 1,
        "to": 2
    }, {
        "from": 3,
        "to": 4
    }, {
        "from": 5,
        "to": 6
    }
]

I want to collect from the List<Period> periods, all of the values from this two fields into one collection. In my case it would be List<Integer> values. Is there any possibility to use stream on periods list? I was trying to make something like this:

values = periods
            .stream()
            .mapToInt(p -> p.getFrom())
            .boxed()
            .collect(Collectors.toList());
values.addAll(
     periods
        .stream()
        .mapToInt(p -> p.getTo())
        .boxed()
        .collect(Collectors.toList()));

The result of this operation on previous JSON is:

[1,2,3,4,5,6]

Is there any any other option to manipulate over stream to accomplish the same result?

3 Answers

You can do that this way:

List<Integer> list = periods.stream()
        .flatMap(m -> Stream.of(m.getFrom(), m.getTo()))
        .collect(Collectors.toList());

Stream over the periods, for each item create a new stream of both attributes, and flatten them.

periods.stream()
    .flatMap(p -> Stream.of(p.getTo(), p.getFrom()))
    .collect(Collectors.toList());

The output of the code in your question is [1, 3, 5, 2, 4, 6] (instead of [1, 2, 3, 4, 5, 6]).

If you want that output, here's a way without using Stream.flatMap:

List<Integer> values = Stream.concat(
        periods.stream().map(Period::getFrom),
        periods.stream().map(Period::getTo))
    .collect(Collectors.toList());

If you want to intermix from and to values, then the other answers should work.

As pointed out in the comments, there's no need to use Stream.mapToInt followed by Stream.boxed, as this unboxes and boxes integer values unnecessarily.

Related