Como entender esse método Java 8 Stream collect ()?

12

Eu estava tentando converter uma matriz int em List e segui a rota desconhecida de usar o Java 8 Stream e criei essa

Arrays.stream(arr).boxed().collect(Collectors.toList());

Eu ainda tenho dificuldade para entender completamente essa linha, principalmente,

  1. Por que Collectors.toList(), neste caso, retorna uma interface de ArrayList<Integer>implementação List? Por que não LinkedList<Integer>ou qualquer outra classe genérica em conformidade com a Listinterface? Não consigo encontrar nada sobre isso, exceto por uma breve menção de ArrayList aqui , na seção Notas da API.

  2. O que significa o painel esquerdo ? Obviamente é o tipo de retorno genérico ( no meu código aqui). E eu acho que é o argumento de tipo genérico do método, mas como eles são especificados? Olhei para Collector interface de doc e não foi capaz de absorvê-lo.insira a descrição da imagem aqui Stream.collect()RArrayList<Integer><R, A>

user3207158
fonte
2
1. Ele usa uma lista real, obviamente. Mas seria imprudente para uma API revelar o tipo de lista subjacente real. Desde então, eles não poderão mais mudar a implementação no futuro. Em geral, geralmente é uma boa ideia expor apenas interfaces e nunca o tipo subjacente real. 2. Ré o tipo genérico do tipo resultante. Ao tipo genérico do tipo de acumulação intermediária do coletor. Esse é o detalhe da implementação de como um coletor funciona. Ele divide e conquista, também para processamento paralelo, coleta primeiro em tipos intermediários.
Zabuzard 4/11/19
10
Você quase nunca deseja realmente o LinkedList. Há um tweet de Josh Bloch , dizendo "eu escrevi e nunca o uso".
Andy Turner
4
"Por que Collectors.toList(), neste caso, retorna um ArrayList<Integer>" Ele pode não retornar um ArrayList. A Listimplementação é indefinida , portanto você não pode confiar em qual implementação ela retorna. Como o javadoc diz: "Não há garantias sobre o tipo , mutabilidade, serialização ou segurança de thread da Lista retornada;"
Andreas
3
e toList()não está retornando um ArrayListou List- está retornando a Collector, que eventualmente criará e retornará a List- também a documentação declara: "... Não há garantias quanto ao tipo , mutabilidade, serialização ou segurança de thread da Lista retornada; se for necessário mais controle sobre a lista retornada, use toCollection (Supplier) .... "
user85421-Baned 04/11/19
3
Eu recomendo fortemente a documentação do pacote
Holger

Respostas:

18
  1. É uma implementação padrão. ArrayListé usado, porque é o melhor na maioria dos casos de uso, mas se não for adequado para você, você sempre pode definir seu próprio coletor e fornecer fábrica para o Collectionque deseja:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. Sim, Ae Rsão parâmetros genéricos desse método, Ré o tipo de retorno, Té o tipo de entrada e Aé um tipo intermediário, que aparece em todo o processo de coleta de elementos (pode não ser visível e não se refere a essa função). O início do Collectorjavadoc define esses tipos (eles são consistentes em todo o documento):

    T - o tipo de elementos de entrada para a operação de redução
    A - o tipo de acumulação mutável da operação de redução (geralmente oculto como um detalhe de implementação)
    R - o tipo de resultado da operação de redução

Andronicus
fonte
OK eu vejo. Eu acho que devo realmente manter List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());e chamar apenas métodos declarados na interface List em myList. Caso contrário, eu estaria potencialmente me colocando em risco, se a Oracle decidir alterar a implementação padrão em Java8u1024 ou 15?
user3207158
2
@ user3207158 o método retorna a List, portanto, independentemente da implementação usada, o comportamento é o mesmo. É improvável que a interface seja alterada nas versões mais recentes do java.
Andronicus
1
  1. Por que Collectors.toList () nesse caso retorna uma interface de lista de implementação ArrayList?

Conforme a definição do método sugere, ele retorna uma implementação do coletor com o fornecedor do coletor como ArrayList. Portanto, é muito claro na definição do método abaixo que Collectors.toListsempre retorna o coletor ArrayList ( While it's arguable why toList not toArrayList word is used in method name).

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. O que significa o painel esquerdo de <R, A> R collect(Collector<? super T, A, R> collector)meios

Se você se referir aos comentários da documentação, ele menciona com precisão o que são esses tipos genéricos:

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);
Vinay Prajapati
fonte
Obrigado senhor. Onde você conseguiu o código-fonte de Collectors.toList()(primeiro trecho)? É openjdk?
user3207158
11
Não! Tenho baixado o código fonte em meu j intelli
Vinay Prajapati