Відповіді:
Ви можете використовувати flatMap
для вирівнювання внутрішніх списків (після перетворення їх у потоки) в один потік, а потім збирати результат у список:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Class::method
спочатку відчуваєш себе трохи дивно, але має перевагу те, що він оголошує, з якого об’єкта ви збираєтесь. Це те, що ви інакше втрачаєте в потоках.
flatMap
Метод на , Stream
безумовно , може придавити ці списки для вас, але він повинен створювати Stream
об'єкти для елемента, то Stream
для результату.
Вам не потрібні всі ці Stream
об’єкти. Ось простий, стислий код для виконання завдання.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Так як List
це Iterable
, цей код викликає в forEach
метод (Java 8 функцій), який успадковується від Iterable
.
Виконує задану дію для кожного елемента до тих
Iterable
пір, поки всі елементи не будуть оброблені або дія не кине виняток. Дії виконуються в порядку ітерації, якщо вказаний порядок.
І А List
«S Iterator
повертає елементи в послідовному порядку.
Для цього Consumer
цей код передається у посиланні на метод (функція Java 8) до методу попередньо Java 8, List.addAll
щоб послідовно додавати внутрішні елементи списку.
Додає всі елементи вказаної колекції до кінця цього списку в порядку, коли вони повертаються вказаним ітератором колекції (необов'язкова операція).
Ви можете використовувати 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.
Так само, як згадував @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);
}
Я просто хочу пояснити ще один сценарій , як 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.
}
Я сподіваюся, що це може вирішити чиюсь проблему під час кодування ...
Для цього ми можемо використовувати плоску карту, зверніться до коду нижче:
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);
Розширення відповіді Ерана, яка була найвищою відповіддю, якщо у вас є купа шарів списків, ви можете продовжувати їх налагодження.
Це також поставляється із зручним способом фільтрації, коли ви також спускаєтесь по шарах, якщо потрібно.
Так, наприклад:
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.
Спосіб перетворення List<List>
на List
:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
Дивіться цей приклад:
public class Example {
public static void main(String[] args) {
List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("listOfLists => " + listOfLists);
System.out.println("list => " + list);
}
}
Він друкує:
listOfLists => [[a, b, c]]
list => [a, b, c]
::
:)