【问题标题】:Is there a way to avoid null check before the for-each loop iteration starts? [duplicate]有没有办法在 for-each 循环迭代开始之前避免空检查? [复制]
【发布时间】:2011-08-29 23:49:04
【问题描述】:

每次我必须迭代一个集合时,我都会在 for-each 循环的迭代开始之前检查 null。像这样:

if( list1 != null ){
    for(Object obj : list1){

    }
}

有没有更短的方法,这样我们就可以避免写“if”块? 注意:我使用的是 Java 5,并且会被它卡住一段时间。

【问题讨论】:

  • 就像 SLaks 所说,你的集合不应该为空,而是它们的大小为零。在这种情况下,增强的 for 循环不会出错。
  • 你可以把if的块去掉,效果一样
  • @ratchet 我无法删除“if”块。如果list1为null,则会出现NullPointerException
  • 我的意思是你输入if(list1 != null)for(Object obj : list1){...},换句话说,去掉花括号,这样你就可以把它放在一行中
  • @ratchet 有趣...但我可能无法通过代码审查 :)

标签: java for-loop foreach


【解决方案1】:

如果可能,您应该设计您的代码,使集合一开始就不是null

null 集合是不好的做法(因此);您应该改用空集合。 (例如,Collections.emptyList()

或者,您可以创建一个实现 Iterable 并接受集合并处理 null 集合的包装类。
然后你可以写foreach(T obj : new Nullable<T>(list1))

【讨论】:

  • 我只是开发人员中的一员……在那方面排名较低:)
  • 如果你使用泛型,最好使用 Collections.emptyList() 而不是 Collections.EMPTY_LIST;它是类型安全的。
  • @Dataknife 更像是它只是为你做演员。这两种情况在运行时都没有泛型类型,emptyList() 的实现内部包含强制转换(也抑制了 unchecked)。
  • 这对我来说是个糟糕的设计。然后 JAX - B 使用我放置它们的位置来解组数据。这些列表是不可变的,它会尝试添加到它们中。我想你也应该考虑这个stackoverflow.com/questions/5552258/…
  • 当您有一个没有任何内容的集合的想法时,空列表非常有用。这与没有收藏有微妙的不同;并且,差异可能很大。例如,当可选列表表示为空列表时,您必须选择将其作为列表处理还是作为空列表处理(简化删除了两个选项之一)。在某些情况下,这可能是不可取的。
【解决方案2】:
public <T extends Iterable> T nullGuard(T item) {
  if (item == null) {
    return Collections.EmptyList;
  } else {
    return item;
  }
}

或者,如果保存文本行是一个优先事项(不应该)

public <T extends Iterable> T nullGuard(T item) {
  return (item == null) ? Collections.EmptyList : item;
}

可以让你写

for (Object obj : nullGuard(list)) {
  ...
}

当然,这实际上只是将复杂性转移到其他地方。

【讨论】:

  • 不错的答案,但可能应该是静态的。
  • 它不仅仅是“将复杂性转移到其他地方”。它将复杂性封装在一个地方,因此您不必一次又一次地编写空检查代码。问题是如何使它更短。检查必须在某处进行。你很谦虚,@edwin-buck
  • public T nullGuard(T item) { if (item == null) { return Collections.EmptyList; } 归还物品; }
  • @corroborator 是的,通过执行短路返回来保存“else”语句。这是一个等效的代码流。我更新了一个更小的解决方案;但是,真正节省文本行应该优先于易于阅读的代码。不确定可能使用此解决方案的地方的样式是什么;但是,如果存在主导风格,则模仿它的风格(不是个人风格)。
【解决方案3】:

已经是 2017 年了,现在可以使用Apache Commons Collections4

用法:

for(Object obj : CollectionUtils.emptyIfNull(list1)){
    // Do your stuff
}

【讨论】:

  • 这是我在这里看到的最干净的答案。如果我的 list1 是一个 Object 数组,即 Object[],有没有办法做同样的事情?
  • for(Object obj : ArrayUtils.nullToEmpty(list1)) { // Do your stuff }
【解决方案4】:

我想正确的答案是:没有办法让它更短。有一些技术,例如 cmets 中的技术,但我不认为自己会使用它们。我认为写一个“if”块比使用这些技术更好。是的..在任何人再次提到它之前:)“理想情况下”代码应该被设计成列表永远不应该是 null

【讨论】:

    【解决方案5】:

    在 Java 8 中,使用 java.util.OptionalifPresent 方法可以使用另一种解决方案。

    Optional.ofNullable(list1).ifPresent(l -> l.forEach(item -> {/* do stuff */}));
    

    因此,它不是针对确切问题的解决方案,但它是单行的,可能更优雅。

    【讨论】:

    • Java 8 Optional 是一个治疗比疾病更糟糕的例子。 Optional 是一个简单的空检查的冗长而笨拙的替代品。为了避免,imo。
    【解决方案6】:

    Null check in an enhanced for loop

    public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
        return iterable == null ? Collections.<T>emptyList() : iterable;
    }
    

    然后使用:

    for (Object object : emptyIfNull(someList)) { ... }
    

    【讨论】:

      【解决方案7】:

      Apache Commons

      for (String code: ListUtils.emptyIfNull(codes)) {
      
      }           
      

      谷歌番石榴

      for (String code: Optional.of(codes).get()) {
      
      }
      

      【讨论】:

        【解决方案8】:

        你希望它短多少?它只是一个额外的 2 行,并且逻辑清晰简洁。

        我认为你需要决定的更重要的事情是null 是否是一个有效值。如果它们无效,您应该编写代码以防止它发生。那么你就不需要这种检查了。如果您在执行foreach 循环时遇到异常,则表明您的代码中的其他地方存在错误。

        【讨论】:

        • 不幸的是,在许多情况下,触摸提供这些列表的方法会给我带来问题......这不是我第一次看到方法“期望”其他方法返回 null ..
        • 我想知道它可以更短,因为我最近遇到了一些使用“?”检查 null 的 Groovy 代码......忘记了它叫什么。
        • 三元运算符。
        【解决方案9】:

        1) 如果 list1 是类的成员,则在构造函数中创建列表,使其存在且非空,但为空。

        2) for (Object obj : list1 != null ? list1 : new ArrayList())

        【讨论】:

        • 有趣..会尝试一下
        • 最好使用 Collections.emptyList()。为什么分配一些东西只是为了垃圾收集它?
        • 灵感来自我在实用程序类中写的这条评论:public static &lt;T&gt; List&lt;T&gt; ofNullable(List&lt;T&gt; list) {return list == null ? Collections.emptyList() : list;},然后使用:` for (Object obj : ofNullable(list1)) {`
        【解决方案10】:

        另一种 Java 8+ 方法是创建一个在使用 null 值时不会崩溃的 forEach 方法:

        public static <T> void forEach(Iterable<T> set, Consumer<T> action) {
            if (set != null) {
                set.forEach(action);
            }
        }
        

        自己定义的foreach的用法接近原生Java 8之一:

        ArrayList<T> list = null;
        
        //java 8+ (will throw a NullPointerException)
        list.forEach(item -> doSomething(...) );
        
        //own implementation
        forEach(list, item -> doSomething(...) );
        

        【讨论】:

          猜你喜欢
          • 2010-10-03
          • 1970-01-01
          • 2010-10-27
          • 1970-01-01
          • 1970-01-01
          • 2020-03-10
          • 2017-02-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多