Inicialización de una ArrayList en una línea


2757

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

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

Luego, refactoré 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?


34
Si esto está destinado a la prueba de la unidad, trate de hacer un swing. Puede escribir su código de prueba en él mientras prueba el código de Java, y usarArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]
ripper234

3
En Java SE 7, puede sustituir el tipo parametrizado del constructor con un conjunto vacío de parámetros de tipo (<>): Map <String, List <String>> myMap = new HashMap <> ();
Rose


2
use inicialización de doble arriostramiento :)
Mohammadreza Khatami

8
Stream.of ("val1", "val2"). Collect (Collectors.toList ()); // crea ArrayList, solución Java8.
torina

Respuestas:


2025

En realidad, probablemente la "mejor" forma de inicializar ArrayListes el método que escribió, ya que no necesita crear uno nuevo Listde ninguna manera:

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

El problema es que hay que escribir bastante para referirse a esa listinstancia.

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

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

Sin embargo, no me gusta mucho ese método porque lo que termina es una subclase de la ArrayListcual 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á un inmutable en Listlugar de un ArrayList, y además, aún no está disponible, si alguna vez lo estará.


172
Consulte stackoverflow.com/questions/924285 para obtener más información sobre la inicialización de doble paréntesis, los pros y los contras.
Eddie

66
@Eddie: Buen llamado para el enlace: una oración sobre la inicialización de doble llave no es suficiente para describirlo completamente.
coobird

2
Solo funciona si no confía en la Lista de boxeo automático <Doble> lista = [1.0, 2.0, 3.0]; falla
Richard B

1
Te falta un punto y coma en la inicialización de doble lista
Don Larynx

66
Dado que esta respuesta es el Proyecto Coin más votado y mencionado, creo que debería mencionar que java 9 se envió con la sintaxis List.of (...): docs.oracle.com/javase/9/docs/api/java/util/ List.html # of-E ...-
Asaf

2155

Sería más simple si simplemente lo declararas como List: ¿tiene que ser una ArrayList?

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

O si solo tiene un elemento:

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

Esto significaría que placeses inmutable (intentar cambiarlo provocará una UnsupportedOperationExceptionexcepción).

Para hacer una lista mutable que sea concreta ArrayList, puede crear una ArrayListdesde la lista inmutable:

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

18
@Marcase: ¿No puede cambiar su clase para usar una Lista en lugar de ArrayList?
Lawrence Dol

74
Según mi respuesta, si no está utilizando métodos específicos para ArrayList, sería mejor diseñar cambiar la declaración a List. Especificar interfaces, no implementaciones.
Christoffer Hammarström

99
@Christoffer Hammarström: si cambia la declaración a Lista y usa la Lista <String> places = Arrays.asList (...); no podrá usar places.add ("blabla")
maks el

57
Para ser claros, asList(...)devuelve un tamaño fijo Listque explota en operaciones de mutación como removey clear, cosas que el Listcontrato afirma respaldar. Incluso si dejó la declaración como List, debe usarla List l = new ArrayList(asList(...))para obtener un objeto que no arroje excepciones OperationNotSupported. Principio de sustitución de Liskov alguien?
Splash

55
@Splash: removey clearson operaciones opcionales en List, así asList(...)que sigue el contrato. En ninguna parte el OP dice que necesita agregar más elementos más tarde, el ejemplo es solo un Listque debe inicializarse con tres elementos.
Christoffer Hammarström

872

La respuesta simple

En Java 9 o posterior, después List.of()se agregó:

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

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

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

Esto le dará un inmutable List , por lo que no se puede cambiar.
Que es lo que quieres en la mayoría de los casos donde lo estás rellenando.


Java 8 o anterior:

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

Esto le dará un Listrespaldo de una matriz, por lo que no puede cambiar la longitud.
Pero puedes llamar List.set, así que todavía es mutable .


Puede Arrays.asListacortar aún más 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 usted.
Por ejemplo, en IntelliJ IDEA, presiona Alt+Entery selecciona Static import method....


Sin embargo, no recomiendo acortar el List.ofmétodo of, porque eso se vuelve confuso.
List.ofya es lo suficientemente corto y se lee bien.


