docs java list java-9

docs - documentation java 9



¿Cuál es la diferencia entre List.of y Arrays.asList? (3)

Java 9 introdujo un nuevo método de fábrica para listas, List.of :

List<String> strings = List.of("first", "second");

¿Cuál es la diferencia entre la opción anterior y la nueva? Es decir, cuál es la diferencia entre esto:

Arrays.asList(1, 2, 3);

y esto:

List.of(1, 2, 3);


Las diferencias entre Arrays.asList y List.of

Vea los JavaDocs y esta talk de Stuart Marks (o versiones anteriores de la misma).

Usaré lo siguiente para los ejemplos de código:

List<Integer> listOf = List.of(...); List<Integer> asList = Arrays.asList(...); List<Integer> unmodif = Collections.unmodifiableList(asList);

Inmutabilidad estructural (O: inmodificabilidad)

Cualquier intento de cambiar estructuralmente List.of dará como resultado una UnsupportedOperationException . Eso incluye operaciones como agregar , establecer y eliminar . Sin embargo, puede cambiar el contenido de los objetos en la lista (si los objetos no son inmutables), por lo que la lista no es "completamente inmutable".

Este es el mismo destino para las listas no modificables creadas con Collections.unmodifiableList . Solo esta lista es una vista de la lista original, por lo que puede cambiar si cambia la lista original.

Arrays.asList no es completamente inmutable, no tiene una restricción en el set .

listOf.set(1, "a"); // UnsupportedOperationException unmodif.set(1, "a"); // UnsupportedOperationException asList.set(1, "a"); // modified unmodif! unmodif is not truly unmodifiable

Del mismo modo, cambiar la matriz de respaldo (si la mantiene) cambiará la lista.

La inmutabilidad estructural viene con muchos efectos secundarios relacionados con la codificación defensiva, la concurrencia y la seguridad que están más allá del alcance de esta respuesta.

Nula hostilidad

List.of y cualquier colección desde Java 1.5 no permiten null como elemento. Intentar pasar null como elemento o incluso una búsqueda dará como resultado una NullPointerException .

Dado que Arrays.asList es una colección de 1.2 (el Marco de colecciones), permite null .

listOf.contains(null); // NullPointerException unmodif.contains(null); // allowed asList.contains(null); // allowed

Forma serializada

Como List.of se ha introducido en Java 9 y las listas creadas por este método tienen su propia forma serializada (binaria), no se pueden deserializar en versiones anteriores de JDK (sin compatibilidad binaria ). Sin embargo, puede des / serializar con JSON, por ejemplo.

Identidad

Arrays.asList llama internamente a la new ArrayList , que garantiza la desigualdad de referencia.

List.of depende de la implementación interna. Las instancias devueltas pueden tener igualdad de referencia, pero como esto no está garantizado, no puede confiar en él.

asList1 == asList2; // false listOf1 == listOf2; // true or false

Vale la pena mencionar que las listas son iguales (a través de List.equals ) si contienen los mismos elementos en el mismo orden, independientemente de cómo se crearon o qué operaciones admiten.

asList.equals(listOf); // true i.f.f. same elements in same order

Implementación (advertencia: los detalles pueden cambiar sobre las versiones)

Si el número de elementos en la lista de List.of es 2 o menos, los elementos se almacenan en campos de una clase especializada (interna). Un ejemplo es la lista que almacena 2 elementos (fuente parcial):

static final class List2<E> extends AbstractImmutableList<E> { private final E e0; private final E e1; List2(E e0, E e1) { this.e0 = Objects.requireNonNull(e0); this.e1 = Objects.requireNonNull(e1); } }

De lo contrario, se almacenan en una matriz de manera similar a Arrays.asList .

Eficiencia de tiempo y espacio

Las implementaciones de List.of que se basan en campos (tamaño <2) funcionan ligeramente más rápido en algunas operaciones. Como ejemplos, size() puede devolver una constante sin obtener la longitud de la matriz, y contains(E e) no requiere sobrecarga de iteración.

Construir una lista no modificable a través de List.of también es más rápido. Compare el constructor anterior con 2 asignaciones de referencia (e incluso la de una cantidad arbitraria de elementos) para

Collections.unmodifiableList(Arrays.asList(...));

que crea 2 listas más otros gastos generales. En términos de espacio, guarda el envoltorio de la UnmodifiableList Modificación más algunos centavos. En última instancia, los ahorros en el equivalente de HashSet son más convincentes.

List.of conclusión: use List.of cuando desee una lista que no cambie y Arrays.asList cuando desee una lista que pueda cambiar (como se muestra arriba).


Vamos a resumir las diferencias entre List.of y Arrays.asList

  1. List.of puede usar mejor cuando el conjunto de datos es menor y sin cambios, mientras que Arrays.asList se puede usar mejor en el caso de un conjunto de datos grande y dinámico.

  2. List.of ocupa mucho menos espacio de sobrecarga porque tiene una implementación basada en el campo y consume menos espacio de List.of dinámico, tanto en términos de sobrecarga fija como por elemento. mientras que Arrays.asList ocupa más espacio de arriba porque durante la inicialización crea más objetos en el montón.

  3. La colección devuelta por List.of es inmutable y, por lo tanto, segura para subprocesos, mientras que la colección devuelta por Arrays.asList es mutable y no segura para subprocesos. (Las instancias de colección inmutable generalmente consumen mucha menos memoria que sus contrapartes mutables).

  4. List.of no permite elementos nulos , mientras que Arrays.asList permite elementos nulos .


Arrays.asList devuelve una lista mutable mientras que la lista devuelta por List.of es immutable :

List<Integer> list = Arrays.asList(1, 2, null); list.set(1, 10); // OK List<Integer> list = List.of(1, 2, 3); list.set(1, 10); // Fails with UnsupportedOperationException

Arrays.asList permite elementos nulos, mientras que List.of no:

List<Integer> list = Arrays.asList(1, 2, null); // OK List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException

contains comporta de manera diferente con nulos:

List<Integer> list = Arrays.asList(1, 2, 3); list.contains(null); // Returns false List<Integer> list = List.of(1, 2, 3); list.contains(null); // Fails with NullPointerException

Arrays.asList devuelve una vista de la matriz aprobada, por lo que los cambios en la matriz también se reflejarán en la lista. Para List.of esto no es cierto:

Integer[] array = {1,2,3}; List<Integer> list = Arrays.asList(array); array[1] = 10; System.out.println(list); // Prints [1, 10, 3] Integer[] array = {1,2,3}; List<Integer> list = List.of(array); array[1] = 10; System.out.println(list); // Prints [1, 2, 3]