Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3 ways to flatten a list of lists. Is there a reason to prefer one of them?

Tags:

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>>?

like image 825
3VYZkz7t Avatar asked Aug 18 '16 13:08

3VYZkz7t


People also ask

How do I flatten a list of lists?

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] .

How do you flatten a string list in Python?

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.


2 Answers

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()); 
like image 95
Zircon Avatar answered Sep 19 '22 11:09

Zircon


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()); 
like image 23
marstran Avatar answered Sep 21 '22 11:09

marstran