java - 为什么将第一项添加到集合中比第二项慢得多?

标签 java performance arraylist collections timing

我发现将第一项和第二项添加到集合(尝试过 ArrayListHashSet)之间存在巨大的性能差异,但我无法解释原因。已搜索但未找到任何答案。

public class Main {

    public static void main(String[] args) {
        // also tried HashSet
        // also tried new ArrayList<>(2)
        ArrayList<String> collection = new ArrayList<>();
        long t1 = System.nanoTime();
        collection.add("a");
        long t2 = System.nanoTime();
        collection.add("b");
        long t3 = System.nanoTime();
        System.out.println(String.valueOf(t2 - t1) + "\n"
                + String.valueOf(t3 - t2));
        //typical output:
        //4399
        //1201
    }
}

一些猜测:

  • 因为在添加第一项时集合被延迟初始化?
  • 还是我使用了错误的方式来衡量绩效?
  • 或与 jvm 的工作原理有关(这超出了我的知识范围)?

环境:jdk11、win10、intellij。

最佳答案

你的三个猜测都是正确的:)

你问了一个好问题。请注意:微基准测试非常危险,您可能很容易对代码各部分的速度做出完全错误的假设。您的惰性初始化是正确的,但这是一个好运气 :)

最重要的是,您“使用错误的方式衡量绩效”的猜测是正确的。

您无法像这样衡量 Java 应用程序的速度。这根本不可能。该过程过于随机并且过于依赖于许多其他因素,尤其是运行时的 JIT(即时优化)。

试试看这里:https://www.baeldung.com/java-microbenchmark-harness ,尝试运行它并思考它是如何工作的。

TL;DR:JVM 必须首先“预热”,然后您必须多次运行测试代码并计算平均时间。而且仍然可能有很多优化导致一些代码根本没有执行:)

如果您不想玩微基准库,至少将您的代码移到一个方法中并调用该方法 20 次。我只是做了(只是将\n替换为---),结果是这样的:

10800---1400
1500---200
600---100
500---100
700---100
400---100
400---100
400---100
400---100
500---100
400---100
400---100
400---100
400---100
300---100
400---100
300---100
500---100
400---100
300---100

如您所见,热身是最重要的因素。然而,惰性初始化的影响也是可见的。

关于java - 为什么将第一项添加到集合中比第二项慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70581310/

相关文章:

具有多个参数的 Java 方法 - 性能

c# - 合并排序的 IEnumerable<T> 的最有效算法

java - 如何使用 BaseAdapter 刷新我的 ListView

Java 支持服务器角色中的服务器名称指示 (SNI)?

javascript - 运行 react native Android 应用程序时出错 - BatchedBridge

抛出 NoSuchAlgorithException 的 Java SSL 代码

java - 良好的性能指标 API?

java - 缺线?从.txt文件读取字符串并放入数组(java)

java - 否则没有if?

java - 相互比较两个 REST 服务