Tipo Lista vs tipo ArrayList en Java [duplicado]

Resuelto kji asked hace 14 años • 15 respuestas
(1) List<?> myList = new ArrayList<?>();

(2) ArrayList<?> myList = new ArrayList<?>();

Entiendo que con (1), se pueden intercambiar implementaciones de la interfaz List . Parece que (1) se usa normalmente en una aplicación independientemente de la necesidad (yo siempre uso esto).

Me pregunto si alguien usa (2).

Además, ¿con qué frecuencia (y puedo darme un ejemplo) la situación realmente requiere el uso de (1) sobre (2) (es decir, cuando (2) no sería suficiente... aparte de la codificación de interfaces y mejores prácticas , etc.)

kji avatar Feb 17 '10 14:02 kji
Aceptado

Casi siempre Listse prefiere ArrayListporque, por ejemplo, Listse puede traducir a LinkedListsin afectar el resto del código base.

Si se usa uno ArrayListen lugar de List, es difícil cambiar la ArrayListimplementación a LinkedListuno porque ArrayListse han usado métodos específicos en el código base que también requerirían una reestructuración.

Puede leer sobre las Listimplementaciones aquí .

Puede comenzar con un ArrayList, pero poco después descubrirá que otra implementación es la opción más adecuada.

kgiannakakis avatar Feb 17 '2010 07:02 kgiannakakis

Me pregunto si alguien usa (2).

Sí. Pero rara vez por una buena razón (en mi opinión).

Y la gente se quema porque consumieron ArrayListcuando deberían haber consumido List:

  • Los métodos de utilidad como Collections.singletonList(...)o Arrays.asList(...)no devuelven un archivo ArrayList.

  • Los métodos de la ListAPI no garantizan que se devuelva una lista del mismo tipo.

Por ejemplo, de alguien que se quema, en https://stackoverflow.com/a/1481123/139985 el cartel tuvo problemas con "cortar" porque ArrayList.sublist(...)no devuelve un ArrayList... y había diseñado su código para usarlo ArrayListcomo el tipo de todas las variables de su lista. Terminó "resolviendo" el problema copiando la sublista en un nuevo archivo ArrayList.

El argumento de que es necesario saber cómo se Listcomporta se aborda en gran medida mediante el uso de la RandomAccessinterfaz del marcador. Sí, es un poco complicado, pero la alternativa es peor.

Además, ¿con qué frecuencia la situación realmente requiere el uso de (1) sobre (2) (es decir, cuando (2) no sería suficiente... aparte de la "codificación de interfaces" y las mejores prácticas, etc.)

La parte de la pregunta "con qué frecuencia" no tiene respuesta objetiva.

(y ¿puedo obtener un ejemplo?)

En ocasiones, la aplicación puede requerir que utilice métodos en la ArrayListAPI que no están en la ListAPI. Por ejemplo ensureCapacity(int), trimToSize()o removeRange(int, int). (Y el último solo surgirá si ha creado un subtipo de ArrayList que declara que el método es public).

Esa es la única buena razón para codificar en la clase en lugar de en la interfaz, en mi opinión.

(Es teóricamente posible que obtenga una ligera mejora en el rendimiento... bajo ciertas circunstancias... en algunas plataformas... pero a menos que realmente necesite ese último 0,05%, no vale la pena hacerlo. Esto no es un buena razón, en mi opinión.)


No puedes escribir código eficiente si no sabes si el acceso aleatorio es eficiente o no.

Ese es un punto valido. Sin embargo, Java proporciona mejores formas de solucionar este problema; p.ej

public <T extends List & RandomAccess> void test(T list) {
    // do stuff
}

Si llama a eso con una lista que no se implementa, RandomAccessobtendrá un error de compilación.

También puedes probar dinámicamente... usando instanceof... si la escritura estática es demasiado incómoda. E incluso podría escribir su código para usar diferentes algoritmos (dinámicamente) dependiendo de si una lista admite o no el acceso aleatorio.

Tenga en cuenta que ArrayListno es la única clase de lista que implementa RandomAccess. Otros CopyOnWriteListincluyen Stacky Vector.

He visto gente hacer el mismo argumento sobre Serializable(porque Listno lo implementa)... pero el enfoque anterior también resuelve este problema. (En la medida en que se pueda solucionar utilizando tipos de tiempo de ejecución. La ArrayListserialización fallará si algún elemento no es serializable).


Finalmente, no voy a decir "porque es buen estilo". Esa "razón" es a la vez un argumento circular ("¿ Por qué es 'buen estilo'?") y una apelación a una autoridad superior no declarada (¡y probablemente inexistente!) ("¿ Quién dice que es 'buen estilo'?"). .

(Creo que es un buen estilo programar en la interfaz, pero no voy a dar esa razón. Es mejor que comprendas las verdaderas razones y llegues a las conclusiones correctas (en mi opinión) por ti mismo. La conclusión correcta puede no ser siempre la misma... dependiendo del contexto.)

Stephen C avatar Feb 17 '2010 07:02 Stephen C

Por ejemplo, puede decidir que a LinkedListes la mejor opción para su aplicación, pero luego decide que ArrayListpodría ser una mejor opción por motivos de rendimiento.

Usar:

List list = new ArrayList(100); // will be better also to set the initial capacity of a collection 

En lugar de:

ArrayList list = new ArrayList();

Para referencia:

ingrese la descripción de la imagen aquí

(publicado principalmente para el diagrama de colección)

Maxim Shoustin avatar Sep 09 '2014 15:09 Maxim Shoustin