Usando Streams

¿Por qué tiene que ser un List?
Con Java 8 o posterior, puede usar uno Streamque sea más flexible:

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

Puedes concatenar Streams:

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

O puedes ir de un Streama un List:

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

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

Pero preferiblemente, solo use el Streamsin recogerlo a List.


Si realmente necesitas unjava.util.ArrayList

(Probablemente no.)
Para citar JEP 269 (el énfasis es 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 una rellenar previamente ArrayList y agregar a ella después (¿por qué?), El uso

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

o en Java 8 o anterior:

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 Streamdirectamente en lugar de recopilarlo en a List.


Programa para interfaces, no para implementaciones

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

Lo que probablemente no estés haciendo.

Por lo general, sólo debe declarar variables por la interfaz más general que se va a utilizar (por ejemplo Iterable, Collectiono List), e inicializar con la aplicación específica (por ejemplo ArrayList, LinkedListo Arrays.asList()).

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

Por ejemplo, si está pasando un ArrayLista 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 una variable InputStreama pesar de que generalmente es a FileInputStreamo a BufferedInputStream, porque un día pronto usted u otra persona querrán usar otro tipo de InputStream.


3
@jollyroger: Arrays.asListes un método estático. Ver docs.oracle.com/javase/1.5.0/docs/guide/language/…
Christoffer Hammarström

2
@ ChristofferHammarström En ese caso, mi mente novata me dice que la importación estática muestra una gran semejanza con las variables globales y los peligros relacionados con dicho uso. ¿Es correcta esta suposición y es también la razón por la que la respuesta similar anterior obtuvo más votos?
jollyroger 01 de

2
La respuesta anterior, creo que estás hablando, se hizo un año antes. Y no, el problema con las variables globales es que son mutables. No tienen nada que ver con las importaciones estáticas.
Christoffer Hammarström

2
Si no desea la importación estática, también puede definir la ruta completa al método estático asList, así: List <String> strings = java.util.Arrays.asList ("", "");
Geert Weening

2
O puede usar import java.util.Arrays; y Arrays.asList ("", ""); No tiene que usar una importación estática. No tienes que usar una ruta completa. Los métodos estáticos no se preocupan por la importación. Simplemente se molestan si usa una instancia para encontrarlos.
candied_orange

111

Si necesita una lista simple de tamaño 1:

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

Si necesita una lista de varios objetos:

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

57

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í .


1
Estoy bastante seguro de que usted puede hacer esto con sólo java.util.Arrayscomo,List<String> names = Arrays.asList("Beckah", "Sam", "Michael");
Beckah

2
El método @beckah Arrays.asLists crea objetos de tipo List, mientras que la pregunta se trata de crear ArrayList
Paweł Adamski


34

Los literales de colección no llegaron a Java 8, pero es posible usar Stream API para inicializar una lista en una línea bastante larga:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

Si necesita asegurarse de que su Listes un ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

34

Con y más arriba, como se sugiere en JEP 269: Convenience Factory Methods for Collections , esto podría lograrse usando literales de colección ahora con -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

También se aplicaría un enfoque similar Map:

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

que es similar a la propuesta de Collection Literals según lo indicado por @coobird. Más aclarado en el JEP también:


Alternativas

Los cambios de idioma se han considerado varias veces y se han rechazado:

Propuesta de proyecto de moneda, 29 de marzo de 2009

Propuesta de proyecto de moneda, 30 de marzo de 2009

Discusión del JEP 186 sobre lambda-dev, enero-marzo de 2014

Las propuestas de lenguaje se reservaron con preferencia a una propuesta basada en la biblioteca como se resume en este mensaje.

Relacionado: ¿Cuál es el punto de los métodos de fábrica de conveniencia sobrecargados para colecciones en Java 9


31
import com.google.common.collect.ImmutableList;

....

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

44
No quiero agregar una nueva dependencia solo para hacer eso.
Macarse

66
Es lo mismo Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"))que sucede unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))con las importaciones estáticas. No necesita Google Collections para esto.
Christoffer Hammarström

99
No, no es lo mismo. Como ImmutableList está documentando su inmutabilidad en el tipo de resultado cuando inmodificableList lo enmascara como una Lista normal.
David Pierre

2
En lugar de la inmutable, las colecciones de Google también ofrecen una lista de matriz mutable: List <String> = Lists.newArrayList ("Buenos Aires", "Córdoba", "La Plata");
L. Holanda

3
Vas a pasar eso ImmutableLista otros métodos que toman un List, y luego has perdido esa documentación de todos modos.
Christoffer Hammarström

23

Podrías crear un método de fábrica:

public static ArrayList<String> createArrayList(String ... elements) {
  ArrayList<String> list = new ArrayList<String>();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList<String> places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

Pero no es mucho mejor que tu primera refactorización.

Para una mayor flexibilidad, puede ser genérico:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

1
Mire hacia atrás en la publicación original, está pidiendo la inicialización de la matriz en una línea , no 7 líneas adicionales.
L. Holanda

77
@LeoHolanda: Crear métodos de fábrica para cada pequeña cosa es demasiado, estoy de acuerdo. Pero dependiendo de la situación y de la cantidad de veces que se utilizará ese método, podría tener sentido crearlo. La creación de capas de abstracción adicionales está destinada a eliminar la complejidad, al crear métodos más significativos que capturan la intención del diseñador.
Jordão


8

La forma más compacta de hacer esto es:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);

8

Simplemente use el siguiente código de la siguiente manera.

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

2
@bsd Puede usar este método para declarar la lista antes de ingresar cualquier método. Entonces, al definir variables de clase, el contenido se puede agregar a la lista sin tener que invocar un método para hacerlo.
melwil

2
La inicialización de llaves dobles debe evitarse en la medida de lo posible. ver: stackoverflow.com/a/924326/760393
Raúl el

8

Con Eclipse Collections puede escribir lo siguiente:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

También puede ser más específico sobre los tipos y si son mutables o inmutables.

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

También puede hacer lo mismo con Conjuntos y Bolsas:

Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Nota: Soy un committer para Eclipse Collections.


7

Aquí hay otra forma:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());

