25

Assume we have a list as follows. CoreResult has a field of type List<Double>.

final List<CoreResult> list = new LinkedList<>(SOME_DATA);

The objective is to flatten the list after extracting that specific field from each CoreResult object. Here are 3 possible options. Is any one of them preferable to the others?

Option 1: extract a field via map() and flatten inside collector

final List<Double> A = list.stream().map(CoreResult::getField)
            .collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);

Option 2: extract a field via map(), flatten via flatMap(), simple collector

final List<Double> B = list.stream().map(CoreResult::getField)
            .flatMap(Collection::stream).collect(Collectors.toList());

Option 3: extract a field and flatten in one go via flatMap(), simple collector

final List<Double> C = list.stream().flatMap(
             x -> x.getField().stream()).collect(Collectors.toList());

Would the answer be different if there was no need to extract any field from CoreResult, and instead one wanted to simply flatten a List<List<Double>>?

3VYZkz7t
  • 448
  • 1
  • 6
  • 11
  • 2
    If you care for performance, you should not use `LinkedList`. And since `SOME_DATA` must already be a collection, there’s no sense in copying it into another `List`. So the preferred way is `SOME_DATA.stream(). /* whatever of the three options you like */`… – Holger Aug 18 '16 at 14:00

3 Answers3

36

I'm not sure about the performance of each one, but an important aspect of the builder pattern utilized by java streams is that it allows for readability. I personally find the option 2 to be the most readable. Option 3 is good, too. I would avoid option one because it kind of "cheats" the flattening of the collection.

Put each method on its own line and determine which is the most intuitive to read. I rather like the second one:

final List<Double> B = list.stream()
                           .map(CoreResult::getField)
                           .flatMap(Collection::stream)
                           .collect(Collectors.toList());
Zircon
  • 4,677
  • 15
  • 32
  • 1
    I am getting "not-static method cannot be referenced from a static context" compilation error on .flatMap(List::stream) line – RoyalTiger Jul 30 '19 at 04:25
8

I would go for option 2 or 3. If you want to flatten a List<List<Double>>, you would do this:

List<Double> list = doubleList.stream()
                              .flatMap(List::stream)
                              .collect(Collectors.toList());
marstran
  • 26,413
  • 5
  • 61
  • 67
0

Option 3 and 2 is same, so up to you if you want to map first and then flat map or just flatmap.

With option 1 you have to open another stream to perform further operations.

ByeBye
  • 6,650
  • 5
  • 30
  • 63