Por que certos coletores na API de fluxo Java são chamados de coletor downstream?

Aug 15 2020

Queria saber por que classificamos certos coletores como "a jusante"? Existe um coletor upstream então? Observe que não se trata de uso, mas de tentar entender a lógica por trás do termo "downstream". Para mim, quando você normalmente lida com o uso da API de fluxo, todos os fluxos na cadeia do construtor parecem ser apenas downstream.

List<String> list = List.of("AAA","B","CCCCC","DDD", "FFFFFF", "AAA");
List<Integer> res =
            list.stream()
                    .collect(
                            Collectors.mapping(s -> s.length(), // string -> int
                                Collectors.toList())); // downstreaming

No código acima, Collectors.toList()é considerado downstream.

Respostas

7 jaco0646 Aug 15 2020 at 08:44

O termo downstream na documentação refere-se a um Coletor que aceita um segundo Coletor como argumento. O argumento é aplicado downstream (depois) do Coletor que o aceita. Em outras palavras, o coletor downstream é aplicado ao resultado do coletor upstream.

No seu exemplo, Collectors.toListé downstream de Collectors.mapping.

5 Sweeper Aug 15 2020 at 08:55

Costumo imaginar a API de fluxo como a construção de uma linha de produção de um produto. São matérias-primas vindas de algum lugar ( ArrayList.stream, IntStream.range, Stream.of, tanto faz), em uma esteira, e depois com métodos intermediários, os materiais são transformados ( map/ flatMapetc) e filtrados ( filter/ limitetc) e finalmente chegam ao final da linha, onde eles são montados em um produto final ( collect) */sup>.

Collectors são "máquinas" que constroem os diferentes produtos finais citados acima. toListconstrói uma lista. toSetconstrói um Setetc. No entanto, outros coletores não constroem totalmentegroupingBy a coisa grande, por exemplo, . groupingByapenas agrupa os materiais por uma chave e, em seguida, cospe os itens novamente, como grupos, de volta à esteira. Esses coletores precisam de outro coletor na linha de produção (também conhecido como fluxo abaixo) para continuar construindo o produto final.

mappingé mais um daqueles coletores que não constrói completamente o produto final. Ele apenas transforma os materiais e os cospe novamente, o que é mais ou menos como map. Sua utilidade vem quando você deseja, por exemplo, transformar os grupos cuspidos de um arquivo groupingBy. ou seja, é mais útil quando você o usa como downstream de outro coletor.

Existe um coletor upstream então?

Seguindo a analogia da linha de produção, a relação é bidirecional: toListé o downstream de mapping, então mappingé o upstream de toList. Na documentação oficial embora. Esta palavra não é muito mencionada. Só encontrei em peek.

*Existem outras operações de terminais, mas vamos nos concentrar em collect, pois é disso que se trata a pergunta.