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>>
?
Flattening a list of lists entails converting a 2D list into a 1D list by un-nesting each list item stored in the list of lists - i.e., converting [[1, 2, 3], [4, 5, 6], [7, 8, 9]] into [1, 2, 3, 4, 5, 6, 7, 8, 9] .
Flatten List using the reduce() Function of functools Module. The first argument to the reduce() function is a function itself with two arguments, and the second argument is a list. Argument function is applied cumulatively to elements in the list.
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());
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());
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