每次我必须迭代一个集合时,我都会在 for-each 循环的迭代开始之前检查 null。像这样:
if( list1 != null ){ for(Object obj : list1){ } }
有没有更短的方法,这样我们就可以避免写“ if”块? 注意: 我正在使用 Java5,并将在某个时候坚持使用它。
如果可能的话,您应该首先设计代码,使集合不是 null。
null
null集合是不好的做法(出于这个原因) ; 您应该改用空集合(例如 Collections.emptyList())
Collections.emptyList()
或者,您可以创建一个包装器类,它实现 Iterable并接受一个集合,并处理一个 null集合。 然后可以编写 foreach(T obj : new Nullable<T>(list1))
Iterable
foreach(T obj : new Nullable<T>(list1))
你想要短多少?它只是一个额外的2行和它是明确和简洁的逻辑。
我认为你需要决定的更重要的事情是 null是否是一个有效的值。如果它们无效,则应编写代码以防止其发生。那你就不需要这种支票了。如果在执行 foreach循环时出现异常,那就表明代码中的其他地方存在 bug。
foreach
1)如果 list1是一个类的成员,那么在构造函数中创建一个列表,这样它就在那里,虽然是空的,但是它是非空的。
2) for (Object obj: list1! = null? list1: new ArrayList ())
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)) { ... }
当然,这实际上只是将复杂性转移到了其他地方。
我想正确的答案是: 没有办法让它变得更短。有一些技巧,比如评论中的那些,但我不认为自己会使用它们。我认为写一个“如果”代码块比使用这些技术更好。是的。.在任何人再次提到它之前:)“理想情况下”,代码应该被设计成这样,列表永远不应该是一个 无效
增强的 for 循环中的空检查
public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) { return iterable == null ? Collections.<T>emptyList() : iterable; }
然后使用:
for (Object object : emptyIfNull(someList)) { ... }
在 Java8中,还有另一种解决方案可以使用 java.util.Optional和 ifPresent方法。
java.util.Optional
ifPresent
Optional.ofNullable(list1).ifPresent(l -> l.forEach(item -> {/* do stuff */}));
所以,这不是一个精确问题的解决方案,但它是一个线条,可能更优雅。
Apache Commons
for (String code: ListUtils.emptyIfNull(codes)) { }
谷歌番石榴
for (String code: Optional.of(codes).get()) { }
现在已经是2017年了,您现在可以使用 Apache Commons Collections4
用法:
for(Object obj : CollectionUtils.emptyIfNull(list1)){ // Do your stuff }
Java8 + 的另一种方法是创建一个在使用 null值时不会崩溃的 forEvery 方法:
public static <T> void forEach(Iterable<T> set, Consumer<T> action) { if (set != null) { set.forEach(action); } }
自己定义的 foreach的用法接近于原生的 Java8:
ArrayList<T> list = null; //java 8+ (will throw a NullPointerException) list.forEach(item -> doSomething(...) ); //own implementation forEach(list, item -> doSomething(...) );