`

arraylist removeAll 与 clear 区别

    博客分类:
  • JAVA
 
阅读更多

很多时候为了重用我们会想要重置一个ArrayList,这里的重置是指清空列表或移除列表所有的元素。在Java中,有两个方法可以帮助我们实现重置clearremoveAll。在列表长度很小的情况下(eg:10或100个元素),可以放心的使用这两种方法。但如果列表很大(eg:10M个元素),那么选择clear还是removeAll会对你java应用的性能造成巨大的影响。甚至有时,在列表过大的情况下,重置会耗费许多时间,那么重新创建一个新的列表比将老的列表重置要好。但需要提醒的是,必须要确保老的列表可以被垃圾回收,否则,有很大的风险会出现java.lang.OutOfMemoryError: Java Heap Space。言归正传,让我们看看clear()和removeAll()两个方法。大家应该常常会选择用clear(),因为他的复杂度是O(n),而相比之下,removeAll(Collection C)的性能要差一些,它的复杂度是O(n^2)。这也是为什么在重置大的列表的时候两个方法会有巨大的差异。如果阅读他们的源码并运行下面的例子程序,差异会更明显。

 

Clear() vs RemoveAll(Collection c)

 

为了更好的比较这两个方法,阅读他们源码是很重要的。可以在java.utils.ArrayList类中找到clear()方法,不过为了方便我将它引入到了这里。下面的代码来自JDK 1.7.0_40版本。如果你想要学习更多的有关性能监控和调优的知识,我强烈建议阅读Scott Oaks写的Java Performance the Definitive Guide,它包含了java 7和一点java 8。下面是clear()的代码片段:

  1.  
    /**
  2.  
    * Removes all of the elements from this list.The list will
  3.  
    * be empty after this call returns.
  4.  
    */
  5.  
    public void clear() {
  6.  
    modCount++; // clear to let GC do its work
  7.  
    for (int i = 0; i < size; i++)
  8.  
    elementData[i] = null;
  9.  
    size = 0;
  10.  
    }

大家可以看出,clear()在循环遍历ArrayList,并且将每一个元素都置为null,使它们在没有被外部引用的情况下可以被垃圾回收。相似的,我们可以在java.util.AbstractCollection类中查看removeAll(Collention c)的代码,下面是代码片段:

 

  1.  
    public boolean removeAll(Collection<?> c) {
  2.  
    //判断对象是否为null
  3.  
    Objects.requireNonNull(c);
  4.  
    boolean modified = false;
  5.  
    Iterator<?> it = iterator();
  6.  
    while (it.hasNext()) {
  7.  
    if (c.contains(it.next())) {
  8.  
    it.remove();
  9.  
    modified = true;
  10.  
    }
  11.  
    }
  12.  
    return modified;
  13.  
    }

这个方法会检查迭代器顺序返回的每个元素是否包含在特定的集合中。如果存在,调用迭代器的remove方法将它从集合中移除。因为会用到contains方法,removeAll的复杂度是O(n^2)。所以在想要重置一个大的ArrayList时,这种方法是绝对不可取的。下面我们比较一下两者在重置一个包含100K个元素时的性能差异。

删除一个包含100k个元素的列表中的所有元素

我本来想在例子中尝试重置一个包含10M个元素的列表,不过在超过半个小时等待removeAll()结束后,我决定将元素的数量降为100K。在这种情况下,两个方法的差距也是很明显的。removeAll()比clear()多花费了10000倍的时间。事实上,在API中clear()和removeAll(Collection c)这两个方法的目的是不同的。clear()方法是为了通过删除所有元素而重置列表,而removeAll(Collection c)是为了从集合中删除某些存在于另一个提供的集合中的元素,并不是为了从集合中移除所有元素。所以如果你的目的是删除所有元素,用clear(),如果你的目的是删除某些存在于另一集合的元素,那么选择removeAll(Collection c)方法。

  1.  
    import java.util.ArrayList;
  2.  
    /**
  3.  
    * Java Program to remove all elements from list in Java and comparing
  4.  
    * performance of clearn() and removeAll() method.
  5.  
    * * @author Javin Paul
  6.  
    */
  7.  
    public class ArrayListResetTest {
  8.  
     
  9.  
    private static final int SIZE = 100_000;
  10.  
    public static void main(String args[]) {
  11.  
     
  12.  
    // Two ArrayList for clear and removeAll
  13.  
    ArrayList numbers = new ArrayList(SIZE);
  14.  
    ArrayList integers = new ArrayList(SIZE);
  15.  
    // Initialize ArrayList with 10M integers
  16.  
    for (int i = 0; i < SIZE; i++) {
  17.  
    numbers.add(new Integer(i));
  18.  
    integers.add(new Integer(i));
  19.  
    }
  20.  
    // Empty ArrayList using clear method
  21.  
    long startTime = System.nanoTime();
  22.  
    numbers.clear();
  23.  
    long elapsed = System.nanoTime() - startTime;
  24.  
    System.out.println("Time taken by clear to empty ArrayList of 1M elements (ns): " + elapsed);
  25.  
    // Reset ArrayList using removeAll method
  26.  
    startTime = System.nanoTime();
  27.  
    integers.removeAll(integers);
  28.  
    long time = System.nanoTime() - startTime;
  29.  
    System.out.println("Time taken by removeAll to reset ArrayList of 1M elements (ns): " + time);
  30.  
    }
  31.  
    }
  32.  
     
  33.  
    Output:
  34.  
    Time taken by clear to empty ArrayList of 100000 elements (ns): 889619
  35.  
    Time taken by removeAll to reset ArrayList of 100000 elements (ns): 36633112126

由于程序使用了两个arrayList存储Integers,所以在运行时要确保有足够的内存,尤其是你想比较在列表存有1M个元素时,两种方法的性能差异。另外,由于使用了在数字中加入下划线的特性,所以需要java7来运行。如果没有JDK7,也可以移除SIZE常量中的下划线。

 


以上就是关于如何重置一个ArrayList的内容。我们不仅仅学到了两种从列表中删除元素的方法,也学到了clear()和removeAll()方法的区别。我们明白了为什么在列表过大时,removeAll()性能很差。
PS:当使用clear()方法也消耗很长的时间时,考虑创建一个新的列表,因为java可以很快的创建一个新的对象。

分享到:
评论

相关推荐

    List.removeAll() 方法的性能效率

    在Java编程语言中,`List.removeAll()`方法是一个非常实用的函数,它允许我们从列表中一次性移除所有指定元素。这个方法是集合框架的一部分,它提供了高效的方式来进行元素的删除操作。本文将深入探讨`removeAll()`...

    ArrayList上机练习1

    - `removeAll`方法:移除列表中所有匹配给定集合的元素。 - `removeRange`方法:删除指定范围内的元素。 - `clear`方法:清空列表的所有元素。 - `contains`方法:检查列表是否包含指定元素。 创建`MyList`...

    arraylist使用方法

    `AddPlayer`方法用于向对应的ArrayList中添加演员,`ShowAll`方法则可能用于遍历并展示所有演员的表演方式。这展示了如何在实际项目中利用ArrayList来管理和操作自定义类型的数据。 总结来说,ArrayList在Java中是...

    ArrayList详解和使用示例_动力节点Java学院整理

    + boolean removeAll(Collection&lt;?&gt; collection):删除集合 + boolean retainAll(Collection&lt;?&gt; collection):保留集合 + int size():获取大小 + &lt;T&gt; T[] toArray(T[] array):转换为数组 + Object[] toArray...

    java基础——集合ArrayList ,LinkedList

    目录前言数组与集合区别集合描述集合格式方法ArrayList实例1.add(E e)2.add(int index, E element)3.addAll(Collection c)4.clear() 与 isEmpty()5.contains(Object o)6.indexOf(Object o)7.iterator()8.remove(int ...

    java代码-使用集合ArrayList对字符串进行存储和管理

    list.removeAll(Arrays.asList("要删除的字符串1", "要删除的字符串2")); ``` 八、判断元素是否存在 使用`contains()`方法可以检查ArrayList是否包含特定元素: ```java boolean contains = list.contains("某字符...

    java代码-使用集合ArrayList对字符串进行存储和管理。

    10. **集合操作**:ArrayList支持多种集合操作,如`addAll()`(合并两个列表)、`retainAll()`(保留两个列表的交集)、`removeAll()`(移除与指定列表相同的元素)等。 在实际开发中,我们通常会结合使用这些方法...

    JAVA集合详解

    - **removeAll(Collection c)**:移除集合中包含指定集合的所有元素。 - **clear()**:清空集合中的所有元素。 ##### 2. Collection的常用方法示例 下面是一个简单的示例代码,展示了如何使用`Collection`接口的...

    CacheManager.java 管理缓存

    public synchronized static void clearAll() { cacheMap.clear(); } /** * 清除指定的缓存 * * @param key */ public synchronized static void clearOnly(String key) { cacheMap.remove(key); ...

    ThinkinginJava之Set接口、HashSet源码学习.pdf

    - **其他方法**:addAll、retainAll、removeAll和clear等方法都是通过HashMap的相应方法来实现的,以保持元素唯一性。 HashSet与其它Set实现(如TreeSet)的主要区别在于效率和排序。TreeSet使用红黑树结构,保证...

    学习笔记 java\CoreJava笔记\CoreJava_day11

    List接口中的方法如`add()`、`add(int index, E element)`、`addAll()`、`clear()`、`equals()`、`get()`、`hashCode()`、`remove()`、`removeAll()`、`retainAll()`和`set()`等,提供了对列表的常用操作。...

    java8源码-note:笔记

    removeAll 的实现 1.3 包装类型 1.4 关于JVM 1.5 泛型 1.6 锁 1.7 浮点数 1.8 ArrayList.toArray() 1.9 String 1.10 HTTP 1.11 HashMap 2.进阶 2.1 关于Java8 stream的使用 2.2 关于读写分离遇到的问题 2.3 对象引用...

    _Java-集合容器-2.List及其实现类.ppt

    - `removeAll(Collection c)`:移除列表中所有属于指定集合的元素。 - `clear()`:移除所有元素。 - `contains(Object o)`:检查列表是否包含指定元素。 - `containsAll(Collection c)`:检查列表是否包含指定集合的...

    java---核心编程

    - 常用方法:`add()`用于添加元素,`addAll()`用于合并两个集合,`contains()`检查集合是否包含特定元素,`containsAll()`检查集合是否包含所有指定元素,`clear()`清除集合所有元素,`isEmpty()`检查集合是否为空...

    Java的集合框架和StreamAPI

    基本操作包括 add、remove、contains、isEmpty、size 等,批量操作包括 addAll、removeAll、retainAll、clear 等。 Stream API 是 Java 8 中引入的一组接口和类,用于对集合进行函数式编程。Stream API 提供了多种...

    Java集合讲义大全.docx

    Collection 是 List 和 Set 的父接口,在 Collection 中定义了一些主要方法,例如 add、addAll、clear、contains、containsAll、equals、hashCode、isEmpty、iterator、remove、removeAll 和 retainAll 等。...

    vector_java

    - `removeAll(Collection&lt;?&gt; c)`:从向量中移除指定集合中的所有元素。 - `removeAllElements()`:移除向量中的所有元素,使其大小变为零。 - `removeElement(Object obj)`:移除第一个匹配的指定元素。 - `...

    黑马程序员java培训就业班笔记集合体系总结.docx

    - `removeAll(Collection&lt;?&gt; c)`: 从当前集合中移除另一集合的所有元素。 - `clear()`: 清空集合。 - `contains(Object o)`: 检查集合中是否存在给定对象。 - `isEmpty()`: 判断集合是否为空。 - `size()`: ...

Global site tag (gtag.js) - Google Analytics