当前位置:  开发笔记 > 编程语言 > 正文

如何在Java中加入两个列表?

如何解决《如何在Java中加入两个列表?》经验,为你挑选了20个好方法。

条件:不修改原始列表; 仅限JDK,没有外部库.单行或JDK 1.3版本的奖励积分.

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

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

AdamC.. 543

在我的头顶,我可以缩短一行:

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

虽然你在技术上是正确的,但你已经将它缩短了一行,这种不对称性使我感到不安.够了,我更乐意"花"额外的路线. (145认同)

这里有没有问题,newList的interal数组将初始化为listOne的大小,然后在添加listTwo的所有项目时必须扩展?获取每个列表的大小并使用它来调整新数组的大小会更好吗? (13认同)

这是最适合我的解决方案.我对不同解决方案的性能进行了比较,这些解决方案获得了胜利,同时创建了空列表,然后创建了两个`addAll()`.我尝试了所有那些建议不复制列表的人,结果我们这次不需要很多开销. (2认同)


Dale Emery.. 523

在Java 8中:

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

Gawd,这是Java 8中的一个东西吗?从技术上讲,你我赢了,但这是一个很长的路线:-) (65认同)

它很丑,但至少它流畅,可以在没有多线lambda的情况下使用.我真的希望有一个流畅的addAll返回到concatinated列表. (7认同)

对于休闲读者来说,这是一个使用Java _ St​​reams的更短的解决方案:http://stackoverflow.com/a/34090554/363573 (4认同)

我想值得注意的是,从中也可以很容易地得到一个独特的列表,就像这样:`List <String> newList = Stream.concat(listOne.stream(),listTwo.stream())。distinct()。 collect(Collectors.toList());` (4认同)


小智.. 276

您可以使用Apache commons-collections库:

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

@Quantum7,对其他人仍然有用;)另外,apache公共甚至是外部库吗?没有它,我什么都没开始! (95认同)

很好,但需要apache公共.他指的是"没有外部图书馆" (49认同)

@Platinum不,根据文档ListUtils.union完全等同于OP的代码.但也许在列表上下文中使用SET操作("Union")会产生误导.我可以看到你如何期望这可以删除重复或类似的东西,但似乎该方法不会这样做. (28认同)

避免使用Apache Commons Collections.它不是类型安全的,没有泛型.如果你使用Java 1.4很好,但对于Java 5及更高版本,我更喜欢Google Guava. (24认同)

@MichaelPiefel最新的Apache Commons Collections 4是类型安全的.使用Java 8方法引用,这种静态实用程序变得非常重要. (9认同)

@Richard是的,但是`Iterables.concat()`怎么样?大多数时候它正是你想要的.如果您绝对需要新列表,请使用`Lists.newArrayList(Iterables.concat(...))`. (3认同)


Kevin K.. 85

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

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

CompositeUnmodifiableList.java:

public class CompositeUnmodifiableList extends AbstractList {

    private final List list1;
    private final List list2;

