详解Java集合的'Clear()' API - yCrash

作者:API传播员 · 2025-11-04 · 阅读时间:5分钟

我们中的一些人可能已经熟悉 Java 集合框架。在这篇文章中,我们将深入探讨 clear() API 的用途、它对性能的影响以及调用该 API 时 JVM 内部的运行机制。


clear() API 的作用

clear() 方法是 Java 集合框架中 Collection 接口的一部分,由实现该接口的所有具体类(如 ArrayListTreeSetStack)实现。当调用此方法时,它会清空集合中所有的元素。


ArrayList 的 clear() 方法在 Java 中的工作原理

本文将重点分析 ArrayListclear() 方法实现,其它集合的实现方式与之类似。在 ArrayList 的底层,数据存储在一个 Object[] 数组中。当向 ArrayList 添加元素时,这些元素会存储在该数组中。

当调用 clear() 方法时,Object[] 数组中的所有元素都会被清除。例如,假设我们创建了一个包含 100 万个整数的 ArrayList,调用 clear() 方法后,数组中的所有元素都会被删除。然而,底层的 Object[] 数组仍然存在,占用内存空间。


创建 ArrayList 示例

通过以下示例代码,我们可以更直观地了解 clear() 方法的功能:

public class ClearNoDemo {
    private static ArrayList myList = new ArrayList();

    public static void main(String[] args) throws Exception {
        for (int counter = 0; counter < 1_000_000; ++counter) {
            myList.add(Long.valueOf(counter));
        }
        System.out.println("所有记录都已添加!");
        Thread.sleep(10000); // 休眠10秒
    }
}

在上述代码中:

  1. 第 3 行创建了一个 ArrayList 类型的 myList 对象。
  2. 第 7 至 10 行向 myList 添加了 100 万个 Long 类型的对象。
  3. 第 14 行让线程休眠 10 秒,以便捕获堆转储并分析内存使用情况。

运行程序后,通过堆转储分析工具可以发现,myList 是内存中最大的对象,其底层的 Object[] 数组占用了 27.5 MB 的内存。这表明,添加的对象存储在内部的 Object[] 数组中。


调用 clear() 方法的示例

以下是一个修改后的示例代码,在其中调用了 clear() 方法:

public class ClearDemo {
    private static ArrayList myList = new ArrayList();

    public static void main(String[] args) throws Exception {
        for (int counter = 0; counter < 1_000_000; ++counter) {
            myList.add(Long.valueOf(counter));
        }
        long startTime = System.currentTimeMillis();
        myList.clear();
        System.out.println("执行时间:" + (System.currentTimeMillis() - startTime));
        Thread.sleep(10000); // 休眠10秒
    }
}

在上述代码中:

  1. 第 3 行创建了一个 ArrayList 类型的 myList 对象。
  2. 第 7 至 10 行向 myList 添加了 100 万个 Long 类型的对象。
  3. 第 13 行调用了 clear() 方法清空集合。
  4. 第 16 行让线程休眠 10 秒,以便捕获堆转储并分析内存使用情况。

调用 clear() 方法后,底层的 Object[] 数组虽然清空了所有元素,但数组本身仍然存在,占用了 4.64 MB 的内存。这表明,即使通过 clear() 方法清除了对象,底层数组仍然会占用内存。


将列表赋值为 null 的示例

以下是将列表赋值为 null 的示例代码:

public class ClearNullDemo {
    private static ArrayList myList = new ArrayList();

    public static void main(String[] args) throws Exception {
        for (int counter = 0; counter < 1_000_000; ++counter) {
            myList.add(Long.valueOf(counter));
        }
        long startTime = System.currentTimeMillis();
        myList = null;
        System.out.println("执行时间:" + (System.currentTimeMillis() - startTime));
        Thread.sleep(10000); // 休眠10秒
    }
}

在上述代码中:

  1. 第 3 行创建了一个 ArrayList 类型的 myList 对象。
  2. 第 7 至 10 行向 myList 添加了 100 万个 Long 类型的对象。
  3. 第 13 行将 myList 赋值为 null

将列表赋值为 null 后,ArrayList 和底层的 Object[] 数组都可以被垃圾回收,从而释放内存。通过堆转储分析工具可以发现,myList 对象已经从内存中移除。


内存影响

下图展示了 ArrayList 在不同情况下的内存占用情况:


处理时间影响

以下是 ArrayList#clear() 方法的源码实现:

public void clear() {
    modCount++;
    final Object[] es = elementData;
    for (int to = size, i = size = 0; i < to; i++) {
        es[i] = null;
    }
}

从源码可以看出,clear() 方法会遍历底层的 Object[] 数组,将每个元素设置为 null,这会消耗一定的处理时间。


何时使用 Collection#clear() API?

尽管 clear() 方法可能会影响内存和性能,但在以下情况下使用它是合理的:

  1. 通过引用传递集合对象:如果集合对象被作为引用传递给代码的其他部分,直接赋值为 null 会导致 NullPointerException,此时可以使用 clear() 方法。
  2. 集合大小较小:当集合实例较少且每个集合的大小较小时,调用 clear() 方法或赋值为 null 的性能差异可以忽略不计。

结论

通过本文的分析,我们详细了解了 clear() API 的功能及其对性能的影响。在实际开发中,应根据具体场景选择合适的方法来清理集合,以平衡性能和内存使用。

原文链接: https://blog.ycrash.io/clear-details-on-java-collection-clear-api/