有没有办法在 for-each 循环迭代开始之前避免 null 检查?

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

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


}
}

有没有更短的方法,这样我们就可以避免写“ if”块? 注意: 我正在使用 Java5,并将在某个时候坚持使用它。

162396 次浏览

如果可能的话,您应该首先设计代码,使集合不是 null

null集合是不好的做法(出于这个原因) ; 您应该改用空集合(例如 Collections.emptyList())

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

你想要短多少?它只是一个额外的2行和它是明确和简洁的逻辑。

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

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.OptionalifPresent方法。

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(...) );