Inicialización de ArrayList equivalente a inicialización de matriz [duplicate]

6 minutos de lectura

avatar de usuario
jonathan

Soy consciente de que puede inicializar una matriz durante la creación de instancias de la siguiente manera:

String[] names = new String[] {"Ryan", "Julie", "Bob"};

¿Hay alguna manera de hacer lo mismo con un ArrayList? O debo agregar los contenidos individualmente con array.add()?

Arreglos.asList puede ayudar aquí:

new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

  • Vale la pena mencionar que, a menos que necesite estrictamente un ArrayList probablemente sea mejor simplemente usar el List eso es devuelto por Arrays#asList.

    – maéricos

    3 mayo 2010 a las 20:51

  • @maerics, también vale la pena mencionar que Arrays.asList() devolver un inmodificable recopilación. 🙂

    – Konstantín Yovkov

    9 oct 2013 a las 9:46

  • La lista devuelta por Arrays.asList() es NO inmodificable, @kocko. Tiene un tamaño fijo, pero puede cambiar las referencias para que apunten a objetos completamente diferentes como Arrays.asList(...).set(0,new String("new string")) Este código funcionará y establecerá el primer elemento de la lista en el objeto String con el valor “nueva cadena”. Y, de hecho, ¡escribe a través de la matriz nativa! Definitivamente no inmodificable

    – Jasón

    19 de abril de 2014 a las 15:22

  • ¿Por qué las personas nunca mencionan la declaración correcta de importación/inclusión/requerimiento en sus publicaciones?

    – Tomáš Zato – Reincorporar a Mónica

    9 de febrero de 2016 a las 20:58

  • Porque un IDE bien configurado escribirá las importaciones por usted, siempre que haya una sola clase coincidente, como es el caso aquí.

    – mérito

    9 febrero 2016 a las 22:25

avatar de usuario
Brian Agnew

Sí.

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

Lo que esto está haciendo en realidad es crear una clase derivada de ArrayList<String> (el conjunto externo de llaves hace esto) y luego declara un inicializador estático (el conjunto interno de llaves). Esto es en realidad un interno clase de la clase contenedora, por lo que tendrá un implícito this puntero. No es un problema a menos que desee serializarlo, o si espera que la clase externa se recopile como basura.

Entiendo que Java 7 proporcionará construcciones lingüísticas adicionales para hacer precisamente lo que quieres.

EDITAR: las versiones recientes de Java brindan funciones más utilizables para crear tales colecciones, y vale la pena investigar sobre lo anterior (proporcionado en un momento anterior a estas versiones)

  • No es mi voto negativo, pero lo considero un abuso bastante desagradable de las clases anónimas. Al menos no estás tratando de hacerlo pasar como una característica especial…

    –Michael Borgwardt

    3 mayo 2010 a las 21:34

  • No creo que crear una clase anónima sea malo. en si mismo. Sin embargo, debes ser consciente de ello.

    – Brian Agnew

    8 de mayo de 2010 a las 8:39

  • Supongo que sigue recibiendo votos negativos porque hace exactamente lo que el OP quería evitar: usar add() para cada elemento.

    – WXB13

    14 de enero de 2014 a las 9:04

  • Consideraría votar negativamente, porque creando una clase, solo para inicializar un solo objeto, me parece una exageración. Pero no soy lo suficientemente experto en java para saber si esto es algo malo. ¿Quizás crear miles de clases innecesarias, en un programa grande, se considera una buena codificación Java? También es horrendamente detallado, si hay muchos elementos. Esta ahí alguna ventaja a este enfoque, frente a otras respuestas propuestas?

    – El fabricante de herramientas Steve

    13/09/2015 a las 16:40


  • Es posible que haya sido rechazado porque solo funciona para los valores finales. Estoy de acuerdo en que su solución funciona para lo que hizo la pregunta, pero sabe que algunas personas están en StackOverflow.

    – José

    15 dic 2015 a las 16:50


Esto es lo más cercano que puede obtener:

ArrayList<String> list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob"));

Puedes ir aún más simple con:

List<String> list = Arrays.asList("Ryan", "Julie", "Bob")

Mirando la fuente de Arrays.asList, construye una ArrayList, pero por defecto se convierte en List. Entonces podría hacer esto (pero no de manera confiable para los nuevos JDK):

ArrayList<String> list = (ArrayList<String>)Arrays.asList("Ryan", "Julie", "Bob")

  • El ArrayList construido por asList no es un java.util.ArrayList, solo comparte el mismo. De hecho, no puede serlo, ya que el valor de retorno de asList se especifica como una lista de tamaño fijo, pero una ArrayList debe ser de tamaño variable.

    – mérito

    3 mayo 2010 a las 20:38

  • Estoy corregido. No leí lo suficiente en la fuente.

    – Fred Haslam

    4 de mayo de 2010 a las 3:28

avatar de usuario
Juan D.

Arrays.asList("Ryan", "Julie", "Bob");

Bueno, en Java no hay una sintaxis literal para las listas, así que tienes que hacer .add().

Si tiene muchos elementos, es un poco detallado, pero podría:

  1. usa Groovy o algo asi
  2. use Arrays.asList (matriz)

2 se vería algo como:

String[] elements = new String[] {"Ryan", "Julie", "Bob"};
List list = new ArrayList(Arrays.asList(elements));

Sin embargo, esto da como resultado una creación de objetos innecesaria.

La respuesta seleccionada es: ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21));

Sin embargo, es importante comprender que la respuesta seleccionada copia internamente los elementos varias veces antes de crear la matriz final, y que existe una forma de reducir parte de esa redundancia.

Comencemos por entender lo que está pasando:

  1. En primer lugar, los elementos se copian en el Arrays.ArrayList<T> creado por la fábrica estática Arrays.asList(T...).

    Esto no produce la misma clase que java.lang.ArrayLista pesar de tener el mismo nombre de clase simple. No implementa métodos como remove(int) a pesar de tener una interfaz de lista. Si llama a esos métodos arrojará un UnspportedMethodException. Pero si todo lo que necesita es una lista de tamaño fijo, puede detenerse aquí.

  2. A continuación el Arrays.ArrayList<T> construido en # 1 se pasa al constructor ArrayList<>(Collection<T>) donde el collection.toArray() se llama al método para clonarlo.

    public ArrayList(Collection<? extends E> collection) {
    ......
    Object[] a = collection.toArray();
    }
    
  3. A continuación, el constructor decide si adoptar la matriz clonada o copiarla nuevamente para eliminar el tipo de subclase. Ya que Arrays.asList(T...) internamente usa una matriz de tipo T, la misma que pasamos como parámetro, el constructor siempre rechaza usar el clon a menos que T sea un Objeto puro. (Por ejemplo, String, Integer, etc., todos se copian nuevamente, porque extienden Object).

    if (a.getClass() != Object[].class) {      
        //Arrays.asList(T...) is always true here 
        //when T subclasses object
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
    

Por lo tanto, nuestros datos se copiaron 3 veces solo para inicializar explícitamente ArrayList. Podríamos reducirlo a 2x si forzamos Arrays.AsList(T...) para construir un objeto[] array, para que luego ArrayList pueda adoptarlo, lo cual se puede hacer de la siguiente manera:

(List<Integer>)(List<?>) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5));

O tal vez solo agregar los elementos después de la creación podría ser lo más eficiente.

avatar de usuario
Ken de Guzmán

Que tal este.

ArrayList<String> names = new ArrayList<String>();
Collections.addAll(names, "Ryan", "Julie", "Bob");

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad