2016-08-18 3 views
3

У меня есть следующий фрагмент, который собирает определенные объекты, у которых есть строковое свойство name, которое содержит определенный фильтр filterName.Java 8 streams nonNull по свойствам объектов

List<Foo> filteredFoo= fooList.stream() 
       .filter(Objects::nonNull) 
       .filter(myFoo -> { 
          if (Strings.isNullOrEmpty(myFoo.getName())) 
           return false; 
          return myFoo.getName().contains(filterName); 
         } 
       ).collect(Collectors.toList()); 

Это работает, как ожидалось, но мне было интересно, есть ли там более элегантный способ, чтобы написать if-statement функциональным способом и проверить наличие пустых или нулевых свойств в более хорошей манере, чем иметь условный блок в фильтре.

+2

Я смущен. Вы решили, что 'Objects :: nonNull' должен быть отдельным фильтром, но все остальное должно быть в одном. Почему это? – zeroflagL

+0

@zeroflagL это делается для целей удобочитаемости, объекты: nonNull работают на уровне объекта, где второй фильтр воздействует на свойства самого объекта. Я не знаю, влияет ли это на производительность, но для удобства чтения я думаю, что это полезно. –

+0

Это моя мысль: если вы стремитесь к удобочитаемости, то почему у вас есть сложный второй фильтр вместо отдельных и, возможно, многоразовых, например 'Foo :: hasName'? – zeroflagL

ответ

7

Заменить второй filter со следующим:

.filter(myFoo -> Optional.ofNullable(myFoo.getName()) 
         .filter(n -> n.contains(filterName)) 
         .isPresent()) 

или даже:

.filter(myFoo -> { 
    String name = myFoo.getName(); 
    return name != null && name.contains(filterName) 
}) 
+0

В вашем первом примере '! Strings.isNullOrEmpty (n)' бессмысленно. – zeroflagL

+0

@zero не могли бы вы объяснить? 'name' может быть« null »или пустым. Необязательно разрешить только первый случай imo. –

+4

Не имеет значения, пусто или нет. Пустая строка не содержит 'filterName', и вы все равно проверяете это. Также '! N.isEmpty()' будет более кратким. – zeroflagL

0

Если у вас есть доступ к Foo класса, то переместить, если условия для метода isSameName и использовать фильтр, как показано ниже

filter(myFoo -> {return myFoo.isSameName(filterName);}) 
1

Перейти к функциональному стилю, для результата expressio п:

.filter(foo -> foo.getName() != null && foo.getName().contains(filterName)) 

Расщепление не принесет больше простоты:

.filter(foo -> foo.getName() != null) 
.filter(foo -> foo.getName().contains(filterName)) 

Использование предиката на Foo :: GetName (объекты :: IsNull) бессмысленно осложнено тоже, просто для того, чтобы избавить переменную.

Если filterName не является пустым, Strings.isEmptyOrNull не требуется.

Смежные вопросы