首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在开始迭代之前检查Java集合是否为空有用吗?

问在开始迭代之前检查Java集合是否为空有用吗?
EN

Stack Overflow用户
提问于 2014-10-15 04:08:18
回答 4查看 8.8K关注 0票数 7

在下面的两种样式中,分配了一个Iterator对象。在迭代之前检查集合是否为空有用吗?我不知道这是否可以算是“过早优化”。希望对JVM垃圾收集器有深入了解的人能够提供洞察力。

另外,我不知道Java编译器如何处理-每个循环。我假设style B会自动转换为style A。但是..。也许还包括了一张空支票。

循环样式A

代码语言:javascript
复制
Collection<String> collection = ...
Iterator<String> iter = collection.iterator();
while (iter.hasNext()) {
    String value = iter.next();
    // do stuff
    // maybe call iter.remove()
}

循环式B型

代码语言:javascript
复制
Collection<String> collection = ...
for (String value : collection) {
    // do stuff
}

循环样式A(改进型)

代码语言:javascript
复制
Collection<String> collection = ...
if (!collection.isEmpty()) {
    Iterator<String> iter = collection.iterator();
    while (iter.hasNext()) {
        String value = iter.next();
        // do stuff
        // maybe call iter.remove()
    }
}

循环样式B(改进型)

代码语言:javascript
复制
Collection<String> collection = ...
if (!collection.isEmpty()) {
    for (String value : collection) {
        // do stuff
    }
}
EN

回答 4

Stack Overflow用户

发布于 2019-12-04 12:24:23

是的,这肯定是一个过早的优化,如果它能有帮助的话。您的循环必须具有极其重要的性能,并且通常使用空集合调用,并且由于某种原因无法优化创建实际迭代器对象的大部分成本。

在这场完美的风暴中,这种巨大的源头丑陋可能是有道理的。但更有可能的是,您可以重新安排一些东西来帮助编译器进行更好的优化,比如保持迭代器的本地性。

迭代器对象是(通常?)函数--本地函数,因此创建起来很便宜(只需要驻留在寄存器中,不需要堆分配)。如果转义分析证明JVM是纯本地的,其他代码看不到对它的引用,请参阅https://www.beyondjava.net/escape-analysis-java获取有关JVM如何对对象进行“标量替换”的详细信息。因此,可能的节省甚至不包括内存分配。

如果这样做了,在执行某些操作之前将JIT编译成单独的检查,那么即使集合不是空的,也总是会运行额外的指令。

对最常见的情况进行优化。没有添加额外的代码来稍微加快罕见的空情况,而忽略它来加快常见的非空情况。

我认为大多数循环倾向于在非空集合上运行。小的在某些情况下是常见的,但是空的通常是罕见的。也许您有一个循环,经常或通常在空集合上运行,例如程序中很少使用的特性。那么,对这种情况进行优化是值得考虑的。(这是否是一种有用的方法,则是另一回事)

如果JIT-编译为数组上简单的指针增量循环,并且开始指针和结束指针都保存在寄存器中,那么对collection.isEmpty()的额外调用可能只是优化到循环条件中。这是最好的情况,但那额外的源噪音是无用的,你会得到什么无论如何。

您可能会争辩说,如果for (String value : collection)还没有以最有效的方式编译集合,那是编译器+JVM的错误,您不应该让源代码变得丑陋。这在某种程度上可能是正确的,尽管引入对.isEmpty()的调用并不是编译器或运行时能够做的事情,除非他们可以内联该方法以确保它确实在检查迭代器所能做的事情。但是有了JIT编译,一切都可以内联了。

TL:很可能一个好的JIT编译器并不真的为大多数简单的集合创建迭代器,所以没有什么需要保存的。

在其他情况下,除非循环通常在空集合上运行,或者(更不可能)创建迭代器,否则(为了性能)不这样做可能仍然更好。

票数 3
EN

Stack Overflow用户

发布于 2014-10-15 04:52:05

不,你不需要检查空的。第一次迭代将为您完成任务。

票数 1
EN

Stack Overflow用户

发布于 2014-10-15 04:59:10

iter.hasNext()方法将返回true/false值。如果集合中没有元素,那么迭代器只需在执行语句iter.hasNext()时返回false,循环就会优雅地终止。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26374334

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档