【问题标题】:Checking for a nullabity when iterating collections迭代集合时检查可空性
【发布时间】:2012-12-29 22:34:30
【问题描述】:

哪个更好?

List list = ... //get list from somewhere

for (int i=0; list != null && i < list.size(); i++){
    // ...
}

还是?

List list = ... //get list from somewhere


if (list != null){
    for (int i = 0; i < list.size(); i++){
        // ...
    }
}

我从这里得到了这个想法:Scala or Java? Exploring myths and facts

【问题讨论】:

  • 如果您控制返回列表的代码,返回空列表而不是空列表将使您的生活更轻松。那么你就不需要再回答这个问题了。
  • 我相信在 Java 7+ 中,您可以使用 ? 运算符更简洁地检查 null。
  • @BlackVegetable 你能详细说明一下吗? AFAIK ? 只能在泛型或 ? : 三元运算符中用作通配符 - 自 Java 1.5 起就已存在
  • @assylias Doh!我认为这是我升级时要使用的一个简洁的功能,但事实证明它最终从未被接受为标准! stackoverflow.com/questions/4390141/…
  • +1 到@assylias。从不使用空集合,而使用空集合,比这两种方法都好。

标签: java coding-style


【解决方案1】:

更好是什么意思?更易读的代码,还是更高效的代码?无论如何,我不喜欢你的两个建议。

当我必须使用返回 List 但可能返回 null 的方法时(我无法更改该方法的源代码以返回空的 List),这就是我做:

List list = ... // get list from somewhere
if (list == null) {
    list = Collections.emptyList();
}
for (int i = 0; i < list.size(); i++) {
    // ...
}

恕我直言,这在可读性、性能和避免我们代码的深度嵌套方面获胜。

【讨论】:

    【解决方案2】:

    将空检查留在循环之外。

    虽然你可以通过将一行合并到循环终止条件中来保存它,但没有人喜欢这样做,因为你失去了清晰度:

    您应该只在循环代码部分中包含与迭代相关的代码!

    这是一个基本的良好编码风格指南。

    此外,合并检查也可能稍微慢一些,因为即使列表为空,您也必须启动循环并执行初始化代码。

    最后,如果你想重构使用方便的foreach语法,你不能合并空检查:

    List<T> list;
    if (list != null) {
        for (T t : list) {
            // ...
        }
    {
    

    【讨论】:

    • 这是要走的路。恕我直言,其他任何事情都更糟。
    • @szegedi:你觉得我的回答更糟糕?
    • @jlordo 实际上这是因为您实际上是在创建一个不必要的空列表实例。
    • @Jagger:看看Collectionssource code。只要 Collections 类被加载,该实例就存在。这只是对该实例的另一个引用;)
    • @jlordo 首先,我同意 assylias 任何返回 null 而不是空列表的代码通常是一个坏主意。如果我编写了其他代码,我也不想抑制其他代码的失败(如果它打算返回一个空列表但由于一些内部问题它返回 null)。另外,(我知道他是否需要迭代次数没有指定)我更喜欢 foreach 循环。但是你的回答没有错,我应该在评论中使用“我当然更喜欢这个解决方案”,正如恕我直言的那样,其他任何事情对我来说可读性都更差。干杯。
    【解决方案3】:

    第二个....在第一个方法中,每次循环都会发生不必要的空检查

    【讨论】:

    • @Muhammad 性能方面,从长远来看可能不会有任何差异,因为编译器应该足够聪明,可以确定可以从 for 循环中提取空条件...
    • 我希望JIT 无论如何都会优化第二个代码。因此,在性能方面,AFAIK 不会有任何差异。
    • 是的......编译器可能正在优化......但我们不应该认为编译器会优化我们的代码。
    • @Renjith 没错,我们应该编写代码以确保我们编写的内容可读且可维护。在这种情况下,我碰巧它也是更有效的解决方案。我只是说,在这种情况下,性能不会产生影响,可能不应该成为标准。
    【解决方案4】:

    您的建议都没有效率。我会建议类似于下面的代码(为什么每次都进行不必要的方法调用 list.size() ):-

    List list = ... //get list from somewhere
    
    int size = (list==null ? 0 : list.size());
    
    for (int i = 0; i < size; i++){
        // ...
    }
    

    这样代码既可读又高效。

    【讨论】:

      【解决方案5】:

      在性能上是一样的。对于可读性问题,我更喜欢第二个。它对我来说更具可读性和简洁性。

      【讨论】:

        猜你喜欢
        • 2020-08-09
        • 1970-01-01
        • 2012-07-07
        • 2012-04-02
        • 2017-05-02
        • 1970-01-01
        • 2022-07-05
        • 2011-04-25
        • 2014-12-10
        相关资源
        最近更新 更多