How can I turn a List of Lists into a List in Java 8?
You can use flatMap
to flatten the internal lists (after converting them to Streams) into a single Stream, and then collect the result into a list:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
How to convert List of Lists to single List using Java8 streams
Use flatMap
here, to not stream again. Just notice that this toMap
assumes that there will be no duplicate keys (or nulls)
list.stream()
.filter(e -> subjectId.equals(e.getId()))
.flatMap(subject -> subject.getTopics().stream())
.collect(Collectors.toMap(Topic::getId, Topic::getName));
How to change a list of lists into a list
public List<LocalDateTime> getallsort(){
List<LocalDateTime> elite = getElite(true);
List<LocalDateTime> recreation = getRecreation(true);
List<LocalDateTime> youth = getYouth(true);
List<List<LocalDateTime>> list = Arrays.asList(elite,recreation,youth);
list.sort((xs1, xs2) -> xs1.size() - xs2.size());
return list.stream().flatMap(List::stream).collect(Collectors.toList());
}
which answers your original question about converting a List<List<>>
into a flattened List<>
.
Or even
public List<LocalDateTime> getallsort(){
return Stream.of(
getElite(true),
getRecreation(true),
getYouth(true)
)
.sorted((xs1, xs2) -> xs1.size() - xs2.size())
.flatMap(List::stream)
.collect(Collectors.toList());
}
which works for your original example, but maybe does not directly answer your question.
Rewriting the sort:
public List<LocalDateTime> getallsort(){
return Stream.of(
getElite(true),
getRecreation(true),
getYouth(true)
)
.sorted(comparingInt(List::size).reversed())
.flatMap(List::stream)
.collect(Collectors.toList());
}
Java 8: How to stream a list into a list of lists?
As mentioned in a comment, referring to a question that is very similar (in fact, I nearly considered it to be a duplicate...), the groupBy
call comes in different flavors, and one of them allows passing in a factory for the map that is to be created.
So there is no need to explicitly wrap the result of the "simple" groupBy
call into the creation of a new TreeMap
, because you can create the TreeMap
directly. This map (and its values()
collection!) will be ordered by the key. The values of the map are lists, which are created using the downstream collector toList()
, which explicitly says that it will collect the results in encounter order.
So the following should indeed be a simple, correct and efficient solution:
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class CollectToListOfList {
static class Widget {
String code;
String name;
Widget(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
@Override
public String toString() {
return code + ": " + name;
}
}
public static void main(String[] args) {
List<Widget> widgetList = Arrays.asList(
new Widget("0", "A"),
new Widget("1", "B"),
new Widget("2", "C"),
new Widget("3", "D"),
new Widget("0", "E"),
new Widget("1", "F"),
new Widget("2", "G"),
new Widget("3", "H"),
new Widget("0", "I"),
new Widget("1", "J"));
Collection<List<Widget>> result = widgetList.stream()
.collect(Collectors.groupingBy(Widget::getCode, TreeMap::new, Collectors.toList()))
.values();
for (List<Widget> list : result) {
System.out.println(list);
}
}
}
Convert List of List into list in java
Try like this using flatMap
:
List<List<Object>> list =
List<Object> lst = list.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
List of lists and Java 8
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
would work if you didn't use flatMap
(since addAll
requires a Collection
, but flatMap
transforms your Stream<List<P>>
to a Stream<P>
.
This would work:
rList.stream().map(R::getP).forEach(result::addAll);
With flatMap
it should be:
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::add);
That said, the correct way is to use collect
:
List<P> result = rList.stream()
.map(R::getP)
.flatMap(List::stream)
.collect(Collectors.toList());
or
List<P> result = rList.stream()
.flatMap(r -> r.getP().stream())
.collect(Collectors.toList());
Java 8: How to turn a list into a list of lists using lambda
Try this approach:
static <T> List<List<T>> listSplitter(List<T> incoming, int size) {
// add validation if needed
return incoming.stream()
.collect(Collector.of(
ArrayList::new,
(accumulator, item) -> {
if(accumulator.isEmpty()) {
accumulator.add(new ArrayList<>(singletonList(item)));
} else {
List<T> last = accumulator.get(accumulator.size() - 1);
if(last.size() == size) {
accumulator.add(new ArrayList<>(singletonList(item)));
} else {
last.add(item);
}
}
},
(li1, li2) -> {
li1.addAll(li2);
return li1;
}
));
}
System.out.println(
listSplitter(
Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
4
)
);
Also note that this code could be optimized, instead of:
new ArrayList<>(Collections.singletonList(item))
use this one:
List<List<T>> newList = new ArrayList<>(size);
newList.add(item);
return newList;
Flattening a List of List to a List with Java 8 stream API
You require only a "simple" map
here:
List<List<String>> listOfListValues;
public List<String> getAsFlattenedList() {
return listOfListValues.stream()
.map(String::valueOf)
.collect(toList());
}
flatMap
is rather used to transform one Stream
to another, which makes sense if you need more entries or less then currently available (or just a newly mapped Stream
to filter/map/etc it further down), e.g.:
count all the unique strings of all lists:
listOfListValues.stream()
.flatMap(List::stream) // we want to count all, also those from the "inner" list...
.distinct()
.count()truncate entries after a certain size:
listOfListValues.stream()
.flatMap(list -> {
if (list.size() > 3) // in this case we use only some of the entries
return Stream.concat(list.subList(0, 2).stream(), Stream.of("..."));
else
return list.stream();
})
.collect(Collectors.toList());flattening values of a map for several interested keys:
Map<Key, List<Value>> map = new HashMap<>();
Stream<Value> valueStream = interestedKeys.stream()
.map(map::get)
.flatMap(List::stream);
Java Streams and List of List of List
You should use flatMap
:
List<String> newList =
listA.stream() // Stream<A>
.flatMap(a->a.getB().stream()) // Stream<B>
.flatMap(b->b.getC().stream()) // Stream<C>
.flatMap(c->c.gtPeople().stream()) // Stream<String>
.collect(Collectors.toList()); // List<String>
3 ways to flatten a list of lists. Is there a reason to prefer one of them?
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());
Related Topics
What Are the Rules For Evaluation Order in Java
Resultset Exception - Before Start of Result Set
Jtextfields on Top of Active Drawing on Jpanel, Threading Problems
How to Set the Environment Variables For Java in Windows
What's Wrong With Using == to Compare Floats in Java
Including Dependencies in a Jar With Maven
Difference Between Final and Effectively Final
How to Get X and Y Index of Element Inside Gridlayout
How to Split a String With Any Whitespace Chars as Delimiters
System.Currenttimemillis VS System.Nanotime
Why Can't I Do Assignment Outside a Method
Difference Between Wait() and Sleep()
Why Are Arrays Covariant But Generics Are Invariant
Close a Scanner Linked to System.In
Why Does the Foreach Statement Not Change the Element Value
How to Assert That a Certain Exception Is Thrown in Junit Tests