Java 8: объединить списки с потоковым API


80

У меня следующая ситуация

Map<Key, ListContainer> map; 

public class ListContainer{
  List<AClass> lst;
}

Я должен объединить все списки lstиз ListContainerобъектов из Mapкарты.

public static void main(String args[]){
   List<AClass> alltheObjectsAClass = map.values().stream(). // continue....    
}

Есть идеи, как с помощью потокового API Java 8?


Вы можете привести пример того, что вы имеете в виду под слиянием? Скажем, ваша карта: {a: [1,2], b[3,4]}вы хотите объединить их в цепочку [1,2,3,4], поставить лайк или составить список списков [[1,2],[3,4]], или заархивировать их [[1,3],[2,4]]? Кроме того, вы знаете, что на карте нет порядка, не так ли?
tobias_k

@tobias_k Я хочу, чтобы результат был [1,2,3,4]несортированным!
mat_boy

Если ListContainerтолько оборачивает, List<T>то вы можете заменить Map<Key, ListContainer>наMap<Key, List<T>>
ThePyroEagle

Ответы:


169

Я думаю, flatMap()это то, что вы ищете.

Например:

 List<AClass> allTheObjects = map.values()
         .stream()
         .flatMap(listContainer -> listContainer.lst.stream())
         .collect(Collectors.toList());

2
? Почему были удалены комментарии, объясняющие, почему .flatMap(Collection::stream)здесь невозможно?
Puce

@Puce - хороший вопрос, но вполне возможно: если ListContainerон инкапсулирован (т.е. имеет геттер для lst), вы можете разложить его .flatMap(->)на.map(ListContainer::getLst) .flatMap(Collection::stream)
TWiStErRob

3
@TWiStErRob Да, это то, что я написал в своем первоначальном комментарии. Почему его удалили?
Puce

@Puce примечание в своем ответе, объясняющее, почему .flatMap(Collection::stream)это невозможно, было бы лучше, я думаю. Должен быть более постоянным.
SQB

1
@Alex да, это в одну сторону соответственно. .map(listContainer -> listContainer.lst).filter(Objects::nonNull).flatMap(Collection::stream)
Puce


2

В Java 8 мы можем использовать поток List1.stream (). Collect (Collectors.toList ()). AddAll (List2); Другой вариант List1.addAll (List2)


1

Уже ответил выше, но вот другой подход, который вы можете использовать. Я не могу найти исходный пост, из которого я адаптировал его, но вот код для вашего вопроса. Как отмечалось выше, функция flatMap () - это то, что вы хотели бы использовать с Java 8. Вы можете добавить ее в служебный класс и просто вызвать "RandomUtils.combine (list1, list2, ...);" и вы получите единый список со всеми значениями. Просто будьте осторожны с подстановочным знаком - вы можете изменить его, если хотите менее общий метод. Вы также можете изменить его для наборов - вам просто нужно позаботиться об использовании flatMap () для наборов, чтобы избежать потери данных из методов equals / hashCode из-за природы интерфейса Set.

  /**
    * Combines multiple lists into a single list containing all elements of
    * every list.
    * 
    * @param <T> - The type of the lists.
    * @param lists - The group of List implementations to combine
    * @return a single List<?> containing all elements of the passed in lists.
    */
   public static <T> List<?> combine(final List<?>... lists) {
      return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
   }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.