有没有办法在 for-each 循环迭代开始之前避免空检查? [复制]

Posted

技术标签:

【中文标题】有没有办法在 for-each 循环迭代开始之前避免空检查? [复制]【英文标题】:Is there a way to avoid null check before the for-each loop iteration starts? [duplicate] 【发布时间】: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 有趣...但我可能无法通过代码审查 :) 【参考方案1】:

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

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

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

【讨论】:

我只是开发人员中的一员……在那方面排名较低:) 如果你使用泛型,最好使用 Collections.emptyList() 而不是 Collections.EMPTY_LIST;它是类型安全的。 @Dataknife 更像是它只是为你做演员。这两种情况在运行时都没有泛型类型,emptyList() 的实现内部包含强制转换(也抑制了 unchecked)。 这对我来说是个糟糕的设计。然后 JAX - B 使用我放置它们的位置来解组数据。这些列表是不可变的,它会尝试添加到它们中。我想你也应该考虑这个***.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(...) );

【讨论】:

以上是关于有没有办法在 for-each 循环迭代开始之前避免空检查? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 ConcurrentModificationException 的情况下使用 for-each 循环进行迭代时修改集合? [复制]

JAVA中的for-each循环与迭代

哪个更有效,for-each 循环还是迭代器?

有没有办法在 XSLT 转换中用应用模板替换 for-each?

2优先使用for-each循环

集合中的 for-Each循环