【发布时间】:2015-05-01 20:34:06
【问题描述】:
如果我想从数组列表中删除一个集合,用什么更好? 我认为 ArrayList 中的 removeAll 方法是为此任务编写的,但在我编写的测试中,仅迭代对象并单独删除它们会快几秒钟。
您为此目的使用什么?
编辑:
我在 grepcode 上找到的 removeAll 代码调用 batchRemove (c, false):
private boolean More ...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);
}
}
}
用不同的列表大小调用它几次并在两种方法之间切换。
【问题讨论】:
-
我预计您的测试中存在缺陷。向我们展示您的测试代码。 (我发现很难相信在性能上真的存在显着差异。在 Java 中编写给出准确结果的基准相当困难。)
-
您为什么不查看 remove 和 removeAll 方法的代码?然而,这个问题不值得被否决。 +1 来自我。有 200 多个赞成票的 SO 问题比这个更糟糕..
-
@bot,请问哪里有进展?
-
@Gabe 我不确定你的意思。
-
正如我所怀疑的,基准代码存在缺陷。您没有正确“预热”JVM,这可能对
removeAll的影响比remove的影响更大。
标签: java performance arraylist collections removeall