    public CompositeUnmodifiableList(List list1, List 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 newList = new CompositeUnmodifiableList(listOne,listTwo);

这是这个问题的真正答案. (12认同)

这是一个可行的解决方案,但请注意,如果基础列表对象发生更改(list1,list2),则此列表的内容会发生变化.您可能无法修改CompositeUnmodifiableList _itself_的实例,但如果您可以获得对原始列表的引用,则可以.对于那些不熟悉的人:最终修饰符只影响_reference_到列表对象本身不能改变但是列表内容仍然可以改变! (8认同)

@jwj都非常好点,谢谢.类名可能值得一些解释.我认为这个类与`Collections.unmodifiableList()`方法非常相似,它包装了一个列表以使其不可修改.`CompositeUnmodifiableList`做同样的事情,除了它包装两个列表并提供连接的视图.关于`CompositeUnmodifiableList`的所有要点也适用于`Collections.unmodifiableList()`. (3认同)


volley.. 84

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

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

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



1> AdamC..:

在我的头顶,我可以缩短一行:

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


虽然你在技术上是正确的,但你已经将它缩短了一行,这种不对称性使我感到不安.够了,我更乐意"花"额外的路线.
这里有没有问题,newList的interal数组将初始化为listOne的大小,然后在添加listTwo的所有项目时必须扩展?获取每个列表的大小并使用它来调整新数组的大小会更好吗?
这是最适合我的解决方案.我对不同解决方案的性能进行了比较,这些解决方案获得了胜利,同时创建了空列表,然后创建了两个`addAll()`.我尝试了所有那些建议不复制列表的人,结果我们这次不需要很多开销.

2> Dale Emery..:

在Java 8中:

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


Gawd,这是Java 8中的一个东西吗?从技术上讲,你我赢了,但这是一个很长的路线:-)
它很丑,但至少它流畅,可以在没有多线lambda的情况下使用.我真的希望有一个流畅的addAll返回到concatinated列表.
对于休闲读者来说,这是一个使用Java _ St​​reams的更短的解决方案:http://stackoverflow.com/a/34090554/363573
我想值得注意的是,从中也可以很容易地得到一个独特的列表,就像这样:`List <String> newList = Stream.concat(listOne.stream(),listTwo.stream())。distinct()。 collect(Collectors.toList());`

3> 小智..:

您可以使用Apache commons-collections库:

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


@Quantum7,对其他人仍然有用;)另外,apache公共甚至是外部库吗?没有它,我什么都没开始!
很好,但需要apache公共.他指的是"没有外部图书馆"
@Platinum不,根据文档ListUtils.union完全等同于OP的代码.但也许在列表上下文中使用SET操作("Union")会产生误导.我可以看到你如何期望这可以删除重复或类似的东西,但似乎该方法不会这样做.
避免使用Apache Commons Collections.它不是类型安全的,没有泛型.如果你使用Java 1.4很好,但对于Java 5及更高版本,我更喜欢Google Guava.
@MichaelPiefel最新的Apache Commons Collections 4是类型安全的.使用Java 8方法引用,这种静态实用程序变得非常重要.
@Richard是的,但是`Iterables.concat()`怎么样?大多数时候它正是你想要的.如果您绝对需要新列表,请使用`Lists.newArrayList(Iterables.concat(...))`.

4> Kevin K..:

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

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

CompositeUnmodifiableList.java:

public class CompositeUnmodifiableList extends AbstractList {

    private final List list1;
    private final List list2;

    public CompositeUnmodifiableList(List list1, List 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 newList = new CompositeUnmodifiableList(listOne,listTwo);


这是这个问题的真正答案.
这是一个可行的解决方案,但请注意,如果基础列表对象发生更改(list1,list2),则此列表的内容会发生变化.您可能无法修改CompositeUnmodifiableList _itself_的实例,但如果您可以获得对原始列表的引用,则可以.对于那些不熟悉的人:最终修饰符只影响_reference_到列表对象本身不能改变但是列表内容仍然可以改变!
@jwj都非常好点,谢谢.类名可能值得一些解释.我认为这个类与`Collections.unmodifiableList()`方法非常相似,它包装了一个列表以使其不可修改.`CompositeUnmodifiableList`做同样的事情,除了它包装两个列表并提供连接的视图.关于`CompositeUnmodifiableList`的所有要点也适用于`Collections.unmodifiableList()`.

5> volley..:

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

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

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


丑陋和邪恶,就像几乎任何使用双括号初始化一样.但它更短;)
虽然它实际上是一条线,但我不认为这是"单线".
@NimChimpsky我认为这主要是因为它不仅仅是一个匿名块初始化器,而是你实际上正在创建一个ArrayList的匿名子类.话虽这么说,如果你相信这个[Double Brace Initilization question](http://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization)的结果,它会让人觉得讨厌DBI主要是风格品味和微观优化.据我所知,这样做没有重大的惩罚.如果你试图比较它的类,那么偷偷摸摸的缺点就是因为它不是ArrayList.
为什么人们讨厌匿名块初始化器
@MarnixKlooster:Eclipse*知道*你不应该使用它并使它使用起来不愉快;-)
如何使用双支撑初始化使其成为单线程?

6> Martin..:

不简单,但没有调整开销:

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



7> Mark..:

另一个Java 8单线程:

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

作为奖励,因为Stream.of()是可变参数,您可以根据需要连接多个列表.

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


`x - > x.stream()`可以替换为`Collection :: stream`.
......甚至是`List :: stream`.

8> Yuri Geinish..:

发现这个问题寻找连接任意数量的列表,而不是关注外部库.所以,也许它会帮助别人:

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

如果要将相同的逻辑应用于for()中的多个不同集合,则非常有用.


例如:Lists.newArrayList(Iterables.concat(list1,list2));

9> SpaceTrucker..:

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

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


请注意,如果使用此方法,则不应使用此方法

原因newList尚不清楚,可能已经与其他线程共享

修改的流newList是并行流,并且访问 newList不同步或线程安全

由于副作用的考虑.

上述两个条件都不适用于上述加入两个列表的情况,因此这是安全的.

基于这个答案的另一个问题.


如果我没有错,实际上不建议这样做 - docs.oracle.com/javase/8/docs/api/java/util/stream/...请参阅side -effects部分.>一般来说,不鼓励行为参数对流操作的副作用,因为它们通常会导致无意中违反无国籍要求,以及其他线程安全危险.所以在这种情况下最好使用Collectors.toList()
@ 11684因为收集器会收集一个`List >.您可能想到的是这样的:/sf/ask/17360801/#37386846

10> i_am_zero..:

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

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

Stream.concat将两个流作为输入并创建一个延迟连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素.由于我们有三个列表,我们使用了这个方法(Stream.concat)两次.

我们还可以使用一个方法编写一个实用程序类,该方法可以获取任意数量的列表(使用varargs)并返回一个连接列表:

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

然后我们可以使用这个方法:

List result3 = Utils.concatenateLists(list1,list2,list3);



11> ceklock..:

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

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


不修改原始列表是其中一个标准,但这对于此处作为不是约束的情况的示例很有用.

12> Tim..:

稍微简单一些:

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


@Zainodis是的,可能有重复.`List`结构没有强加唯一性约束.您可以通过使用集合执行相同的操作来删除欺骗.`Set newSet = new HashSet <>(setOne); newSet.addAll(setTwo);`

13> Jorn..:

稍短一点就是:

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



14> Daniel Hári..:

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

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



15> deterb..:

如果目标列表是预先声明的,则可以执行oneliner.

(newList = new ArrayList(list1)).addAll(list2);



16> Nitin Jain..:

Java 8中(另一种方式):

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



17> Saravana..:

使用Java8流的另一个线性解决方案,因为flatMap已经发布了解决方案,这里是一个没有的解决方案flatMap

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

要么

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

    List> lol = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
    List 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]



18> Olivier Fauc..:

我认为最聪明的是:

/**
 * @param smallLists
 * @return one big list containing all elements of the small ones, in the same order.
 */
public static  List concatenate (final List ... smallLists)
{
    final ArrayList bigList = new ArrayList();
    for (final List list: smallLists)
    {
        bigList.addAll(list);
    }
    return bigList;
}


不要忘记`@SafeVarargs`!

19> Dave Cheney..:

您可以使用静态导入和帮助程序类来完成此操作

注意这个类的generification很可能得到改善

public class Lists {

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

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

}

然后你可以做的事情

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



20> 小智..:

Java 8版本,支持按对象键加入:

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

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

    return new ArrayList<>(mergedList.values());
}

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有