如何在 Java 中连接两个列表?

发布于 2024-07-06 06:57:26 字数 264 浏览 10 评论 0原文

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

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

条件:

  1. 不要修改原始列表。
  2. 仅限 JDK。
  3. 没有外部库。

单行版或 JDK 1.3 版本的奖励积分。

Is there a simpler way than:

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

Conditions:

  1. Do not modify the original lists.
  2. JDK only.
  3. No external libraries.

Bonus points for a one-liner or a JDK 1.3 version.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

方觉久 2024-07-13 06:57:27

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 version with support for joining by object key:

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());
}
埖埖迣鎅 2024-07-13 06:57:27
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;
}
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;
}
清醇 2024-07-13 06:57:27

使用助手类。

我建议:

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)));
}

Use a Helper class.

I suggest:

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)));
}
南七夏 2024-07-13 06:57:27
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;
  }
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;
  }
回忆追雨的时光 2024-07-13 06:57:27

我最喜欢的方式是使用 Fluent api 和 Guava:

List<String> combined = ImmutableList.<String>builder().addAll(list1).addAll(list2).build()

My favourite way, using fluent api and Guava:

List<String> combined = ImmutableList.<String>builder().addAll(list1).addAll(list2).build()
哆兒滾 2024-07-13 06:57:27

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

Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] {
    new Vector(list1).elements(),
    new Vector(list2).elements(),
    ...
}))

编辑: ... 13 年后

var mergedList = Stream.of(list1, list2)
                       .flatMap(Collection::stream)
                       .toList()

I'm not claiming that it's simple, but you mentioned bonus for one-liners ;-)

Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] {
    new Vector(list1).elements(),
    new Vector(list2).elements(),
    ...
}))

Edit: ... and 13 years later

var mergedList = Stream.of(list1, list2)
                       .flatMap(Collection::stream)
                       .toList()
夏末的微笑 2024-07-13 06:57:27

远不是一句简单的话,但我认为这是最简单的:

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

for(String w:newList)
        System.out.printf("%s ", w);

No way near one-liner, but I think this is the simplest:

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

for(String w:newList)
        System.out.printf("%s ", w);
黯淡〆 2024-07-13 06:57:27

如果您的列表具有不同的类型并且您想将它们组合到另一种类型的列表中,那么这里有一种使用流和 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());
}

Here's an approach using streams and java 8 if your lists have different types and you want to combine them to a list of another type.

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());
}
欲拥i 2024-07-13 06:57:27

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

这些示例使用 2 个按自然顺序 (==Enum-order) A, B 的 EnumSet,然后连接到 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);
                  }}
              );

If you want to do this statically you can the following.

The examples uses 2 EnumSets in natural-order (==Enum-order) A, B and joins then in an ALL list.

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);
                  }}
              );
一杆小烟枪 2024-07-13 06:57:26

在 Java 8 中:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                             .collect(Collectors.toList());

Java 16+:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).toList();

In Java 8:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                             .collect(Collectors.toList());

Java 16+:

List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).toList();
过度放纵 2024-07-13 06:57:26

从我的头顶上看,我可以将其缩短一行:

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

Off the top of my head, I can shorten it by one line:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
聽兲甴掵 2024-07-13 06:57:26

您可以使用 Apache commons-collections< /a> 库:

List<String> newList = ListUtils.union(list1, list2);

You could use the Apache commons-collections library:

List<String> newList = ListUtils.union(list1, list2);
遗忘曾经 2024-07-13 06:57:26

另一个 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());

Another Java 8 one-liner:

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

As a bonus, since Stream.of() is variadic, you may concatenate as many lists as you like.

List<String> newList = Stream.of(listOne, listTwo, listThree)
                            .flatMap(Collection::stream)
                            .collect(Collectors.toList());
青春如此纠结 2024-07-13 06:57:26

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

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

CompositeUnmodifyingList.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);

One of your requirements is to preserve the original lists. If you create a new list and use addAll(), you are effectively doubling the number of references to the objects in your lists. This could lead to memory problems if your lists are very large.

If you don't need to modify the concatenated result, you can avoid this using a custom list implementation. The custom implementation class is more than one line, obviously...but using it is short and sweet.

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();
    }
}

Usage:

List<String> newList = new CompositeUnmodifiableList<String>(listOne,listTwo);
转角预定愛 2024-07-13 06:57:26

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

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

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

Probably not simpler, but intriguing and ugly:

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

Don't use it in production code... ;)

时光倒影 2024-07-13 06:57:26

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

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

Not simpler, but without resizing overhead:

