java – 从另一个数组列表中删除一个arraylist元素的最佳方式

Java(7,8)中最好的性能方法是从另一个消除一个Arraylist的整数元素.所有元素在第一和第二列表中是唯一的.

目前我知道API方法removeall并以此方式使用:

tempList.removeAll(tempList2);

当我使用数组列表具有超过10000个元素时,出现问题.例如,当我删除65000个元素时,延迟似乎约为2秒.但是,我需要用超过1000000个元素的更大的列表来操作.

这个问题的策略是什么?

可能有新的Stream API应该解决它?

最佳答案
TL;博士:

把事情简单化.使用

list.removeAll(new HashSet<T>(listOfElementsToRemove));

代替.

正如Eran在his answer中已经提到的那样:低性能源于一个通用的removeAll实现的伪代码是

public boolean removeAll(Collection<?> c) {
    for (each element e of this) {
        if (c.contains(e)) {
            this.remove(e);
        }
    }
}

因此,在要删除的元素列表中完成的包含调用将导致O(n * k)性能(其中n是要删除的元素的数量),而k是该方法被调用的列表中的元素数上).

天真地,可以想象一下,this.remove(e)调用List也可能有O(k),这个实现也将具有二次复杂度.但是情况并非如此:您提到这些列表是特定的ArrayList实例.并且实现了ArrayList#removeAll方法来委托一个名为batchRemove的方法,该方法直接在底层数组上运行,并且不会单独删除这些元素.

所以你需要做的就是确保集合中包含要删除的元素的查找是快速的 – 最好是O(1).这可以通过将这些元素放入集合来实现.最后,它可以写成

list.removeAll(new HashSet<T>(listOfElementsToRemove));

附注:

Eran的答案有IMHO的两个主要缺点:首先,它需要排序列表,这是O(n * logn),而且根本不是必需的.但更重要的是(显然):排序可能会改变元素的顺序!如果这根本不需要怎么办?

远程相关:removeAll实现中还涉及到一些其他细微之处.例如,HashSet removeAll method is surprisingly slow在某些情况下.虽然当要删除的元素存储在列表中时,这也归结为O(n * n),但在这种特定情况下,确切的行为确实会令人惊讶.

转载注明原文:java – 从另一个数组列表中删除一个arraylist元素的最佳方式 - 代码日志