有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

性能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;
}

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;
}

共 (2) 个答案

  1. # 1 楼答案

    We all agree the code is more readable with a single return.

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

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

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

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

    在我看来,您的第二个示例不仅可读性更强(变量valueFound只是额外的噪声),而且速度更快,因为它在执行任务时只返回。如果在设置valueFound = true之后加上break,第一个例子的速度会一样快。如果你不这样做,你有一百万个项目要检查,而你需要的项目是第一个,你将毫无意义地比较所有其他项目

  2. # 2 楼答案

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

    具体来说,添加一个提前返回将改变thingIterator.hasNext()的调用次数,因为第一个代码块将继续迭代集合到最后

    Java可能会用提前返回来取代break,但这会对程序的时间安排产生任何影响