ArrayList.clear()和ArrayList.removeAll()有什么区别?


283

假设arraylist定义为ArrayList<String> arraylistarraylist.removeAll(arraylist)等于arraylist.clear()

如果是这样,我clear()是否可以认为该方法更有效地清空数组列表?

使用arraylist.removeAll(arraylist)代替有什么注意事项arraylist.clear()吗?


这个问题的一个可能推论:什么时候可以代替一个?
Corey Ogburn

3
@Corey:每个人何时想使用arraylist.removeAll(arraylist)?我绝对没有理由这样做。
约阿希姆·绍尔

@Joachim Sauer正是我要验证的内容。谢谢+2。但是elementData[i] = null和之间有e.remove()显着差异吗?
ateiob 2011年

没有理智的理由arrList.removeAll(arrList)代替arrList.clear()arrList1.removeAll(arrList2)是另一回事。
弗拉德

3
如果仅removeAll()的实现是从这一行开始的,那么整个讨论可能会更加有趣!!! if (c == this && !isEmpty()) { clear(); return true; }。我将把它作为补丁提交给OpenJDK!;-)
Julius Musseau

Answers:


396

的源代码clear()

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

的源代码removeAll()(如中所定义AbstractCollection):

public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    Iterator<?> e = iterator();
    while (e.hasNext()) {
        if (c.contains(e.next())) {
            e.remove();
            modified = true;
        }
    }
    return modified;
}

clear() 更快,因为它不必处理所有这些额外的方法调用。

正如Atrey所指出的,与的O(n )相比,c.contains(..)增加了removeAllO(n 2)的时间复杂度clear


29
c.contains(...)将运算的时间复杂度平方成平方的音符将使该答案完整。
阿特里斯

8
来源很强大。(对于所有其他答案:使用源代码Luke。)请注意如何将clear()仅实现为size = 0的一行;但是垃圾收集将不知道如何收集数组无法访问的部分中的元素。
Julius Musseau

2
e.remove()更加复杂!e.remove()也使复杂度平方,就像c.contains(...)一样。在ArrayList上,e.remove()调用ArrayList.remove(int index),该方法必须将数组的其余部分移动一个。
Julius Musseau

1
@ateiob e.remove()是两个额外的方法调用,范围检查和对象返回(内部AbstractList.Itr.remove()ArrayList.remove(int)),太
Atreys

2
@julius如果这样做:size = 0; elementData = new Object[10];由于支持数组没有外部引用,所有其余部分将被垃圾回收。
corsiKa 2011年

51

的时间复杂度ArrayList.clear()O(n)removeAllIS O(n^2)

是的,ArrayList.clear速度要快得多。


15

clear()方法删除单个元素的所有元素ArrayList。这是一项快速的操作,因为它只是将数组元素设置为null

removeAll(Collection)从继承的方法AbstractCollection从调用该方法的集合中删除参数集合中的所有元素。这是一个相对较慢的操作,因为它必须搜索所涉及的集合之一。


我认为这只是将所有内容而不是某些元素设置为null。如果不是这种情况,如何决定应将哪些元素设置为null?
Farid

2
@Farid对不起,我的英语在这里太随意了。我的确意味着将所有元素设置为null。我会解决的!
欧内斯特·弗里德曼·希尔

7

除非有具体的优化来检查,如果该参数传递到removeAll()是集合本身(我高度怀疑,这样的优化是存在的),这将是显著慢于简单.clear()

除此之外(至少同等重要):arraylist.removeAll(arraylist)只是令人费解,令人困惑的代码。说“清除此收藏集”是一种非常落后的方式。与非常容易理解的 相比,它有什么优势arraylist.clear()



5

clear() 将遍历基础Array并将每个条目设置为null;

removeAll(collection)将通过ArrayList检查remove(Object)是否存在集合(如果存在)。

我想这clear()比removeAll快得多,因为它没有比较,等等。


2

清除速度更快,因为它不会循环显示要删除的元素。此方法可以假定可以删除所有元素。

Remove all不一定意味着删除列表中的所有元素,仅应删除作为参数提供的元素。因此,需要更多的努力来保留不应删除的内容。

澄清说明

“循环”是指不必检查是否应保留该元素。它可以设置引用为,null而无需搜索提供的要删除的元素列表。

Clear比快deleteall


1
我很确定这ArrayList.clear()也必须循环。
约阿希姆·绍尔

@JVerstry您是不是说clear()不会删除它从ArrayList中删除的元素?
ateiob 2011年

1
错误的做法是,clear会循环遍历内部数组,并将所有引用都设置为null,以使垃圾回收器完成其工作。
devconsole

1
@ Joachim,@ devconsole:我认为他的意思是不必循环/迭代作为参数给出的列表。target.removeAll(param)将迭代param,然后调用target.contains(...)进行迭代target
弗拉德

2
-3有点苛刻。如果JVerstry愿意,他可以从头编写没有循环的Java实现。clear()可以在没有循环的情况下在O(1)中实现,而removeAll()必须具有某种O(n)算法,如果不检查所有元素,就无法满足removeAll()API的约定。
朱利叶斯·穆索

1

clear()将更加高效。它只会删除每个项目。使用removeAll(arraylist)会花费更多的工作,因为它将在删除它之前检查arraylist中的每个项目以查看是否存在于arraylist中。


-8

Array =>一旦在运行时为Array变量分配了空间,就不能扩展或删除分配的空间。

ArrayList =>在arraylist中不是这种情况。ArrayList可以在运行时增长和收缩。可以在运行时最小化或最大化分配的空间。


这没有回答这个问题,即ArrayList.clear()和ArrayList.removeAll()之间的区别,而不是Array和ArrayList之间的区别。
Pierre

这个答案是不必要的。这不是问题所在。
Serafim Costa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.