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

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

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

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

Ответы [ 30 ]

509 голосов
/ 10 октября 2008

С макушки головы я могу сократить ее на одну строку:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
470 голосов
/ 08 сентября 2013

В Java 8:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                             .collect(Collectors.toList());
257 голосов
/ 27 августа 2010

Вы можете использовать библиотеку Apache commons-collection :

List<String> newList = ListUtils.union(list1, list2);
80 голосов
/ 14 декабря 2012

Одно из ваших требований - сохранить оригинальные списки. Если вы создаете новый список и используете addAll(), вы фактически удваиваете количество ссылок на объекты в ваших списках. Это может привести к проблемам с памятью, если ваши списки очень большие.

Если вам не нужно изменять объединенный результат, вы можете избежать этого, используя собственную реализацию списка. Очевидно, что пользовательский класс реализации состоит из нескольких строк, но его использование короткое и приятное.

CompositeUnmodifiableList.java:

public class CompositeUnmodifiableList<E> extends AbstractList<E> {

    private final List<E> list1;
    private final List<E> list2;

    public CompositeUnmodifiableList(List<E> list1, List<E> list2) {
        this.list1 = list1;
        this.list2 = list2;
    }

    @Override
    public E get(int index) {
        if (index < list1.size()) {
            return list1.get(index);
        }
        return list2.get(index-list1.size());
    }

    @Override
    public int size() {
        return list1.size() + list2.size();
    }
}

Использование:

List<String> newList = new CompositeUnmodifiableList<String>(listOne,listTwo);
79 голосов
/ 10 октября 2008

Вероятно, не проще, но интригует и уродлив:

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

Не используйте его в производственном коде ...;)

64 голосов
/ 14 декабря 2012

Не проще, но без изменения размера:

List<String> newList = new ArrayList<>(listOne.size() + listTwo.size());
newList.addAll(listOne);
newList.addAll(listTwo);
54 голосов
/ 04 апреля 2014

Еще один однострочный Java 8:

List<String> newList = Stream.of(listOne, listTwo)
                             .flatMap(x -> x.stream())
                             .collect(Collectors.toList());

В качестве бонуса, поскольку Stream.of() является вариативным, вы можете объединить столько списков, сколько захотите.

List<String> newList = Stream.of(listOne, listTwo, listThree)
                             .flatMap(x -> x.stream())
                             .collect(Collectors.toList());
50 голосов
/ 29 июля 2011

Нашел этот вопрос, пытаясь объединить произвольное количество списков, не обращая внимания на внешние библиотеки. Так что, возможно, это поможет кому-то еще:

com.google.common.collect.Iterables#concat()

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

35 голосов
/ 04 декабря 2015

Вот решение Java 8 с использованием двух строк:

List<Object> newList = new ArrayList<>();
Stream.of(list1, list2).forEach(newList::addAll);

Помните, что этот метод не следует использовать, если

  • происхождение newList неизвестно и может уже использоваться другими потоками
  • поток, который изменяет newList, является параллельным потоком, и доступ к newList не синхронизирован или не безопасен для потоков

из-за побочных эффектов.

Оба вышеперечисленных условия не применяются для вышеуказанного случая объединения двух списков, поэтому это безопасно.

На основании этого ответа на другой вопрос.

30 голосов
/ 09 сентября 2013

Это просто и всего одна строка, но добавит содержимое listTwo в listOne. Вам действительно нужно поместить содержимое в третий список?

Collections.addAll(listOne, listTwo.toArray());
...