Как мне объединить два списка в Java? - PullRequest
641 голосов
/ 10 октября 2008

Условия: не изменять исходные списки; Только JDK, без внешних библиотек. Бонусные баллы за однострочную версию или версию JDK 1.3.

Есть ли более простой способ, чем:

List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);

Ответы [ 30 ]

25 голосов
/ 23 мая 2016

Предлагаемое решение предназначено для трех списков, хотя его можно применять и для двух списков. В Java 8 мы можем использовать Stream.of или Stream.concat как:

List<String> result1 = Stream.concat(Stream.concat(list1.stream(),list2.stream()),list3.stream()).collect(Collectors.toList());
List<String> result2 = Stream.of(list1,list2,list3).flatMap(Collection::stream).collect(Collectors.toList());

Stream.concat принимает два потока в качестве входных данных и создает ленивый каскадный поток, элементами которого являются все элементы первого потока, за которыми следуют все элементы второго потока. Поскольку у нас есть три списка, мы использовали этот метод (Stream.concat) два раза.

Мы также можем написать служебный класс с методом, который принимает любое количество списков (используя varargs ) и возвращает объединенный список в виде:

public static <T> List<T> concatenateLists(List<T>... collections) {
        return Arrays.stream(collections).flatMap(Collection::stream).collect(Collectors.toList()); 
}

Тогда мы можем использовать этот метод как:

List<String> result3 = Utils.concatenateLists(list1,list2,list3);
24 голосов
/ 10 октября 2008

Чуть проще:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
20 голосов
/ 10 октября 2008

Немного короче будет:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
13 голосов
/ 10 октября 2008

Вы можете сделать oneliner, если целевой список предварительно объявлен.

(newList = new ArrayList<String>(list1)).addAll(list2);
9 голосов
/ 18 мая 2018

Вы можете создать свой универсальный Java 8 служебный метод для объединения любого количества списков .

@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
    return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}
8 голосов
/ 12 ноября 2016

еще одно линейное решение с использованием потока Java8, поскольку flatMap решение уже опубликовано, вот решение без flatMap

List<E> li = lol.stream().collect(ArrayList::new, List::addAll, List::addAll);

или

List<E> ints = Stream.of(list1, list2).collect(ArrayList::new, List::addAll, List::addAll);

код

    List<List<Integer>> lol = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
    List<Integer> li = lol.stream().collect(ArrayList::new, List::addAll, List::addAll);
    System.out.println(lol);
    System.out.println(li);

выход

[[1, 2, 3], [4, 5, 6]]
[1, 2, 3, 4, 5, 6]
7 голосов
/ 24 марта 2017

В Java 8 (наоборот):

List<?> newList = 
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());
6 голосов
/ 26 июля 2012

Самый умный на мой взгляд:

/**
 * @param smallLists
 * @return one big list containing all elements of the small ones, in the same order.
 */
public static <E> List<E> concatenate (final List<E> ... smallLists)
{
    final ArrayList<E> bigList = new ArrayList<E>();
    for (final List<E> list: smallLists)
    {
        bigList.addAll(list);
    }
    return bigList;
}
5 голосов
/ 29 ноября 2016

Java 8 версия с поддержкой соединения по ключу объекта:

public List<SomeClass> mergeLists(final List<SomeClass> left, final List<SomeClass> right, String primaryKey) {
    final Map<Object, SomeClass> mergedList = new LinkedHashMap<>();

    Stream.concat(left.stream(), right.stream())
        .map(someObject -> new Pair<Object, SomeClass>(someObject.getSomeKey(), someObject))
        .forEach(pair-> mergedList.put(pair.getKey(), pair.getValue()));

    return new ArrayList<>(mergedList.values());
}
5 голосов
/ 10 октября 2008

Вы можете сделать это с помощью статического импорта и вспомогательного класса

nb обобщение этого класса, вероятно, может быть улучшено

public class Lists {

   private Lists() { } // can't be instantiated

   public static List<T> join(List<T>... lists) {
      List<T> result = new ArrayList<T>();
      for(List<T> list : lists) {
         result.addAll(list);
      }
      return results;
   }

}

Тогда вы можете делать такие вещи, как

import static Lists.join;
List<T> result = join(list1, list2, list3, list4);
...