【问题标题】:Why is initial capacity important for deleting from ArrayList?为什么初始容量对于从 ArrayList 中删除很重要?
【发布时间】:2016-08-27 10:33:07
【问题描述】:

对于我的工作,我对时间表进行了一些测试。 我遇到了令我惊讶的事情,需要帮助来理解它。

我使用很少的数据结构作为队列,想知道根据项目数量删除的速度如何。而具有 10 个项目的 arraylist,从前面删除并且未设置初始容量比设置初始容量(至 15)要慢得多。为什么?以及为什么它在 100 件商品上是一样的。

这是图表:

数据结构:L - 实现列表,C - 设置初始容量,B - 从后面移除,Q - 实现队列

编辑: 附加相关代码

new Thread(new Runnable() {
 @Override
 public void run()
 {
  long time;
  final int[] arr = {10, 100, 1000, 10000, 100000, 1000000};
  for (int anArr : arr)
  {
    final List<Word> temp = new ArrayList<>();
    while (temp.size() < anArr) temp.add(new Item());

    final int top = (int) Math.sqrt(anArr);

    final List<Word> first = new ArrayList<>();
    final List<Word> second = new ArrayList<>(anArr);
    ...
    first.addAll(temp);
    second.addAll(temp);
    ...

    SystemClock.sleep(5000);

    time = System.nanoTime();
    for (int i = 0; i < top; ++i) first.remove(0);
    Log.d("al_l", "rem: " + (System.nanoTime() - time));

    time = System.nanoTime();
    for (int i = 0; i < top; ++i) second.remove(0);
    Log.d("al_lc", "rem: " + (System.nanoTime() - time));

    ...
   }
  }
}).start();

【问题讨论】:

  • 不清楚你对这次的评价如何。是微基准测试吗?它在哪里?你应该提供一些代码来玩。

标签: java


【解决方案1】:

阅读这篇关于Avoiding Benchmarking Pitfalls on the JVM 的文章。它解释了 Hotspot VM 对测试结果的影响。如果你不关心它,你的测量是不正确的。正如您通过自己的测试发现的那样。

如果您想进行可靠的基准测试,请使用JMH

【讨论】:

    【解决方案2】:

    我也可以通过创建下面的代码来复制它。但是,我注意到首先运行的任何内容(设置容量与非设置容量)都是耗时最长的。我认为这是某种优化,可能是 JVM,还是某种缓存?

    public class Test {
    
    
    
    public static void main(String[] args) {
            measure(-1, 10); // switch with line below
            measure(15, 10); // switch with line above
            measure(-1, 100);
            measure(15, 100);
        }
    
        public static void measure(int capacity, long numItems) {
            ArrayList<String> arr = new ArrayList<>();
    
            if (capacity >= 1) {
                arr.ensureCapacity(capacity);
            }
    
            for (int i = 0; i <= numItems; i++) {
                arr.add("T");
            }
            long start = System.nanoTime();
    
            for (int i = 0; i <= numItems; i++) {
                arr.remove(0);
            }
    
            long end = System.nanoTime();
            System.out.println("Capacity: " + capacity + ", " + "Runtime: "
                    + (end - start));
        }
    }
    

    【讨论】:

    • 是的,我的代码几乎相同(在 android 环境中)。但你可能是对的,这只是因为它是第一个。但是,答案是正确的,所以我接受它。我的建议是 JVM,所以如果有 JVM 专家我想听听他的意见。
    猜你喜欢
    • 1970-01-01
    • 2013-03-04
    • 2010-10-14
    • 1970-01-01
    • 2012-08-08
    • 2021-08-03
    相关资源
    最近更新 更多