List<String> newList = new ArrayList<>(listOne.size() + listTwo.size());
newList.addAll(listOne);
newList.addAll(listTwo);
小ぇ时光︴ 2024-07-13 06:57:26

发现这个问题希望连接任意数量的列表,而不介意外部库。 因此,也许它会对其他人有所帮助:

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

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

Found this question looking to concatenate arbitrary amount of lists, not minding external libraries. So, perhaps it will help someone else:

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

Useful if you want to apply the same logic to a number of different collections in one for().

薔薇婲 2024-07-13 06:57:26

Java 8(Stream.ofStream.concat

建议的解决方案适用于三个列表,但也可以应用于两个列表。 在 Java 8 中,我们可以使用 Stream.ofStream.concat as:

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 (Stream.of and Stream.concat)

The proposed solution is for three lists though it can be applied for two lists as well. In Java 8 we can make use of Stream.of or Stream.concat as:

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 takes two streams as input and creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. As we have three lists we have used this method (Stream.concat) two times.

We can also write a utility class with a method that takes any number of lists (using varargs) and returns a concatenated list as:

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

Then we can make use of this method as:

List<String> result3 = Utils.concatenateLists(list1,list2,list3);
写给空气的情书 2024-07-13 06:57:26

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

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

则不应使用此方法

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

newList 是并行流,出于副作用考虑,

。 上述两个条件不适用于上述连接两个列表的情况,因此这是安全的。

基于另一个问题的此答案

Here is a java 8 solution using two lines:

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

Be aware that this method should not be used if

  • the origin of newList is not known and it may already be shared with other threads
  • the stream that modifies newList is a parallel stream and access to newList is not synchronized or threadsafe

due to side effect considerations.

Both of the above conditions do not apply for the above case of joining two lists, so this is safe.

Based on this answer to another question.

明天过后 2024-07-13 06:57:26

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

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

This is simple and just one line, but will add the contents of listTwo to listOne. Do you really need to put the contents in a third list?

Collections.addAll(listOne, listTwo.toArray());
鱼窥荷 2024-07-13 06:57:26

稍微简单一点:

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

Slightly simpler:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
假情假意假温柔 2024-07-13 06:57:26

稍微短一点的是:

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

A little shorter would be:

List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
擦肩而过的背影 2024-07-13 06:57:26

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

@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
    return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}

You can create your generic Java 8 utility method to concat any number of lists.

@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
    return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}
孤单情人 2024-07-13 06:57:26

在 Java 8 中(另一种方式):

List<?> newList = 
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());

In Java 8 (the other way):

List<?> newList = 
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());
祁梦 2024-07-13 06:57:26

如果目标列表已预先声明,您可以做一个简短的说明。

(newList = new ArrayList<String>(list1)).addAll(list2);

You can do a oneliner if the target list is predeclared.

(newList = new ArrayList<String>(list1)).addAll(list2);
与风相奔跑 2024-07-13 06:57:26

另一种使用 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]

another one liner solution using Java8 stream, since flatMap solution is already posted, here is a solution without flatMap

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

or

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

code

    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);

output

[[1, 2, 3], [4, 5, 6]]
[1, 2, 3, 4, 5, 6]
棒棒糖 2024-07-13 06:57:26

我们可以使用 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]

We can join 2 lists using java8 with 2 approaches.

    List<String> list1 = Arrays.asList("S", "T");
    List<String> list2 = Arrays.asList("U", "V");

1) Using concat :

    List<String> collect2 = Stream.concat(list1.stream(), list2.stream()).collect(toList());
    System.out.println("collect2 = " + collect2); // collect2 = [S, T, U, V]

2) Using flatMap :

    List<String> collect3 = Stream.of(list1, list2).flatMap(Collection::stream).collect(toList());
    System.out.println("collect3 = " + collect3); // collect3 = [S, T, U, V]
岁吢 2024-07-13 06:57:26

我认为最聪明的是:

/**
 * @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;
}

The smartest in my opinion:

/**
 * @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;
}
彼岸花似海 2024-07-13 06:57:26

几乎所有答案都建议使用 ArrayList。

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

更喜欢使用 LinkedList 进行高效的添加操作。

ArrayList add 的分摊时间复杂度为 O(1),但最坏情况为 O(n),因为必须调整数组大小并进行复制。
而 LinkedList add 始终是常数 O(1)。

更多信息https://stackoverflow.com/a/322742/311420

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

怀中猫帐中妖 2024-07-13 06:57:26

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

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);

You could do it with a static import and a helper class

nb the generification of this class could probably be improved

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;
   }

}

Then you can do things like

import static Lists.join;
List<T> result = join(list1, list2, list3, list4);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文