[英]ArrayList remove vs removeAll
如果我想从arraylist中删除一个集合,最好使用什么? 我认为ArrayList中的removeAll方法是为这个任务编写的,但是在我写的一个测试中,只是迭代遍历对象并删除它们个人的速度要快几秒。
你为此目的使用了什么?
编辑:
我在grepcode上找到的removeAll代码调用batchRemove(c,false):
private boolean更多... batchRemove(Collection c,boolean complement){
700 final Object[] elementData = this.elementData;
701 int r = 0, w = 0;
702 boolean modified = false;
703 try {
704 for (; r < size; r++)
705 if (c.contains(elementData[r]) == complement)
706 elementData[w++] = elementData[r];
707 } finally {
708 // Preserve behavioral compatibility with AbstractCollection,
709 // even if c.contains() throws.
710 if (r != size) {
711 System.arraycopy(elementData, r,
712 elementData, w,
713 size - r);
714 w += size - r;
715 }
716 if (w != size) {
717 // clear to let GC do its work
718 for (int i = w; i < size; i++)
719 elementData[i] = null;
720 modCount += size - w;
721 size = w;
722 modified = true;
723 }
724 }
725 return modified;
726 }
我其实不明白..
我的测试代码是这样的:
public class RemoveVsRemovall {
public static void main(String[] args){
ArrayList<String> source = new ArrayList<>();
ArrayList<String> toRemove = new ArrayList<>();
for(int i = 0; i < 30000; i++){
String s = String.valueOf(System.nanoTime());
source.add(s);
if(i % 2 == 0) toRemove.add(s);
}
long startTime = System.nanoTime();
removeList1(source, toRemove);
long endTime = System.nanoTime();
System.out.println("diff: " + (endTime - startTime) * 1e-9);
}
static void removeList1(ArrayList<String> source, ArrayList<String> toRemove){
source.removeAll(toRemove);
}
static void removeList2(ArrayList<String> source, ArrayList<String> toRemove){
for(String s : toRemove){
source.remove(s);
}
}
}
用不同的列表大小调用它几次并在两种方法之间切换。
有几个原因很难给出这个问题的一般答案。
首先,您必须了解这些性能特征是依赖于实现的。 实现很可能取决于JDK的平台和版本。
话虽如此,实施removeAll
主要有两种策略:
ArrayList
每个元素,检查它是否在另一个Collection
; 如果是这样,删除它。 Collection
每个元素,检查它是否在ArrayList
; 如果是这样,删除它。 如果Collection
执行包含in constant-time,则策略1(渐近地)获胜。 另一方面,如果通过扫描整个连接执行contains
并且Collection
非常缓慢地迭代,则策略2通常具有边缘,因为它仅在Collection
迭代一次; 但即使在这种情况下,如果Collection
非常大并且ArrayList
大多数元素都是Collection
的第一个元素,那么策略1再次获胜......它没有尽头。
你可能最好相信removeAll()
的实现; 如果失败,请尝试更改数据结构; 如果这也失败了,请从经验基准中实施自己的方法。
另外需要考虑的事情:
Java的代码经过长时间的争论,编写时可以适应许多不同的特殊情况(请参阅注释Preserve behavioral compatibility with AbstractCollection
)。
所以,实际上你可能会编写自己的方法实现,运行速度会更快。 但另一方面,您确定可以处理自Java诞生以来Java开发人员面临的所有特殊情况吗?
还要考虑到某些Java函数可能正在使用某些C实现来加快速度。 这显然不是这里的情况,但它可以。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.