Условия: не изменяйте исходные списки; Только JDK, без внешних библиотек. Бонусные баллы за однострочную версию или версию JDK 1.3.
Есть ли способ попроще, чем:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
Решение Java 8 с служебным методом: stackoverflow.com/a/37386846/1216775




Чуть проще:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
Будет ли это вызывать дублирование строк? Значит, строка, которая существует в обоих списках, будет существовать дважды в результирующем списке?
@Zainodis Да, дубликаты могут быть. Структура List не накладывает ограничений на уникальность. Вы можете удалить дубли, проделав то же самое с наборами. Set<String> newSet = new HashSet<>(setOne); newSet.addAll(setTwo);
С макушки я могу сократить его на одну строчку:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
Хотя вы технически правы, вы сократили его на одну строчку, асимметрия этого меня беспокоит. Достаточно, чтобы я с удовольствием «потратил» лишнюю строчку.
Разве здесь не проблема, когда внутренний массив newList будет инициализирован размером listOne, а затем должен потенциально расширяться при добавлении всех элементов из listTwo? Было бы лучше взять размер каждого списка и использовать его для определения размера нового массива?
Это было решение, которое лучше всего сработало для меня. Я провел сравнение производительности различных решений, и оно оказалось победителем, вместе с созданием пустого списка, а затем addAll() обоих. Я перепробовал все те, которые предлагают не копировать списки, и в результате возникают большие накладные расходы, которые нам не понадобились на этот раз.
Используйте LinkedList вместо ArrayList для эффективного добавления. stackoverflow.com/a/322742/311420
Чуть короче было бы:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
Наверное, не проще, но интригующе и некрасиво:
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
Не используйте его в производственном коде ...;)
Безответственное использование анонимного класса. Как сказал OPP - не используйте его в производственном коде.
Уродливый и злой, как почти любое использование инициализации двойных скобок. Хотя короче;)
+1, приятно. Хотя Eclipse для меня разбивает более шести строк и сообщает мне @SuppressWarnings("serial"). :-)
@MarnixKlooster: Eclipse знает, что вы не должны его использовать, и это делает его использование неприятным ;-)
который известен как «объект двойной скобки», который очень удобен в тестовом коде junit для создания объекта, который возвращает заданное значение, поскольку вы можете сразу вызвать защищенный установщик и передать некоторую последнюю ссылку на тестовые данные. затем снова с хорошей фреймворком для насмешек ...
Хотя физически это одна строка, я не считаю это однострочным.
почему люди ненавидят инициализаторы анонимных блоков
@NimChimpsky Я думаю, это в основном потому, что это не просто инициализатор анонимного блока, а вы фактически создаете анонимный подкласс ArrayList. При этом, если вы доверяете результатам этого Вопрос инициализации двойной скобки, создается впечатление, что ненависть к DBI - это в основном вопрос стилистического вкуса и микрооптимизации. Насколько я могу судить, за это нет серьезных штрафов. Подлый недостаток будет, если вы когда-нибудь попытаетесь сравнить его класс, потому что это не будет ArrayList.
@MarnixKlooster не говорит вам добавлять предупреждения о подавлении, он сообщает вам, что что-то не так с кодом, и, конечно же, «если вы установите уровень журнала на FATAL, вы не получите сообщения DEBUG»
Как использование инициализации двойной скобки делает его однострочным?
@NimChimpsky еще одна причина, по которой инициализаторы анонимных блоков могут быть злом, заключается в том, что они будут пропускать внешний экземпляр объекта так же, как любой анонимный класс в Java. Однако использование в статических методах должно быть безопасным.
@NimChimpsky Вы можете ознакомиться с этой статьей о недостатках инициализации двойных скобок: Не будь «умным»: анти-узор с двойными фигурными скобками
Вы можете сделать однострочник, если целевой список заранее объявлен.
(newList = new ArrayList<String>(list1)).addAll(list2);
Вы можете сделать это с помощью статического импорта и вспомогательного класса
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);
Каким образом актуален статический импорт или вспомогательный класс?
Я не могу улучшить двухстрочный интерфейс в общем случае, не вводя ваш собственный служебный метод, но если у вас есть списки строк, и вы готовы предположить, что эти строки не содержат запятых, вы можете вытащить этот длинный -лайнер:
List<String> newList = new ArrayList<String>(Arrays.asList((listOne.toString().subString(1, listOne.length() - 1) + ", " + listTwo.toString().subString(1, listTwo.length() - 1)).split(", ")));
Если вы откажетесь от дженериков, они должны быть совместимы с JDK 1.4 (хотя я этого не тестировал). Также не рекомендуется для производственного кода ;-)
Это отвратительная строчка кода. Вероятно, более высокая производительность, чем все другие решения (вместе взятые), делает массу предположений, которые вам действительно не нужно делать, на самом деле не однострочный (вы можете поместить всю программу в одну строку технически).
@ luk2302 Однако не содержит точек с запятой (кроме конца), поэтому его можно рассматривать как однострочное.
о, боже, а что, если в элементах списка есть запятая?
Я не утверждаю, что это просто, но вы упомянули бонус за однострочники ;-)
Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] {
new Vector(list1).elements(),
new Vector(list2).elements(),
...
}))
почему кто-то никогда не должен их использовать?
@David, потому что он предназначен для внутреннего использования в JDK. Если вы использовали это в своем коде, ваш код, скорее всего, не будет работать не на Sun (или не на Oracle сейчас) JDK / JRE.
@AdrianShum Существуют ли другие JDK / JRE, кроме Oracle? Это бы меня удивило. Даже если ограничиться наиболее распространенной функциональностью API, восстановление всего этого, вероятно, займет много времени ...
JVM довольно много. Чаще всего в корпоративном мире используется IBM, который, iirc, связан с websphere.
всякий раз, когда вы видите использование Vector, сделайте 5-минутный перерыв.
Используйте вспомогательный класс.
Я предлагаю:
public static <E> Collection<E> addAll(Collection<E> dest, Collection<? extends E>... src) {
for(Collection<? extends E> c : src) {
dest.addAll(c);
}
return dest;
}
public static void main(String[] args) {
System.out.println(addAll(new ArrayList<Object>(), Arrays.asList(1,2,3), Arrays.asList("a", "b", "c")));
// does not compile
// System.out.println(addAll(new ArrayList<Integer>(), Arrays.asList(1,2,3), Arrays.asList("a", "b", "c")));
System.out.println(addAll(new ArrayList<Integer>(), Arrays.asList(1,2,3), Arrays.asList(4, 5, 6)));
}
Вы можете использовать библиотеку Коллекции общего пользования Apache:
List<String> newList = ListUtils.union(list1, list2);
Красиво, но требует общих ресурсов Apache. Он не указал «никаких внешних библиотек»
@ Quantum7, все еще полезно для других;) Кроме того, apache commons даже внешняя библиотека? Я без него ничего не запускаю!
@Platinum Нет, согласно документации ListUtils.union в точности эквивалентен коду OP. Но, возможно, использование операции SET («Объединение») в контексте списка ошибочно. Я вижу, как вы могли ожидать, что это удалит дубликаты или что-то в этом роде, но похоже, что метод этого не делает.
Избегайте коллекций Apache Commons. Это небезопасно, здесь нет дженериков. Отлично, если вы используете Java 1.4, но для Java 5 и выше я бы предпочел Google Guava.
@MichaelPiefel кажется, что единственный метод, отсутствующий в Guava, - это метод Lists.concat (...).
@ Ричард Да, а как насчет Iterables.concat()? В большинстве случаев это именно то, что вы хотите. Если вам абсолютно необходим новый список, используйте Lists.newArrayList(Iterables.concat(…)).
@MichaelPiefel Последняя версия Apache Commons Collections 4 является типобезопасной. Благодаря справочнику по методам Java 8 статические утилиты такого типа становятся очень важными.
ListUtils от Apache - очень хорошая библиотека, простая в использовании ListUtils.uniion (list1, list2), как вы говорите, но нужны ли вам другие методы, например longestCommonSubsequence (...) или fixedSizeList (...)? Может быть полезно подумать о том, что еще перетаскивается, что вам может не понадобиться, когда так легко объединить списки, как List.addAll ()
Проголосовали за, так как это единственный ответ, для которого не требовалось несколько вызовов методов. Потоки - это весело, но необходимость делать n вызовов методов для каждой ... одной ... мелочи ... кажется подверженной ошибкам. Объединение двух списков ДОЛЖНО быть простой операцией.
К сожалению, ListUtils.union () не поддерживает более двух параметров.
Нашел этот вопрос, пытаясь объединить произвольное количество списков, не обращая внимания на внешние библиотеки. Так что, возможно, это поможет кому-то другому:
com.google.common.collect.Iterables#concat()
Полезно, если вы хотите применить одну и ту же логику к нескольким различным коллекциям в одной for ().
Например: Lists.newArrayList (Iterables.concat (list1, list2));
вы должны вызвать com.google.common.collect.Iterators#concat(java.util.Iterator<? extends java.util.Iterator<? extends T>>) вместо Iterables#concat(); потому что последние по-прежнему копируют элементы во временную ссылку!
Никаких однострочных, но я думаю, что это самый простой вариант:
List<String> newList = new ArrayList<String>(l1);
newList.addAll(l2);
for(String w:newList)
System.out.printf("%s ", w);
Самый умный на мой взгляд:
/**
* @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;
}
Не забывайте @SafeVarargs!
Не проще, но без накладных расходов на изменение размера:
List<String> newList = new ArrayList<>(listOne.size() + listTwo.size());
newList.addAll(listOne);
newList.addAll(listTwo);
Одно из ваших требований - сохранить исходные списки. Если вы создаете новый список и используете 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);
Это работоспособное решение, но имейте в виду, что если изменяются базовые объекты списка (list1, list2), содержимое этого списка изменяется. Возможно, вы не сможете изменить экземпляр CompositeUnmodifiableList сам, но если вы можете получить ссылку на исходные списки, то сможете. Также для тех, кто незнаком: последний модификатор просто влияет на Справка, сам объект списка не может измениться, но содержимое списка все еще может измениться!
@jwj, все очень хорошие моменты, спасибо. Название класса, вероятно, заслуживает некоторого пояснения. Я вижу, что этот класс делает что-то очень похожее на метод Collections.unmodifiableList(), который обертывает список, чтобы сделать его неизменяемым. CompositeUnmodifiableList делает то же самое, за исключением того, что он объединяет два списка и обеспечивает объединенное представление. Все замечания, которые вы говорите о CompositeUnmodifiableList, справедливы и для Collections.unmodifiableList().
Конструктор может принимать List<? extends E>
public class TestApp {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Hi");
Set<List<String>> bcOwnersList = new HashSet<List<String>>();
List<String> bclist = new ArrayList<String>();
List<String> bclist1 = new ArrayList<String>();
List<String> object = new ArrayList<String>();
object.add("BC11");
object.add("C2");
bclist.add("BC1");
bclist.add("BC2");
bclist.add("BC3");
bclist.add("BC4");
bclist.add("BC5");
bcOwnersList.add(bclist);
bcOwnersList.add(object);
bclist1.add("BC11");
bclist1.add("BC21");
bclist1.add("BC31");
bclist1.add("BC4");
bclist1.add("BC5");
List<String> listList= new ArrayList<String>();
for(List<String> ll : bcOwnersList){
listList = (List<String>) CollectionUtils.union(listList,CollectionUtils.intersection(ll, bclist1));
}
/*for(List<String> lists : listList){
test = (List<String>) CollectionUtils.union(test, listList);
}*/
for(Object l : listList){
System.out.println(l.toString());
}
System.out.println(bclist.contains("BC"));
}
}
Я даже не понимаю, какая часть на самом деле должна быть ответом ...
Несколько предложений с объяснением очень помогут. Имейте это в виду для будущих комментариев
В Java 8:
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
.collect(Collectors.toList());
Gawd, это что-то в Java 8? Технически ты выиграешь, я полагаю, но это чертовски длинная очередь :-)
Интересно, оказывает ли создание и выполнение двух потоков заметное влияние на производительность. Я полагаю, что этого не должно быть, по сравнению с созданием двух итераторов.
Для случайного читателя есть более короткое решение, использующее также Java _ Streams: stackoverflow.com/a/34090554/363573
Это некрасиво, но, по крайней мере, свободно и может использоваться без многострочных лямбда-выражений. Я действительно хотел бы, чтобы был свободный addAll, который возвращал бы объединенный список.
Думаю, стоит отметить, что и из этого действительно легко получить четкий список, например: List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).distinct().collect(Collectors.toList());
Альтернатива concat: поток потоков Stream.of(listOne, listTwo).flatMap(Collection::stream).collect(Collectors.toList())
По сути, это то же самое, что и C# List<string> l = list1.Union(list2).ToList();, но гораздо более подробный.
@PeterWalser Это должен быть отдельный ответ, поскольку он также позволяет использовать более одного списка. flatMap, хороший звонок!
Обычно, когда я дохожу до точки, когда единственный разумный API - это API для потоков, я понимаю, что listOne и listTwo должны были быть потоками все время.
Это просто и всего одна строка, но добавит содержимое listTwo в listOne. Вам действительно нужно поместить содержимое в третий список?
Collections.addAll(listOne, listTwo.toArray());
Не изменять исходные списки было одним из критериев, но это полезно иметь здесь в качестве примера для ситуаций, когда это не ограничение.
Спасибо, а то еще проще listOne.addAll (listTwo)
Еще один однострочник Java 8:
List<String> newList = Stream.of(listOne, listTwo)
.flatMap(Collection::stream)
.collect(Collectors.toList());
В качестве бонуса, поскольку Stream.of() является вариативным, вы можете объединить столько списков, сколько захотите.
List<String> newList = Stream.of(listOne, listTwo, listThree)
.flatMap(Collection::stream)
.collect(Collectors.toList());
x -> x.stream() можно заменить на Collection::stream.
... или даже с List::stream.
public static <T> List<T> merge(List<T>... args) {
final List<T> result = new ArrayList<>();
for (List<T> list : args) {
result.addAll(list);
}
return result;
}
Вот решение java 8 с использованием двух строк:
List<Object> newList = new ArrayList<>();
Stream.of(list1, list2).forEach(newList::addAll);
Имейте в виду, что этот метод не следует использовать, если
newList неизвестно, и, возможно, он уже используется другими потокамиnewList, является параллельным потоком, и доступ к newList не синхронизирован или не является потокобезопаснымиз-за побочных эффектов.
Оба вышеуказанных условия не применимы к вышеуказанному случаю объединения двух списков, так что это безопасно.
На основании этот ответ к другому вопросу.
Если я не ошибаюсь, это на самом деле не рекомендуется - docs.oracle.com/javase/8/docs/api/java/util/stream/… См. Раздел «Побочные эффекты». > Побочные эффекты в поведенческих параметрах потоковых операций, как правило, не приветствуются, так как они часто могут привести к непреднамеренным нарушениям требования безгражданства, а также к другим угрозам безопасности потоков. Так что в этом случае лучше использовать Collectors.toList ()
@AntonBalaniuc Вопрос в том, действительно ли это побочный эффект. В этот момент newList не наблюдается ни в каком другом потоке. Но вы правы, что этого, вероятно, не следует делать, если неизвестно, откуда взялось значение newList (например, если newList был передан в качестве параметра.
Мне любопытно; почему .forEach(newList::addAll); вместо .collect(Collectors.toList());?
@ 11684, потому что сборщик собирает List<List<Object>>. Вы можете иметь в виду что-то вроде этого: stackoverflow.com/questions/189559/…
@SpaceTrucker Ой, я не заметил этого. Спасибо, что разъяснили мою путаницу. Да, мне следовало подумать о flatMap.
Java 8 (
Stream.ofandStream.concat)
Предлагаемое решение предназначено для трех списков, хотя его можно применить и для двух списков. В 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);
Вот подход с использованием потоков и java 8, если ваши списки имеют разные типы и вы хотите объединить их в список другого типа.
public static void main(String[] args) {
List<String> list2 = new ArrayList<>();
List<Pair<Integer, String>> list1 = new ArrayList<>();
list2.add("asd");
list2.add("asdaf");
list1.add(new Pair<>(1, "werwe"));
list1.add(new Pair<>(2, "tyutyu"));
Stream stream = Stream.concat(list1.stream(), list2.stream());
List<Pair<Integer, String>> res = (List<Pair<Integer, String>>) stream
.map(item -> {
if (item instanceof String) {
return new Pair<>(0, item);
}
else {
return new Pair<>(((Pair<Integer, String>)item).getKey(), ((Pair<Integer, String>)item).getValue());
}
})
.collect(Collectors.toList());
}
еще одно решение для лайнера с использованием потока 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]
Я бы добавил, что это решение, вероятно, более производительно, чем то, которое использует flatMap, потому что списки повторяются только один раз, когда они собираются.
Версия 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());
}
В Java 8 (наоборот):
List<?> newList =
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());
Этот подход уже предлагается в этом ответе: stackoverflow.com/a/37386846
Если вы хотите сделать это статически, вы можете сделать следующее.
В примерах используются 2 набора EnumSet в естественном порядке (== порядок перечислений) A, B и затем объединяются в список ALL.
public static final EnumSet<MyType> CATEGORY_A = EnumSet.of(A_1, A_2);
public static final EnumSet<MyType> CATEGORY_B = EnumSet.of(B_1, B_2, B_3);
public static final List<MyType> ALL =
Collections.unmodifiableList(
new ArrayList<MyType>(CATEGORY_A.size() + CATEGORY_B.size())
{{
addAll(CATEGORY_A);
addAll(CATEGORY_B);
}}
);
Это создаст новый анонимный класс. Не рекомендуемый подход!
public static <T> List<T> merge(@Nonnull final List<T>... list) {
// calculate length first
int mergedLength = 0;
for (List<T> ts : list) {
mergedLength += ts.size();
}
final List<T> mergedList = new ArrayList<>(mergedLength);
for (List<T> ts : list) {
mergedList.addAll(ts);
}
return mergedList;
}
Вы можете создать свой общий служебный метод Java 8 для объединения любое количество списков.
@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}
import java.util.AbstractList;
import java.util.List;
/**
* The {@code ConcatList} is a lightweight view of two {@code List}s.
* <p>
* This implementation is <em>not</em> thread-safe even though the underlying lists can be.
*
* @param <E>
* the type of elements in this list
*/
public class ConcatList<E> extends AbstractList<E> {
/** The first underlying list. */
private final List<E> list1;
/** The second underlying list. */
private final List<E> list2;
/**
* Constructs a new {@code ConcatList} from the given two lists.
*
* @param list1
* the first list
* @param list2
* the second list
*/
public ConcatList(final List<E> list1, final List<E> list2) {
this.list1 = list1;
this.list2 = list2;
}
@Override
public E get(final int index) {
return getList(index).get(getListIndex(index));
}
@Override
public E set(final int index, final E element) {
return getList(index).set(getListIndex(index), element);
}
@Override
public void add(final int index, final E element) {
getList(index).add(getListIndex(index), element);
}
@Override
public E remove(final int index) {
return getList(index).remove(getListIndex(index));
}
@Override
public int size() {
return list1.size() + list2.size();
}
@Override
public boolean contains(final Object o) {
return list1.contains(o) || list2.contains(o);
}
@Override
public void clear() {
list1.clear();
list2.clear();
}
/**
* Returns the index within the corresponding list related to the given index.
*
* @param index
* the index in this list
*
* @return the index of the underlying list
*/
private int getListIndex(final int index) {
final int size1 = list1.size();
return index >= size1 ? index - size1 : index;
}
/**
* Returns the list that corresponds to the given index.
*
* @param index
* the index in this list
*
* @return the underlying list that corresponds to that index
*/
private List<E> getList(final int index) {
return index >= list1.size() ? list2 : list1;
}
}
Мы можем объединить 2 списка с помощью java8 с двумя подходами.
List<String> list1 = Arrays.asList("S", "T");
List<String> list2 = Arrays.asList("U", "V");
1) Использование concat:
List<String> collect2 = Stream.concat(list1.stream(), list2.stream()).collect(toList());
System.out.println("collect2 = " + collect2); // collect2 = [S, T, U, V]
2) Использование flatMap:
List<String> collect3 = Stream.of(list1, list2).flatMap(Collection::stream).collect(toList());
System.out.println("collect3 = " + collect3); // collect3 = [S, T, U, V]
Отвечая на вопрос одиннадцатилетней давности тридцатью другими ответами, обязательно укажите, какие новые аспекты вопроса затрагивает ваш ответ, и отметьте, сработали бы эти методы, когда был задан вопрос, или они зависят от функций, которые были заданы. введен с годами.
Почти из ответов предлагается использовать ArrayList.
List<String> newList = new LinkedList<>(listOne);
newList.addAll(listTwo);
Предпочитайте использовать LinkedList для эффективных операций добавления.
Добавление ArrayList амортизируется за O (1), но в худшем случае за O (n), поскольку размер массива необходимо изменить и скопировать. В то время как LinkedList add всегда является постоянным O (1).
больше информации https://stackoverflow.com/a/322742/311420
Если вы делаете это исключительно для целей итерации, см. Другой вопрос - есть решения google guava и java 8 stackoverflow.com/questions/4896662/…