7

(Debería ser un comentario, pero demasiado largo, así que nueva respuesta). Como otros han mencionado, el Arrays.asListmétodo es de tamaño fijo, pero ese no es el único problema con él. Tampoco maneja la herencia muy bien. Por ejemplo, suponga que tiene lo siguiente:

class A{}
class B extends A{}

public List<A> getAList(){
    return Arrays.asList(new B());
}

Lo anterior genera un error de compilación porque List<B>(que es lo que devuelve Arrays.asList) no es una subclase de List<A>, aunque puede agregar Objetos de tipo B a un List<A>objeto. Para evitar esto, debe hacer algo como:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

Esta es probablemente la mejor manera de hacerlo, especialmente. si necesita una lista ilimitada o necesita usar la herencia.


6

Puede usar las siguientes declaraciones:

Fragmento de código:

String [] arr = {"Sharlock", "Homes", "Watson"};

List<String> names = Arrays.asList(arr);

Puede alinear la primera expresión para tener una solución compacta:letters = Arrays.asList(new String[]{"A", "B", "C"});
Pavel Repin

5

Como dijo Tom :

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

Pero como se quejó de querer una ArrayList, primero debe saber que ArrayList es una subclase de List y simplemente puede agregar esta línea:

ArrayList<String> myPlaces = new ArrayList(places);

Sin embargo, eso podría hacer que te quejes de "rendimiento".

En ese caso, no tiene sentido para mí, por qué, dado que su lista está predefinida, no se definió como una matriz (ya que el tamaño se conoce en el momento de la inicialización). Y si esa es una opción para ti:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

En caso de que no le importen las pequeñas diferencias de rendimiento, también puede copiar una matriz a una ArrayList de manera muy simple:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

Está bien, pero en el futuro necesita un poco más que el nombre del lugar, también necesita un código de país. Asumiendo que esta sigue siendo una lista predefinida que nunca cambiará durante el tiempo de ejecución, entonces es apropiado usar un enumconjunto, que requeriría una nueva compilación si la lista necesita ser cambiada en el futuro.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

