Відповіді:
Ви можете використовувати 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]
:::)