Inicialización de un ArrayList en una línea

java collections arraylist initialization


Quería crear una lista de opciones para las pruebas.Al principio,hice esto:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

Entonces,refactoricé el código de la siguiente manera:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

¿Hay una mejor manera de hacer esto?




Answer 1 coobird


En realidad, probablemente la "mejor" forma de inicializar ArrayList es el método que escribió, ya que no necesita crear una nueva List a de ninguna manera:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

El problema es que se requiere bastante tipeo para referirse a esa instancia de la list a .

Existen alternativas,como hacer una clase interna anónima con un inicializador de instancia (también conocido como "inicialización de doble corsé"):

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}};

Sin embargo, no me gusta demasiado ese método porque lo que termina es una subclase de ArrayList que tiene un inicializador de instancia, y esa clase se crea solo para crear un objeto, eso me parece un poco exagerado. .

Lo que hubiera sido bueno fue que se aceptara la propuesta de Collection Literals para Project Coin (estaba programada para ser introducida en Java 7, pero tampoco es probable que forme parte de Java 8):

List<String> list = ["A", "B", "C"];

Desafortunadamente, no lo ayudará aquí, ya que inicializará una List a inmutable en lugar de una Lista de ArrayList , y además, aún no está disponible, si alguna vez lo estará.




Answer 2 Tom


Sería más simple si solo lo declararas como una List a : ¿tiene que ser una Lista de Array?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

O si sólo tienes un elemento:

List<String> places = Collections.singletonList("Buenos Aires");

Esto significaría que los places son inmutables (al intentar cambiarlo se generará una excepción UnsupportedOperationException ).

Para hacer una lista mutable que sea una ArrayList concreta , puede crear una ArrayList a partir de la lista inmutable:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));



Answer 3 Christoffer Hammarström


La respuesta simple

En Java 9 o posterior, después de List.of() :

List<String> strings = List.of("foo", "bar", "baz");

Con Java 10 o posterior, esto se puede acortar con la palabra clave var .

var strings = List.of("foo", "bar", "baz");

Esto le dará una List ainmutable , por lo que no se puede cambiar.
Que es lo que quieres en la mayoría de los casos en los que lo estás poblando.


Java 8 o anterior:

List<String> strings = Arrays.asList("foo", "bar", "baz");

Esto le dará una List respaldada por una matriz, por lo que no puede cambiar la longitud.
Pero puede llamar a List.set , por lo que sigue siendo mutable .


Puede hacer que Arrays.asList sea aún más corto con una importación estática:

List<String> strings = asList("foo", "bar", "baz");

La importación estática:

import static java.util.Arrays.asList;  

Lo que cualquier IDE moderno sugerirá y hará automáticamente por ti.
Por ejemplo, en IntelliJ IDEA pulsa Alt+Enter y seleccione Static import method... .


Sin embargo, yo no recomiendo el acortamiento de la List.of método para of , ya que se vuelve confusa.
List.of ya es lo suficientemente corto y se lee bien.


Usando Stream s

¿Por qué tiene que ser una List ?
Con Java 8 o posterior puedes usar un Stream que es más flexible:

Stream<String> strings = Stream.of("foo", "bar", "baz");

Puede concatenar Stream s:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

O puede pasar de una Stream a una List :

import static java.util.stream.Collectors.toList;

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

Pero preferiblemente, solo use el Stream sin recopilarlo en una List a .


Si realmente necesita una java.util.ArrayList

(Probablemente no)
Para citar JEP 269 (énfasis mío):

Hay un pequeño conjunto de casos de uso para inicializar una instancia de colección mutable con un conjunto predefinido de valores. Por lo general, es preferible tener esos valores predefinidos en una colección inmutable, y luego inicializar la colección mutable a través de un constructor de copia.


Si desea tanto rellenar previamente un ArrayList y añadir a ello después (¿por qué?), El uso

ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

o en Java 8 o antes:

ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

o usando Stream :

import static java.util.stream.Collectors.toCollection;

ArrayList<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

Pero, de nuevo, es mejor usar el Stream directamente en lugar de recopilarlo en una List a .


El programa a las interfaces,no a las implementaciones

Dijiste que declaraste la lista como ArrayList en tu código, pero solo deberías hacerlo si estás usando algún miembro de ArrayList que no está en List .

Lo cual es muy probable que no estés haciendo.

Por lo general, debe declarar las variables mediante la interfaz más general que va a utilizar (por ejemplo , Iterable , Collection o List ) e inicializarlas con la implementación específica (por ejemplo , ArrayList , LinkedList o Arrays.asList() ).

De lo contrario,estarás limitando tu código a ese tipo específico,y será más difícil cambiarlo cuando quieras.

Por ejemplo, si está pasando una ArrayList a un void method(...) :

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need .get(index):
void method(List<String> strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

Otro ejemplo sería siempre declarar variable un InputStream a pesar de que generalmente es un FileInputStream o un BufferedInputStream , porque un día pronto usted u otra persona querrán usar algún otro tipo de InputStream .




Answer 4 Randyaa


Si necesitas una simple lista de tamaño 1:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

Si necesitas una lista de varios objetos:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");



Answer 5 Paweł Adamski


Con guayaba puedes escribir:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

En Guava también hay otros constructores estáticos útiles. Puedes leer sobre ellos aquí .