928

条件:不修改原名单;只有 JDK,没有外部库。单行或 JDK 1.3 版本的奖励积分。

有没有比以下更简单的方法:

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

33 回答 33

809

在 Java 8 中:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                             .collect(Collectors.toList());
于 2013-09-08T19:31:49.730 回答
659

在我的脑海中,我可以将它缩短一行:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
于 2008-10-09T23:21:09.777 回答
382

您可以使用Apache commons-collections库:

List<String> newList = ListUtils.union(list1, list2);
于 2010-08-27T03:28:00.207 回答
191

另一个 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());
于 2014-04-03T22:51:03.553 回答
98

您的要求之一是保留原始列表。如果您创建一个新列表并使用addAll(),那么您实际上将列表中对象的引用数量增加了一倍。如果您的列表非常大,这可能会导致内存问题。

如果您不需要修改连接结果,则可以使用自定义列表实现来避免这种情况。自定义实现类不止一行,显然……但使用它又短又甜。

CompositeUnmodifiableList.java:

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

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

    public CompositeUnmodifiableList(List<? extends E> list1, List<? extends 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);
于 2012-12-13T20:54:12.000 回答
97

可能并不简单,但有趣且丑陋:

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

不要在生产代码中使用它... ;)

于 2008-10-10T00:30:15.690 回答
83

不简单,但无需调整开销:

List<String> newList = new ArrayList<>(listOne.size() + listTwo.size());
newList.addAll(listOne);
newList.addAll(listTwo);
于 2012-12-13T20:35:54.373 回答
57

发现这个问题希望连接任意数量的列表,而不是在意外部库。所以,也许它会帮助别人:

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

如果您想在一个 for() 中将相同的逻辑应用于多个不同的集合,这很有用。

于 2011-07-29T13:46:36.307 回答
53

Java 8(Stream.ofStream.concat

建议的解决方案适用于三个列表,尽管它也可以应用于两个列表。在 Java 8 中,我们可以将Stream.ofStream.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);
于 2016-05-23T09:04:22.310 回答
51

这是使用两行的 java 8 解决方案:

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

请注意,如果出现以下情况,则不应使用此方法

  • 的来源newList未知,可能已经与其他线程共享
  • 修改的流newList是并行流,并且访问 newList不是同步的或线程安全的

出于副作用考虑。

上述两个条件都不适用于上述加入两个列表的情况,所以这是安全的。

基于这个回答另一个问题。

于 2015-12-04T14:27:51.770 回答
38

这很简单,只有一行,但会将 listTwo 的内容添加到 listOne。您真的需要将内容放在第三个列表中吗?

Collections.addAll(listOne, listTwo.toArray());
于 2013-09-08T22:50:19.707 回答
33

稍微简单一点:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
于 2008-10-09T23:21:09.463 回答
21

更短一点是:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
于 2008-10-09T23:22:50.990 回答
20

您可以创建通用Java 8实用程序方法来连接任意数量的列表

@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
    return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}
于 2018-05-18T20:33:05.163 回答
13

如果预先声明了目标列表,您可以执行 oneliner。

(newList = new ArrayList<String>(list1)).addAll(list2);
于 2008-10-10T00:46:50.493 回答
12

Java 8中(另一种方式):

List<?> newList = 
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());
于 2017-03-24T02:58:27.853 回答
10

另一个使用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]
于 2016-11-12T04:38:17.820 回答
9

我们可以使用 java8 和 2 种方法加入 2 个列表。

    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]
于 2020-03-25T17:37:58.243 回答
8

我认为最聪明的:

/**
 * @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;
}
于 2012-07-26T09:25:40.403 回答
8

Almost of answers suggest to use an ArrayList.

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

Prefer to use a LinkedList for efficient add operations.

ArrayList add is O(1) amortized, but O(n) worst-case since the array must be resized and copied. While LinkedList add is always constant O(1).

more infos https://stackoverflow.com/a/322742/311420

于 2020-04-07T14:58:14.953 回答
6

您可以使用静态导入和辅助类来完成

注意这个类的泛化可能会得到改进

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);
于 2008-10-10T00:51:43.120 回答
6

支持按对象键加入的 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());
}
于 2016-11-29T15:49:17.153 回答
4

使用 Helper 类。

我建议:

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)));
}
于 2008-10-10T11:36:59.463 回答
4
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;
}
于 2014-07-12T17:12:52.240 回答
3
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;
  }
于 2018-02-21T11:11:36.237 回答
2

我最喜欢的方式,使用 fluent api 和 Guava:

List<String> combined = ImmutableList.<String>builder().addAll(list1).addAll(list2).build()
于 2021-11-24T21:01:16.600 回答
0

我并不是说这很简单,但你提到了单线的奖金;-)

Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] {
    new Vector(list1).elements(),
    new Vector(list2).elements(),
    ...
}))
于 2008-10-10T10:17:23.693 回答
0

没有办法接近单线,但我认为这是最简单的:

List<String> newList = new ArrayList<String>(l1);
newList.addAll(l2);

for(String w:newList)
        System.out.printf("%s ", w);
于 2011-09-06T09:14:03.523 回答
0

如果您想静态地执行此操作,您可以执行以下操作。

这些示例以自然顺序(==枚举顺序)使用 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);
                  }}
              );
于 2017-11-23T14:12:11.773 回答
0

如果您的列表具有不同的类型并且您想将它们组合到另一种类型的列表中,这是一种使用流和 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());
}
于 2016-10-18T22:28:23.480 回答
-3
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;
    }

}
于 2019-04-04T13:53:03.963 回答
-6

在一般情况下,如果不引入您自己的实用程序方法,我无法改进两行,但是如果您确实有字符串列表并且您愿意假设这些字符串不包含逗号,您可以拉长一个-衬垫:

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 兼容的(虽然我没有测试过)。也不推荐用于生产代码;-)

于 2008-10-10T04:52:07.610 回答
-7
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"));

}

}
于 2012-12-21T12:37:40.950 回答