Novos coletores de fluxo em Java 9
1. Visão geral
Collectors foram adicionados em Java 8, o que ajudou a acumular elementos de entrada em contêineres mutáveis, comoMap,List eSet.
Neste artigo, vamos explorartwo new collectors added in Java 9: Collectors.filtering andCollectors.flatMapping usado em combinação comCollectors.groupingBy fornecendo coleções inteligentes de elementos.
2. Filtering Collector
OCollectors.filtering é semelhante aoStream filter(); é usado para elementos de entradafiltering, mas usado para diferentes cenários. OStream’sfilter é usado na cadeia de fluxo, enquanto ofiltering é umCollector que foi projetado para ser usado junto comgroupingBy.
ComStream’sfilter, os valores são filtrados primeiro e depois agrupados. Dessa maneira, os valores que são filtrados desaparecem e não há vestígios. Se precisarmos de um rastreamento, precisaremos primeiro agrupar e, em seguida, aplicar a filtragem que realmente oCollectors.filtering faz.
OCollectors.filtering assume uma função para filtrar os elementos de entrada e um coletor para coletar os elementos filtrados:
@Test
public void givenList_whenSatifyPredicate_thenMapValueWithOccurences() {
List numbers = List.of(1, 2, 3, 5, 5);
Map result = numbers.stream()
.filter(val -> val > 3)
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
assertEquals(1, result.size());
result = numbers.stream()
.collect(Collectors.groupingBy(i -> i,
Collectors.filtering(val -> val > 3, Collectors.counting())));
assertEquals(4, result.size());
}
3. FlatMapping Collector
OCollectors.flatMapping é semelhante aCollectors.mapping, mas tem um objetivo mais refinado. Ambos os coletores assumem uma função e um coletor onde os elementos são coletados, mas a funçãoflatMapping aceitaStream de elementos que são então acumulados pelo coletor.
Vamos ver a seguinte classe de modelo:
class Blog {
private String authorName;
private List comments;
// constructor and getters
}
Collectors.flatMapping nos permite pular a coleção intermediária e gravar diretamente em um único contêiner que é mapeado para aquele grupo definido porCollectors.groupingBy:
@Test
public void givenListOfBlogs_whenAuthorName_thenMapAuthorWithComments() {
Blog blog1 = new Blog("1", "Nice", "Very Nice");
Blog blog2 = new Blog("2", "Disappointing", "Ok", "Could be better");
List blogs = List.of(blog1, blog2);
Map>> authorComments1 = blogs.stream()
.collect(Collectors.groupingBy(Blog::getAuthorName,
Collectors.mapping(Blog::getComments, Collectors.toList())));
assertEquals(2, authorComments1.size());
assertEquals(2, authorComments1.get("1").get(0).size());
assertEquals(3, authorComments1.get("2").get(0).size());
Map> authorComments2 = blogs.stream()
.collect(Collectors.groupingBy(Blog::getAuthorName,
Collectors.flatMapping(blog -> blog.getComments().stream(),
Collectors.toList())));
assertEquals(2, authorComments2.size());
assertEquals(2, authorComments2.get("1").size());
assertEquals(3, authorComments2.get("2").size());
}
OCollectors.mapping mapeia todos os comentários do autor agrupados para o contêiner do coletor, ou seja, List, enquanto essa coleção intermediária é removida comflatMapping, pois fornece um fluxo direto da lista de comentários a ser mapeada para o contêiner do coletor.
4. Conclusão
Este artigo ilustra o uso do novoCollectors introduzido emJava9, ou seja, Collectors.filtering() and Collectors.flatMapping() used in combination with Collectors.groupingBy().
Esses coletores também podem ser usados junto comCollectors.partitioningBy(), mas só cria duas partições com base nas condições e o poder real dos coletores não é aproveitado; portanto, deixado de fora deste tutorial.
O código-fonte completo para os trechos de código neste tutorial está disponívelover on GitHub.