Novos coletores de fluxo em Java 9

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.