Comment comprendre cette méthode de collecte () Java 8 Stream?

12

J'essayais de convertir un tableau int en List et j'ai pris la voie inconnue de l'utilisation de Java 8 Stream et j'ai trouvé cela

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

J'ai encore du mal à bien comprendre cette ligne, surtout,

  1. Pourquoi Collectors.toList()dans ce cas retourne une interface d' ArrayList<Integer>implémentation List? Pourquoi pas LinkedList<Integer>ou toute autre classe générique conforme à l' Listinterface? Je ne trouve rien à ce sujet, à l'exception d'une brève mention d'ArrayList ici , dans la section Notes d'API.

  2. Que signifie le panneau de gauche ? C'est évidemment le type de retour générique ( dans mon code ici). Et je pense que c'est l'argument de type générique de la méthode, mais comment sont-ils spécifiés? J'ai regardé dans le document d'interface Collector et je n'ai pas pu l'absorber.entrez la description de l'image ici Stream.collect()RArrayList<Integer><R, A>

user3207158
la source
2
1. Il utilise une liste réelle sous le capot, évidemment. Mais il serait imprudent pour une API de révéler le type de liste sous-jacent réel. Depuis lors, ils ne pourraient plus changer la mise en œuvre à l'avenir. En général, il est souvent judicieux d'exposer uniquement les interfaces et jamais le type sous-jacent réel. 2.R est le type générique du type résultant. Ale type générique du type d'accumulation intermédiaire du collecteur. C'est le détail de l'implémentation du fonctionnement d'un collecteur. Il divise et conquiert, également pour le traitement parallèle, recueille d'abord en types intermédiaires.
Zabuzard
10
Vous ne voulez presque jamais réellement LinkedList. Il y a un tweet de Josh Bloch , disant "Je l'ai écrit et je ne l'utilise jamais".
Andy Turner
4
"Pourquoi Collectors.toList()dans ce cas renvoie un ArrayList<Integer>" Il peut ne pas retourner un ArrayList. L' Listimplémentation n'est pas définie , vous ne pouvez donc pas vous fier à l'implémentation qu'elle renvoie. Comme le dit le javadoc : "Il n'y a aucune garantie sur le type , la mutabilité, la sérialisation ou la sécurité des threads de la liste renvoyée;"
Andreas
3
et toList()ne renvoie pas de ArrayListou List- il renvoie un Collector, ce qui finira par créer et retournera List- également la documentation indique: "... Il n'y a aucune garantie sur le type , la mutabilité, la sérialisation ou la sécurité des threads de la liste retournée; si plus de contrôle sur la liste retournée est nécessaire, utilisez toCollection (Supplier) .... "
user85421-Banned
3
Je recommande fortement la documentation du paquet
Holger

Réponses:

18
  1. C'est une implémentation par défaut. ArrayListest utilisé, car il est préférable dans la plupart des cas d'utilisation, mais s'il ne vous convient pas, vous pouvez toujours définir votre propre collecteur et fournir l'usine que Collectionvous souhaitez:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. Oui, A et Rsont des paramètres génériques de cette méthode, Rest le type de retour, Test le type d'entrée et Aest un type intermédiaire, qui apparaît dans l'ensemble du processus de collecte des éléments (peut ne pas être visible et ne concerne pas cette fonction). Le début de Collectorjavadoc définit ces types (ils sont cohérents sur l'ensemble du document):

    T - le type d'éléments d'entrée pour l'opération de réduction
    A - le type d'accumulation modifiable de l'opération de réduction (souvent masqué comme détail d'implémentation)
    R - le type de résultat de l'opération de réduction

Andronicus
la source
OK je vois. Je suppose que je devrais vraiment m'en tenir List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());et appeler uniquement les méthodes déclarées dans l'interface List sur myList. Sinon, je me mettrais potentiellement en danger, si Oracle décide de changer l'implémentation par défaut dans Java8u1024 ou 15?
user3207158
2
@ user3207158 la méthode renvoie un List, donc quelle que soit l'implémentation utilisée, le comportement est le même. Il est peu probable que l'interface soit modifiée dans les nouvelles versions de java.
Andronicus
1
  1. Pourquoi Collectors.toList () dans ce cas renvoie une interface de liste d'implémentation ArrayList?

Comme la définition de la méthode le suggère, elle renvoie une implémentation Collector avec le fournisseur collector as ArrayList. Par conséquent, il est très clair d'après la définition de la méthode ci-dessous qui Collectors.toListretourne toujours ArrayList collector ( 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. Qu'est - ce que le panneau gauche de <R, A> R collect(Collector<? super T, A, R> collector)moyens

Si vous vous référez aux commentaires de documentation, il mentionne avec précision quels sont ces types génériques:

/*
      @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
la source
Merci Monsieur. Où avez-vous obtenu le code source de Collectors.toList()(premier extrait)? Est-ce openjdk?
user3207158
1
Non! J'ai téléchargé le code source dans mon intelli j
Vinay Prajapati