Cadeia de Predicado Java 8
1. Visão geral
Neste tutorial rápido,we’ll discuss different ways to chain Predicates in Java 8.
2. Exemplo básico
Primeiro,let’s see how to use a simple Predicate para filtrarList de nomes:
@Test
public void whenFilterList_thenSuccess(){
List names = Arrays.asList("Adam", "Alexander", "John", "Tom");
List result = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Adam","Alexander"));
}
Neste exemplo, filtramos nossosList de nomes para deixar apenas os nomes que começam com “A” usando oPredicate:
name -> name.startsWith("A")
Mas e se quiséssemos aplicar váriosPredicates?
3. Filtros Múltiplos
Se quisermos aplicar váriosPredicates,one option is to simply chain multiple filters:
@Test
public void whenFilterListWithMultipleFilters_thenSuccess(){
List result = names.stream()
.filter(name -> name.startsWith("A"))
.filter(name -> name.length() < 5)
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
Agora, atualizamos nosso exemplo para filtrar nossa lista extraindo nomes que começam com "A" e têm um comprimento inferior a 5.
Usamos dois filtros - um para cadaPredicate.
4. ComplexoPredicate
Agora, em vez de usar vários filtros,we can use one filter with a complex Predicate:
@Test
public void whenFilterListWithComplexPredicate_thenSuccess(){
List result = names.stream()
.filter(name -> name.startsWith("A") && name.length() < 5)
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
Esta opção é mais flexível que a primeira, já quewe can use bitwise operations to build the Predicate é tão complexo quanto queremos.
5. CombinandoPredicates
Em seguida, se não quisermos construir umPredicate complexo usando operações bit a bit, Java 8Predicate tem métodos úteis que podemos usar para combinarPredicates.
Vamos combinarPredicates usando os métodosPredicate.and(),Predicate.or() ePredicate.negate().
5.1. Predicate.and()
Neste exemplo, definiremos nossosPredicates explicitamente e, em seguida, os combinaremos usandoPredicate.and():
@Test
public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){
Predicate predicate1 = str -> str.startsWith("A");
Predicate predicate2 = str -> str.length() < 5;
List result = names.stream()
.filter(predicate1.and(predicate2))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
Como podemos ver, a sintaxe é bastante intuitiva e os nomes dos métodos sugerem o tipo de operação. Usandoand(), filtramos nossoList extraindo apenas nomes que atendem às duas condições.
5.2. Predicate.or()
Também podemos usarPredicate.or() para combinarPredicates.
Vamos extrair nomes que começam com "J", bem como nomes com comprimento inferior a 4:
@Test
public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){
Predicate predicate1 = str -> str.startsWith("J");
Predicate predicate2 = str -> str.length() < 4;
List result = names.stream()
.filter(predicate1.or(predicate2))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("John","Tom"));
}
5.3. Predicate.negate()
Podemos usarPredicate.negate() ao combinar nossosPredicates também:
@Test
public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){
Predicate predicate1 = str -> str.startsWith("J");
Predicate predicate2 = str -> str.length() < 4;
List result = names.stream()
.filter(predicate1.or(predicate2.negate()))
.collect(Collectors.toList());
assertEquals(3, result.size());
assertThat(result, contains("Adam","Alexander","John"));
}
Aqui, usamos uma combinação deor() enegate() para filtrarList por nomes que começam com “J” ou têm um comprimento não inferior a 4.
5.4. CombinarPredicates Inline
Não precisamos definir explicitamente nossoPredicates para usarand(),or() enegate().
Também podemos usá-los embutidos lançando oPredicate:
@Test
public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){
List result = names.stream()
.filter(((Predicate)name -> name.startsWith("A"))
.and(name -> name.length()<5))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
6. Combinando uma coleção dePredicates
Finalmente,let’s see how to chain a collection of Predicates by reducing them.
No exemplo a seguir, temos umList dePredicates que combinamos usandoPredicate.and():
@Test
public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){
List> allPredicates = new ArrayList>();
allPredicates.add(str -> str.startsWith("A"));
allPredicates.add(str -> str.contains("d"));
allPredicates.add(str -> str.length() > 4);
List result = names.stream()
.filter(allPredicates.stream().reduce(x->true, Predicate::and))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Alexander"));
}
Observe que usamos nossa identidade base como:
x->true
Mas isso será diferente se quisermos combiná-los usandoPredicate.or():
@Test
public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){
List result = names.stream()
.filter(allPredicates.stream().reduce(x->false, Predicate::or))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Adam","Alexander"));
}
7. Conclusão
Neste artigo, exploramos diferentes maneiras de encadear Predicados em Java 8, usandofilter(), complexo de construçãoPredicates combinandoPredicates.
O código-fonte completo está disponívelover on GitHub.