java编译器可以优化循环以提前返回吗



我正在处理一个外部库,该库决定自己处理集合。不使用它或更新是我无法控制的。为了处理这个第三方"集合"的元素,它只返回迭代器。

在一次代码审查中,出现了一个问题,即在代码中进行多次返回以获得性能。我们都同意(在团队内部(只需一次返回,代码就更可读,但有些人担心优化。

我知道过早的优化是不好的。这是另一天的话题。

我相信JIT编译器可以处理这一问题并跳过不必要的迭代,但找不到任何信息来支持这一点JIT能做这样的事情吗

手头问题的代码示例:

public void boolean contains(MyThings things, String valueToFind) {
Iterator<Thing> thingIterator = things.iterator();
boolean valueFound = false;
while(thingIterator.hasNext()) {
Thing thing = thingIterator.next();
if (valueToFind.equals(thing.getValue())) {
valueFound = true;
}
}
return valueFound;
}

public void boolean contains(MyThings things, String valueToFind) {
Iterator<Thing> thingIterator = things.iterator();
while(thingIterator.hasNext()) {
Thing thing = thingIterator.next();
if (valueToFind.equals(thing.getValue())) {
return true;
}
}
return false;
}

我们都同意,只需一个返回,代码就更可读。

不是。这只是老式的结构化编程,当时函数通常不保持较小,保持值不变的范式还不流行。

尽管存在争议,但拥有在不同点返回的非常小的方法(几行代码(并没有错。例如,在递归方法中,通常至少有一个立即返回的基本情况,另一个返回递归调用返回的值。

通常你会发现,创建一个额外的结果变量,只是为了保存返回值,然后确保函数的其他部分不会覆盖结果,当你已经知道你可以返回时,只会产生噪音,使其可读性降低,而不是更高。读者必须处理认知过载,才能看到结果不会被进一步修改。在调试过程中,这会更加增加痛苦。

我不认为你的例子是过早的优化。它是搜索算法的一个逻辑和关键部分。这就是为什么您可以从循环中break,或者在您的情况下,只返回值。我不认为JIT能轻易地意识到它应该打破循环。如果在集合中找到其他内容,它不知道您是否要将变量更改回false。(我认为意识到valueFound不会变回false并不明智(。

在我看来,您的第二个示例不仅可读性更强(valueFound变量只是额外的噪声(,而且速度更快,因为它只是在完成任务时返回。如果在设置valueFound = true之后放置break,则第一个示例的速度会很快。如果你不这样做,并且你有一百万个项目要检查,而你需要的项目是第一个,你将免费比较所有其他项目。

Java编译器不能进行这样的优化,因为在一般情况下这样做会改变程序的逻辑。

具体来说,添加早期返回将更改thingIterator.hasNext()的调用次数,因为您的第一个代码块将继续迭代集合直到结束。

Java可能会提前返回break,但这会对程序的时间产生任何影响。

最新更新