有没有办法在 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已经是 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.Optional
和 ifPresent
方法可以使用另一种解决方案。
Optional.ofNullable(list1).ifPresent(l -> l.forEach(item -> /* do stuff */));
因此,它不是针对确切问题的解决方案,但它是单行的,可能更优雅。
【讨论】:
Java 8Optional
是一个治疗比疾病更糟糕的例子。 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 <T> List<T> ofNullable(List<T> 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 循环进行迭代时修改集合? [复制]