Давайте рассмотрим, что мы должны проверять поля в объекте в соответствии с некоторой логикой. Я привожу пример этого класса.
@Data public class Example { private String a; private String b; private String c; private String d; }
Все поля могут быть обнулены. Если поле “a” присутствует, то поле “b” тоже должно присутствовать. Если поле “c” пустое, то поле “d” тоже должно быть пустым. Мой первый вариант – это
public class Validator { public void validate(Example example) { List.of(example.getA(), example.getB(), example.getC(), example.getD()) .forEach(this::validateSomeLogic); } private void validateSomeLogic(String example) { ... } }
Предположим, как только мы получим null
для поля, в этом случае мы получим NPE. Простым решением для предотвращения ошибки будет проверка определения null перед добавлением значения в список. Давайте посмотрим, что произойдет.
public class Validator { public void validate(Example example) { Listlist = new ArrayList<>(); if (exapmle.getA() != null) list.add(example.getA()); if (exapmle.getB() != null) list.add(example.getB()); if (exapmle.getC() != null) list.add(example.getC()); if (exapmle.getD() != null) list.add(example.getD()); list.forEach(this::validateSomeLogic); } private void validateSomeLogic(String example) { ... } }
Это работает, но выглядит немного неуклюже. Есть ли у нас способ выполнить ленивую инициализацию? Одно из различий между коллекциями и потоками заключается в том, что потоки поддерживают ленивую инициализацию.
public class Validator { public void validate(Example example) { Stream.of(example.getA(), example.getB(), example.getC(), example.getD()) .filter(Objects::nonNull) .forEach(this::validateSomeLogic); } private void validateSomeLogic(String example) { ... } }
Это выглядит намного лучше! Я думаю, что этот пример хорош для демонстрации различий между типами инициализаций в коллекциях и потоках.
Оригинал: “https://dev.to/sudek/a-way-initialization-in-streams-and-collections-2n1k”