java - 将具体集合类型转换到其接口(interface)的性能成本

标签 java performance casting

当我编写一些API时,有时会使用Collection<Model>为参数。当然,你可以使用ArrayList如果你知道ArrayList已经足以处理所有用例。

我的问题是,例如转换 ArrayList<Model> 时是否会产生相当大的性能成本?至Collection<Model>传递参数时。

集合大小也会影响类型转换的性能吗?有什么建议吗?

感谢彼得的回答。

我认为答案足够漂亮,足以阻止我浪费时间进行更改。

编辑

正如接受的答案中所说,成本实际上是在接口(interface)方法的调用中付出的。 保持这种灵 active 并不是免费的。但成本并没有那么可观。

最佳答案

与大多数性能问题一样,答案是:编写清晰且简单的代码,应用程序通常也能正常运行。

转换为接口(interface)可能需要大约 10 ns(少于方法调用),具体取决于代码的优化方式,它可能太小而无法测量。

泛型类型之间的转换是编译器时间检查,运行时实际上什么也没有发生。

当你转换时,改变的是引用类型,所有引用的大小相同。它们所指向的内容的大小并不重要。

顺便说一句:所有 ArrayList 对象的大小相同,所有 LinkedList 对象的大小相同,所有 HashMap 对象的大小相同等等。它们可以引用一个数组,该数组在不同的集合中可以有不同的大小。

<小时/>

您可以看到未经 JIT 处理的代码中的差异。

public static void main(String... args) throws Throwable {
  ArrayList<Integer> ints = new ArrayList<>();
  for(int i=0;i<100;i++) ints.add(i);
  sumSize(ints, 5000);
  castSumSize(ints, 5000);
  sumSize(ints, 5000);
  castSumSize(ints, 5000);
}

public static long sumSize(ArrayList<Integer> ints, int runs) {
  long sum = 0;
  long start = System.nanoTime();
  for(int i=0;i<runs;i++)
    sum += ints.size();
  long time = System.nanoTime() - start;
  System.out.printf("sumSize: Took an average of %,d ns%n", time/runs);
  return sum;
}

public static long castSumSize(ArrayList<Integer> ints, int runs) {
  long sum = 0;
  long start = System.nanoTime();
  for(int i=0;i<runs;i++)
    sum += ((Collection) ints).size();
  long time = System.nanoTime() - start;
  System.out.printf("castSumSize: Took an average of %,d ns%n", time/runs);
  return sum;
}

打印

sumSize: Took an average of 31 ns
castSumSize: Took an average of 37 ns
sumSize: Took an average of 28 ns
castSumSize: Took an average of 34 ns

但是差异可能是由于方法调用更昂贵。唯一的字节码差异是

invokevirtual   #9; //Method java/util/ArrayList.size:()I

invokeinterface #15,  1; //InterfaceMethod java/util/Collection.size:()I

一旦 JIT 优化了代码,就不会有太大区别。运行足够长的时间,-server JVM 的时间会降至 0 ns,因为它检测到循环没有执行任何操作。 ;)

关于java - 将具体集合类型转换到其接口(interface)的性能成本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7309703/

相关文章:

java - 使用 ByteBuffer 处理 byte[]

java - 如何将纪元的年月日转换为正确的 UTC 毫秒?

c - SPI写STM32很慢

c++ - 为什么这个 for 循环使用 OpenMP 没有更快?

c# - 如何形成 TaskCompletionSource<T> 的集合并保持类型安全

java - 我可以在 Android 拔下电源并处于 hibernate 状态时唤醒它吗?

java - 为什么我的正则表达式在 shell 脚本中失败,尽管它在 jregex 中工作?

excel - 更有效的写法是什么?

java:接口(interface)和模板

swift - 如何快速将自身转换为UnsafeMutablePointer <Void>类型