繁体   English   中英

java编译器可以优化循环以尽早返回吗?

[英]Can the java compiler optimize loops to return early?

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

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

我知道过早的优化很糟糕。 这是另一天的话题。

我相信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;
}

VS

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()的调用thingIterator.hasNext() ,因为您的第一个代码块会继续将集合迭代到最后。

Java可以用早期的返回来代替break ,但这会对程序的时间产生任何影响。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM