¿Cómo entender este método Java 8 Stream collect ()?


12

Estaba tratando de convertir una matriz int a List y tomé la ruta desconocida de usar Java 8 Stream y se me ocurrió esto

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

Todavía tengo dificultades para entender completamente esta línea, principalmente,

  1. ¿Por qué Collectors.toList()en este caso se devuelve una interfaz de ArrayList<Integer>implementación List? ¿Por qué no LinkedList<Integer>o cualquier otra clase genérica conforme a la Listinterfaz? No puedo encontrar nada sobre esto, excepto una breve mención de ArrayList aquí , en la sección de Notas de la API.

  2. ¿Qué significa el panel izquierdo de ? Obviamente es el tipo de retorno genérico ( en mi código aquí). Y creo que es el argumento de tipo genérico del método, pero ¿cómo se especifican? Miré en el documento de interfaz de Collector y no pude absorberlo.ingrese la descripción de la imagen aquí Stream.collect()RArrayList<Integer><R, A>


2
1. Utiliza una lista real debajo del capó, obviamente. Pero no sería prudente que una API revele el tipo de Lista subyacente real. Desde entonces, nunca más pudieron cambiar la implementación en el futuro. En general, a menudo es una buena idea exponer solo las interfaces y nunca el tipo subyacente real. 2. Res el tipo genérico del tipo resultante. AEl tipo genérico del tipo de acumulación intermedia del recopilador. Ese es el detalle de implementación de cómo funciona un colector. Divide y conquista, también para el procesamiento paralelo, recoge primero en tipos intermedios.
Zabuzard el

10
Casi nunca realmente quiere LinkedList. Hay un tweet de Josh Bloch , que dice "Lo escribí y nunca lo uso".
Andy Turner el

44
"Por qué Collectors.toList()en este caso devuelve un ArrayList<Integer>" Es posible que no devuelva un ArrayList. La Listimplementación no está definida , por lo que no puede confiar en la implementación que devuelve. Como dice el javadoc : "No hay garantías sobre el tipo , mutabilidad, serialización o seguridad de subprocesos de la Lista devuelta".
Andreas

3
y toList()no está devolviendo una ArrayListo List, está devolviendo una Collector, que eventualmente creará y devolverá una List, también la documentación dice: "... No hay garantías sobre el tipo , mutabilidad, serialización o seguridad de subprocesos de la Lista devuelta; si se requiere más control sobre la Lista devuelta, use toCollection (Supplier) .... "
user85421-Prohibido el

3
Recomiendo encarecidamente la documentación del paquete
Holger

Respuestas:


18
  1. Es una implementación predeterminada. ArrayListse usa, porque es mejor en la mayoría de los casos de uso, pero si no es adecuado para usted, siempre puede definir su propio colector y proporcionarle la fábrica Collectionque desee:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. Sí, Ay Rson parámetros genéricos de este método, Res el tipo de retorno, Tes el tipo de entrada y Aes un tipo intermedio, que aparece en todo el proceso de recopilación de elementos (puede no ser visible y no se refiere a esta función). El comienzo de Collector'javadoc' define esos tipos (son consistentes en todo el documento):

    T - el tipo de elementos de entrada a la operación de reducción
    A - el tipo de acumulación mutable de la operación de reducción (a menudo oculto como un detalle de implementación)
    R - el tipo de resultado de la operación de reducción


OK veo. Supongo que realmente debería apegarme List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());y llamar solo a los métodos declarados en la interfaz List en myList. De lo contrario, ¿podría ponerme en riesgo si Oracle decide cambiar la implementación predeterminada en Java8u1024 o 15?
user3207158

2
@ user3207158, el método devuelve a List, por lo que, independientemente de la implementación utilizada, el comportamiento es el mismo. Es poco probable que la interfaz se cambie en las versiones más recientes de Java.
Andronicus

1
  1. ¿Por qué Collectors.toList () en este caso devuelve una interfaz de lista de implementación de ArrayList?

Como sugiere la definición del método, devuelve una implementación de recopilador con el proveedor de recopilador como ArrayList. Por lo tanto, es muy claro a partir de la definición de método a continuación que Collectors.toListsiempre devuelve 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. Lo que hace el panel izquierdo de <R, A> R collect(Collector<? super T, A, R> collector)medios

Si hace referencia a los comentarios de la documentación, menciona con precisión cuáles son estos 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);

Gracias Señor. ¿De dónde sacaste el código fuente de Collectors.toList()(primer fragmento)? ¿Es openjdk?
user3207158

1
¡No! He descargado el código fuente en mi intelli j
Vinay Prajapati el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.