java常量循环性能优化

java常量循环性能优化,java,optimization,compiler-optimization,Java,Optimization,Compiler Optimization,我有两段代码: 第一个: List<Integer> integers = new ArrayList<>(); integers.add(0); integers.add(1); //Assume that list will always have the same values with loop indices. //Also any of the methods will not change the size and elements of the list.

我有两段代码:

第一个:

List<Integer> integers = new ArrayList<>();
integers.add(0);
integers.add(1);
//Assume that list will always have the same values with loop indices.
//Also any of the methods will not change the size and elements of the list.

for (int i=0;i<integers.size();i++) {

    if (0 == integers.get(i)) {
        foo();
    }
    else if (1 == integers.get(i)) {
        bar();
    }
}

我知道两个代码段都在做相同的事情,但是性能有什么不同吗?或者JVM是否在编译时或运行时对第一个代码段进行了优化?

第二个代码段效率更高,因为您在第一个代码段中执行了更多的操作,这(显然)需要更多的时间来执行和评估

通常,您可以得出结论,for循环/操作/if语句越多,性能就越差


Java将只进行计算,而不会将其简化为第二个代码段。

编译器/JIT将无法为第一个代码段做很多工作

它无法证明对
integers.get(i)
的连续调用始终会产生相同的结果,因此不允许重用第一次调用的结果,甚至无法判断是否始终会执行
foo()
bar()
中的一个


代码对于人类来说似乎足够简单,但编译器必须对将在运行时加载的
ArrayList
的实现进行假设,而它不会这样做。

在第一个代码段中花费时间的事情: 创建列表对象、向列表中添加元素、向变量中添加值、检查变量是否小于另一个变量、递增变量、跳入代码(中断循环和if语句)、调用方法并执行它们

在第二个sinnpet中: 调用方法和执行方法


如果您将这两个代码段都放入for循环中,并执行1000次或更多次,您将看到很大的不同。

您尝试过吗?但是不,我不希望JIT在这种情况下会有太多的优化。你知道如果我们不使用Arraylist并使用常量(即(int i=0;这将是一个不同的故事-在这种情况下,它可能会选择展开循环,还可能能够找出调用哪个分支,使它们等效。必须测试特定编译器/JIT是否确实对给定代码执行此操作。您能给我一些有关此方面的参考,因为我的问题是s实际上与该主题相关。提前感谢。问题是方法调用-JVM没有看穿它们,什么也不做。但是,当被调用的方法足够小时,它们可能会内联,并且可能会开始大量优化,这可能会导致第二个代码段。我恐怕,在这种情况下不会发生这可能太复杂了。JVM可以预测列表的大小与索引的大小一样严格,并进行一些优化吗?@AlperenÜretmen不,它不会,它必须检查
size()
以确保列表的大小不会改变,因为大小是可变的。它不会改变that@AlperenÜretmen它必须确保
integers
的运行时类型确实是
ArrayList
,然后查找
size()的实现
,不知何故,我发现这只取决于一个字段,并证明该字段不能在循环体中的某个地方进行修改——这将是一项复杂的工作,在一般情况下甚至不可能。谢谢,但我的问题是JVM是否能找出第二个代码段与第一个代码段的工作相同(因为列表只创建一次,之后不会修改)并进行一些优化。
foo();
bar();