将混凝土集合浇铸到其界面的性能成本

Cla*_*Bao 0 java performance casting

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

我的问题是ArrayList<Model>,Collection<Model>当传递参数时,例如施放时,是否存在相当大的性能成本.

收集尺寸是否也会影响铸造性能?有什么建议?

谢谢Peter的回答.

我认为答案足以阻止我浪费时间去改变它.

编辑

如在接受的答案中所述,实际上在调用接口方法时支付了成本.保持这种灵活性并不是免费的.但成本并不那么可观.

Pet*_*rey 6

像大多数表演问题一样,答案是; 编写清晰和简单的代码,应用程序通常也可以正常运行.

对接口的强制转换大约需要10 ns(少于方法调用)根据代码的优化方式,它可能太小而无法测量.

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

在转换时,它是更改的引用类型,所有引用都是相同的大小.他们指出的大小并不重要.

BTW:所有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;
}
Run Code Online (Sandbox Code Playgroud)

版画

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
Run Code Online (Sandbox Code Playgroud)

然而,差异可能是由于方法调用更昂贵.唯一的字节码差异是

invokevirtual   #9; //Method java/util/ArrayList.size:()I
Run Code Online (Sandbox Code Playgroud)

invokeinterface #15,  1; //InterfaceMethod java/util/Collection.size:()I
Run Code Online (Sandbox Code Playgroud)

一旦JIT优化了代码,就没有太大区别.运行时间足够长,-server JVM 的时间下降到0 ns,因为它检测到循环没有做任何事情.;)