se convertiría:

enum Places {
    BUENOS_AIRES("Buenos Aires",123),
    CORDOBA("Córdoba",456),
    LA_PLATA("La Plata",789);

    String name;
    int code;
    Places(String name, int code) {
      this.name=name;
      this.code=code;
    }
}

Las valuesenumeraciones tienen un método estático que devuelve una matriz que contiene todos los valores de la enumeración en el orden en que se declaran, por ejemplo:

for (Places p:Places.values()) {
    System.out.printf("The place %s has code %d%n",
                  p.name, p.code);
}

En ese caso, supongo que no necesitarías tu ArrayList.

PS Randyaa demostró otra forma agradable usando el método de utilidad estática Collections.addAll .


5

Java 9 tiene el siguiente método para crear una lista inmutable :

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

que se adapta fácilmente para crear una lista mutable, si es necesario:

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

Métodos similares están disponibles para Sety Map.


1
Es bueno que hayas dicho explícitamente "lista inmutable" y luego hayas mostrado otro ejemplo de lista mutable porque deja en claro cuál usar cuando.
heredar


4

Sí, con la ayuda de matrices, puede inicializar la lista de matrices en una línea,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");

4

Puedes usar StickyListdesde Cactoos :

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

3

Pruebe con esta línea de código:

Collections.singletonList(provider)

1
Agregue una breve descripción de su respuesta.
Morales Batovski

2

En Java, no puedes hacer

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

Como se señaló, necesitaría hacer una inicialización de doble llave:

List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};

Pero esto puede obligarlo a agregar una anotación @SuppressWarnings("serial")o generar un UUID en serie que es molesto. Además, la mayoría de los formateadores de código lo desenvolverán en múltiples declaraciones / líneas.

Alternativamente puedes hacer

List<String> places = Arrays.asList(new String[] {"x", "y" });

pero entonces es posible que desee hacer una @SuppressWarnings("unchecked").

También según javadoc, deberías poder hacer esto:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

Pero no puedo hacer que se compile con JDK 1.6.


55
¡Incorrecto! Usted puede hacer la primera línea, y esa es la respuesta correcta por cierto
Bohemia

1
Collections.singletonList(messageBody)

¡Si necesita tener una lista de un artículo !

Colecciones es del paquete java.util .


1

La mejor manera de hacerlo:

package main_package;

import java.util.ArrayList;


public class Stackkkk {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<Object>();
        add(list, "1", "2", "3", "4", "5", "6");
        System.out.println("I added " + list.size() + " element in one line");
    }

    public static void add(ArrayList<Object> list,Object...objects){
        for(Object object:objects)
            list.add(object);
    }
}

Simplemente cree una función que pueda tener tantos elementos como desee y llámela para agregarlos en una línea.


1
Si pasa por todos los problemas, podría convertirlo en un método de plantilla en lugar de utilizarlo sin formato Object.
Robert

1

Aquí está el código de AbacusUtil

// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);

// The most efficient way, which is similar with Arrays.asList(...) in JDK. 
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");

Declaración: Soy el desarrollador de AbacusUtil.


0

Para mí, Arrays.asList () es el mejor y conveniente. Siempre me gusta inicializar de esa manera. Si es un principiante en Java Collections, me gustaría que consulte la inicialización de ArrayList


¿Por qué Arrays.asList () es mejor que crear una nueva ArrayList en una línea con add()métodos?
IgorGanapolsky

0

¿Por qué no hacer una función de utilidad simple que haga esto?

static <A> ArrayList<A> ll(A... a) {
  ArrayList l = new ArrayList(a.length);
  for (A x : a) l.add(x);
  return l;
}

" ll" significa "lista literal".

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

0

Curiosamente, no aparece una línea con el otro método sobrecargadoStream::collect

ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );

-1

En realidad, es posible hacerlo en una línea:

Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})

3
¿Puedo preguntar qué agrega esto a la pregunta? Esta respuesta ya está cubierta varias veces por otras respuestas.
Mysticial

En realidad, esta es una solución realmente mala, ya que crea una LISTA ABSTRACTA. No podrá agregar nada más al contenedor.
Atais
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.