仿写ArrayList时,针对clear方法,产生了jvm结果的困惑

背景

最近刷题学数据结构,研究ArrayList时因为仿写的ArrayList实现手段与JDK不同(clear方法),测试结果与预期的有偏差(我仿写的效果居然更好),请教有经验的猿们具体啥情况。(是我测试有错,还是我结果看的不对,又或者是别的情况)

代码

clear方法

JDK1.8

public void clear() {
    modCount++;
    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    size = 0;
}

仿写

/**
 * 空值
 */
private static final Object[] EMPTY_ELEMENT = {};
public void clear() {
    size = 0;
    elements = EMPTY_ELEMENT;
}

最大的差异就是我没有for循环遍历逐个清空。

测试方法

clear2()是仿照JDK写的方法。

public static void test1() {
    MyArrayList<Integer> myArrayList = new MyArrayList<Integer>(1);
    for (int i = 0; i < 10000000; i ++) {
        myArrayList.add(i);
    }
    myArrayList.clear();
    System.gc();
}

public static void test2() {
    MyArrayList<Integer> myArrayList = new MyArrayList<Integer>(1);
    for (int i = 0; i < 10000000; i ++) {
        myArrayList.add(i);
    }
    myArrayList.clear2();
    System.gc();
}

测试结果

[GC (Allocation Failure)  28672K->18629K(110080K), 0.0730491 secs]
[GC (Allocation Failure)  47301K->37091K(138752K), 0.0912045 secs]
[GC (Allocation Failure)  79231K->79292K(138752K), 0.2543684 secs]
[Full GC (Ergonomics)  79292K->69918K(226304K), 2.4897254 secs]
[GC (Allocation Failure)  158404K->135196K(254464K), 0.3057838 secs]
[Full GC (Ergonomics)  135196K->121269K(348672K), 3.9478386 secs]
[GC (Allocation Failure)  206773K->206862K(377856K), 0.3599932 secs]
[Full GC (Ergonomics)  206862K->175546K(514560K), 6.3232826 secs]
[GC (System.gc())  205257K->203994K(599040K), 0.2672577 secs]
[Full GC (System.gc())  203994K->966K(599040K), 0.0135492 secs]
================================
[GC (Allocation Failure)  122822K->81343K(595968K), 0.2753535 secs]
[GC (Allocation Failure)  178133K->156860K(625664K), 0.6571283 secs]
[GC (System.gc())  236044K->109967K(667648K), 0.1013700 secs]
[Full GC (System.gc())  109967K->47679K(667648K), 0.0593073 secs]

疑问

针对网上的教程帖子,例如下文:

https://www.polarxiong.com/archives/Java-%E5%AF%B9%E8%B1%A1%E4%B8%8D%E5%86%8D%E4%BD%BF%E7%94%A8%E6%97%B6%E8%B5%8B%E5%80%BC%E4%B8%BAnull%E7%9A%84%E4%BD%9C%E7%94%A8%E5%92%8C%E5%8E%9F%E7%90%86.html

再加上JDK的写法,针对gc机制,都是设置null触发。为什么我的方案直接设置为空,等价于new一个新的对象,不管之前内容的占用会清理的更好?是我理解有误还是JDK做了别的优化?

配置的vmoption:-verbose:gc

项目完整内容在github上:

https://github.com/wyue1227/DataStructuresAndAlgorithms/blob/main/src/com/yue/season1/class02/Main.java

你这个写法应该有点问题,当调用了clear 方法后,不能再做添加元素的操作了。

你有算过总时间吗?我觉得不管怎样都是差不多的。

你只是把当前变量指向了一个为空的内存地址把,那JVM怎么知道原来的List的内存地址是否需要GC?那么是否会占用内存,你可以看看具体处理完后,不手动GC的内存消耗

只是我的观点,具体没论证