Есть ли способ избежать проверки на ноль перед началом итерации цикла for-each?
Каждый раз, когда мне приходится перебирать коллекцию, я заканчиваю проверку на нулевое значение, как раз перед началом итерации цикла for-each. Как это:
if( list1 != null ){
for(Object obj : list1){
}
}
Есть ли более короткий путь, чтобы мы могли избежать записи блока if? Примечание: я использую Java 5, и застряну с ним некоторое время.
9 ответов
Я думаю, что правильный ответ таков: нет способа сделать его короче. Есть некоторые методы, такие как те в комментариях, но я не вижу себя использующим их. Я думаю, что лучше написать блок "если", чем использовать эти методы. и да.. прежде чем кто-нибудь еще это упомянет:) "в идеале" код должен быть разработан таким образом, чтобы список никогда не был нулевым
Если возможно, вы должны разработать свой код так, чтобы коллекции не null
на первом месте.
null
коллекции - плохая практика (по этой причине); Вы должны использовать пустые коллекции вместо этого. (например, Collections.emptyList()
)
В качестве альтернативы, вы можете сделать класс-оболочку, который реализует Iterable
и берет коллекции, и обрабатывает null
коллекция.
Вы могли бы тогда написать foreach(T obj : new Nullable<T>(list1))
public <T extends Iterable> T nullGuard(T item) {
if (item == null) {
return Collections.EmptyList;
} else {
return item;
}
}
позволит вам написать
for (Object obj : nullGuard(list)) {
...
}
Конечно, это действительно просто перемещает сложность в другом месте.
Уже 2017 год, и теперь вы можете использовать Apache Commons Collections4
Использование:
for(Object obj : CollectionUtils.emptyIfNull(list1)){
// Do your stuff
}
В Java 8 есть другое решение, доступное с помощью java.util.Optional
и ifPresent
-метод.
Optional.ofNullable(list1).ifPresent(l -> l.forEach(item -> {/* do stuff */}));
Таким образом, не решение для точной проблемы, но это единственное и, возможно, более элегантный.
Проверка нуля в расширенном цикле for
public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
return iterable == null ? Collections.<T>emptyList() : iterable;
}
Тогда используйте:
for (Object object : emptyIfNull(someList)) { ... }
Apache Commons
for (String code: ListUtils.emptyIfNull(codes)) {
}
Google Guava
for (String code: Optional.of(codes).get()) {
}
Насколько короче вы хотите, чтобы это было? Это всего лишь лишние 2 строки И это понятная и лаконичная логика.
Я думаю, что более важная вещь, которую вы должны решить, это если null
является действительным значением или нет. Если они недействительны, вы должны написать свой код, чтобы предотвратить это. Тогда вам не понадобится такая проверка. Если вы идете получить исключение во время выполнения foreach
цикл, это признак того, что где-то в вашем коде есть ошибка.
1) если list1 является членом класса, создайте список в конструкторе, чтобы он был и не был нулевым, хотя и пустым.
2) for (Объект obj: list1!= Null? List1: new ArrayList())
Другой способ Java 8+ - создать метод forEach, который не дает сбоев при использовании null
значение:
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(...) );