Если у меня есть List<List<Object>>
, как я могу превратить это в List<Object>
который содержит все объекты в одном и том же порядке, используя функции Java 8?
Как включить список списков в список в Java 8?
Ответ 1
Вы можете использовать flatMap
чтобы сгладить внутренние списки (после их преобразования в потоки) в один поток, а затем собрать результат в список:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Ответ 2
flatmap
лучше, но есть и другие способы добиться того же
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
Ответ 3
Метод flatMap
в Stream
может, конечно, сгладить эти списки для вас, но он должен создать объекты Stream
для элемента, а затем Stream
для результата.
Вам не нужны все эти объекты Stream
. Вот простой и сжатый код для выполнения задачи.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Поскольку List
is Iterable
, этот код вызывает метод forEach
(функция Java 8), который унаследован от Iterable
.
Выполняет данное действие для каждого элемента
Iterable
до тех пор, пока все элементы не будут обработаны, или действие не выдает исключение. Действия выполняются в порядке итерации, если указан этот порядок.
И Iterator
List
возвращает элементы в последовательном порядке.
Для Consumer
этот код передается в ссылке метода (функция Java 8) в метод pre-Java 8 List.addAll
для добавления элементов внутреннего списка последовательно.
Добавляет все элементы в указанной коллекции в конец этого списка, в том порядке, в котором они возвращаются указанным итератором коллекции (дополнительная операция).
Ответ 4
Вы можете использовать шаблон flatCollect()
из Коллекций Eclipse.
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
Если вы не можете изменить список из List
:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
Примечание. Я участвую в коллекциях Eclipse.
Ответ 5
Так же, как @Saravana упомянул:
лучше, но есть другие способы добиться того же
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
Подводя итог, можно сделать несколько способов:
private <T> List<T> mergeOne(Stream<List<T>> listStream) {
return listStream.flatMap(List::stream).collect(toList());
}
private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
List<T> result = new ArrayList<>();
listStream.forEach(result::addAll);
return result;
}
private <T> List<T> mergeThree(Stream<List<T>> listStream) {
return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
private <T> List<T> mergeFour(Stream<List<T>> listStream) {
return listStream.reduce((l1, l2) -> {
List<T> l = new ArrayList<>(l1);
l.addAll(l2);
return l;
}).orElse(new ArrayList<>());
}
private <T> List<T> mergeFive(Stream<List<T>> listStream) {
return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}
Ответ 6
Я просто хочу объяснить еще один сценарий, такой как List<Documents>
, этот список содержит еще несколько списков других документов, таких как List<Excel>
, List<Word>
, List<PowerPoint>
. Итак, структура
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
Теперь, если вы хотите перебрать Excel только из документов, сделайте что-то вроде ниже.
Так что код будет
List<Documents> documentList = new A().getDocumentList();
//check documentList as not null
Optional<Excel> excelOptional = documentList.stream()
.map(doc -> doc.getExcel())
.flatMap(List::stream).findFirst();
if(excelOptional.isPresent()){
Excel exl = optionalExcel.get();
// now get the value what you want.
}
Я надеюсь, что это может решить проблему кого-то во время кодирования...
Ответ 7
Метод преобразования Преобразовать список списков в список: ListOfLists.stream(). FlatMap (List :: stream).collect(Collectors.toList()); Пример 1:
public class ConvertListOfListsToList {
public static void main(String[] args) {
List<String> StringList = Arrays.asList("Protijayi", "Gini", "Gina");
System.out.println(StringList);
List<List<String>> ListOfLists = new ArrayList<>();
ListOfLists.add(StringList);
System.out.println("ListOfLists => " + ListOfLists);
// Now let do this in Java 8 using FlatMap
List<String> flatMapList = ListOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("FlatList => " + flatMapList);
/*
ListOfLists => [[Protijayi, Gini, Gina]]
FlatList => [Protijayi, Gini, Gina]
*/
}
}
Ответ 8
Мы можем использовать flatmap для этого, пожалуйста, обратитесь ниже код:
List<Integer> i1= Arrays.asList(1, 2, 3, 4);
List<Integer> i2= Arrays.asList(5, 6, 7, 8);
List<List<Integer>> ii= Arrays.asList(i1, i2);
System.out.println("List<List<Integer>>"+ii);
List<Integer> flat=ii.stream().flatMap(l-> l.stream()).collect(Collectors.toList());
System.out.println("Flattened to List<Integer>"+flat);
Ответ 9
Расширение ответа Eran, которое было лучшим ответом, если у вас есть несколько слоев списков, вы можете продолжать отображать их.
Это также идет с удобным способом фильтрации, когда вы спускаетесь по слоям, если это необходимо.
Так, например:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
В SQL это похоже на использование операторов SELECT внутри операторов SELECT.