Colecciones Java: la interfaz de lista

C

Introducción

los Marco de colecciones de Java es un marco fundamental y esencial que cualquier desarrollador de Java fuerte debería conocer como la palma de su mano.

Una colección en Java se define como un grupo o colección de objetos individuales que actúan como un solo objeto.

Hay muchas clases de colección en Java y todas ellas extienden el java.util.Collection y java.util.Map interfaces. En su mayoría, estas clases ofrecen diferentes formas de formular una colección de objetos dentro de un solo objeto.

Colecciones de Java es un marco que proporciona numerosas operaciones sobre una colección: búsqueda, clasificación, inserción, manipulación, eliminación, etc.

Esta es la primera parte de una serie de artículos de las colecciones de Java:

  • La interfaz de lista (estás aquí)
  • La interfaz de conjunto
  • La interfaz del mapa
  • Las interfaces Queue y Deque

Problemas con matrices

Matrices son una de las primeras cosas con las que se presenta un nuevo desarrollador Java horneado.

Una matriz de objetos, muy similar a una colección, representa un grupo de objetos como un solo objeto.

Tanto una matriz como una colección son un objeto que representa muchos otros objetos, entonces, ¿por qué se necesitan ambos?

Consideremos una colección de productos:

Product door = new Product("Wooden Door", 35);
Product floorPanel = new Product("Floor Panel", 25);

Tenemos una puerta de madera y un panel de puerta, con un peso de 35 kg y 25 kg respectivamente. Estos son POJOs, lo que significa que solo tienen un par de métodos getter y setter y un toString() método.

Con esto, es bastante sencillo crear una instancia de una matriz de estos objetos:

Product[] products = { door, floorPanel };

Impresión de matrices

Hay muchas razones por las que alguien querría imprimir una matriz, incluida la depuración o la devolución de los resultados:

System.out.println(products);

Sin embargo, cuando intentamos imprimirlo, recibimos un resultado que no es muy amigable para los humanos:

com.demo.collections.Product;@14ae5a5

De hecho, necesitamos confiar en la clase auxiliar java.util.Arrays para obtener un resultado sensato:

System.out.println(Arrays.toString(products));

Esta vez, estamos viendo algo que tiene más sentido:

[Product{name="Wooden Door", weight=35}, Product{name="Floor Panel", weight=25}]

Agregar y eliminar elementos

Nuestra colección de productos se hizo más grande y se supone que debemos agregar una ventana a la matriz:

final Product window = new Product("Window", 15);
products = add(window, products);
System.out.println(Arrays.toString(products));


public static Object[] add(Object[] array, Object... elements) {
    Object[] tempArray = new Object[array.length + elements.length];
    System.arrayCopy(array, 0, tempArray, 0, array.length);

    for(int i = 0; i < elements.length; i++) {
        tempArray[array.length+i] = elements[i];
        return tempArray;
    }
}

Este es exactamente el tipo de situación en la que probablemente prefieras pegar un tiro en la pierna, porque las matrices no cambian de tamaño.

Para agregar un elemento, tenemos que hacer una copia de la matriz en una nueva matriz, instanciarla con los nuevos elementos y asignar la nueva matriz a nuestra variable de referencia.

Las matrices son una construcción de bajo nivel y no nos brindan muchas características, mientras que las colecciones están hechas para combatir ese mismo problema y ofrecen muchas características y una gran funcionalidad.

Colecciones

Java Collections Framework se envía con el propio JDK. Vale la pena recordar que en los viejos tiempos, especialmente para las personas que escribían código C, los desarrolladores no tenían estructuras de datos para elegir. De hecho, la gente solía escribir sus propias estructuras de datos, lo que algunos hacen incluso hoy.

Existen razones legítimas de rendimiento por las que alguien podría encontrar una estructura de datos personalizada ideal para un proyecto específico. Pero, para la mayoría de los desarrolladores, confiar en el marco existente es una buena opción.

Java se utiliza para construir aplicaciones y sistemas grandes y complejos. Dicho esto, casi todas las aplicaciones de Java terminarán usando el marco de colecciones en un momento u otro.

Todas las clases de recopilación tienen una estructura de datos subyacente que están implementando: árboles, tablas hash, mapas hash, colas, etc. . No hay necesidad de reinventar la rueda si ya está servida, a menos que desee practicar y desafiarse a sí mismo para encontrar soluciones innovadoras y alternativas.

Echaremos un vistazo a algunos tipos diferentes de colecciones en Java:

  • Liza – Una colección secuencial (ordenada). Realizan un seguimiento de las posiciones de todos los elementos, como matrices, y ofrecen operaciones de búsqueda, iteración y vista de rango de sus elementos. Las listas pueden tener elementos duplicados.
  • Conjuntos – Aplica restricciones de unicidad: no puede contener elementos duplicados. No se preocupa por el orden de iteración dentro de sí mismo, ya que modela la abstracción matemática del conjunto. Los conjuntos no ofrecen más funciones que las heredadas de las colecciones.
  • Colas – Introducir orden de modificación, es decir, si agregas elementos en un orden determinado, tienes que seguir un orden determinado. Las colas ofrecen operaciones adicionales de inserción, eliminación e inspección de sus elementos. Es único que las colas sigan el FIFO Estructura (primero en entrar, primero en salir).
  • Deques – Al igual que las colas, las colas de dos extremos (abreviadas a deques) ofrecen además la posibilidad de realizar operaciones en elementos de ambos lados de la cola.
  • Mapas – Aunque las implementaciones de java.util.Map no se consideran “colecciones verdaderas”, ofrecen operaciones de visualización de colecciones que prácticamente les permiten la manipulación a nivel de colección. Esta colección no es una colección de valores individuales, sino pares. Se trata de asociaciones entre claves y valores únicos (mapas) que se pueden buscar a partir de esas claves. Es importante tener en cuenta que las claves son únicas y cada clave está asociada con un valor, pero un valor puede estar asociado con más de una clave.

Interfaz Collection

Como se mencionó anteriormente, todas las interfaces de colección dentro de la API de Java extienden una interfaz común: java.util.Collection. Esta interfaz principal proporciona todas las funciones de colecciones comunes.

Cada subinterfaz tiene varias implementaciones y algunas de estas subinterfaces ofrecen operaciones adicionales:

El punto clave a entender es que cada interfaz define el comportamiento y las características funcionales donde podemos utilizar múltiples estructuras de datos mientras que las implementaciones definen las características de desempeño, utilizan una estructura de datos específica y son instanciables.

Los métodos más utilizados en el Collection interfaz son:

Nombre del método Descripción del método
contiene (elemento)Verdadero si el elemento está en esta colección, falso en caso contrario

Talla()Obtener la cantidad de elementos de la colección
esta vacio()Verdadero si size () == 0, falso en caso contrario
agregar (elemento)Agrega el elemento al comienzo de esta colección
addAll (colección)Agregue todos los elementos de la colección de argumentos a esta colección
eliminar (elemento)Quitar el elemento de esta colección
removeAll (colección)Eliminar todos los elementos de la colección de argumentos a esta colección
retener todo ()Eliminar todos los elementos de esta colección que no están en la colección de argumentos
containsAll (colección)Verdadero si todos los elementos de la colección de argumentos están en esta colección
claro()Eliminar todos los elementos de esta colección

Liza

La primera interfaz, y probablemente la más utilizada: java.util.List.

Cada elemento de la lista tiene un índice, un int valor que define su posición. El recuento de indexación comienza en 0, lo mismo que la indexación que podemos encontrar con las matrices.

los java.util.List La interfaz también agrega un par de otras operaciones más allá de las operaciones habituales de recolección:

  • get(int index)
  • set(int index, Object object)

Estas operaciones se explican por sí mismas y no necesitan más explicación. Sin embargo, echemos un vistazo a algunos ejemplos de código.

Agregar un elemento

Utilizando el add() método, podemos agregar fácilmente objetos a nuestra lista:

List<String> products = new ArrayList<>();
products.add("Mug");
products.add("Wallet");
products.add("Phone");
System.out.println(products);

Salida:

[Mug, Wallet, Phone]

Nota: Estamos creando una instancia de la lista como su implementación concreta ArrayList. En la mayoría de los casos, usaríamos esta implementación para una lista.

Otra nota: Puede especificar el tamaño inicial de ArrayList a través del constructor para evitar cambiar el tamaño si conoce un tamaño definitivo.

La interfaz también proporciona otra versión del add() método, incluido un índice. En este caso, agregamos el elemento al índice dado, y si el índice ya está tomado por otro elemento, todos los elementos después del agregado se desplazan a la derecha en uno:

products.add(2, "Pen");
System.out.println(products);

Salida:

[Mug, Wallet, Pen, Phone]

Recuperando elementos

Utilizando el get() método con el índice dado, podemos recuperar un elemento específico en la lista:

System.out.println(products.get(0));

Salida:

[Mug]

Eliminar elementos

Utilizando el remove() método, podemos eliminar un elemento de la lista. Llamar a este método devolverá el elemento y desplazará los elementos posteriores un índice hacia atrás, para completar el hueco ahora existente en la secuencia:

System.out.println(products.remove(1));

Salida:

[Wallet]

Elementos de ajuste

Utilizando el set() método, podemos reemplazar un elemento existente dado un índice:

products.set(1, "Book");

System.out.println(products);

Salida:

[Mug, Book, Phone]

Buscando elementos

Utilizando el indexOf() método, también podemos buscar valores, dado un índice. Si la búsqueda falla y no existe ningún objeto con el índice dado, la lista devolverá -1. En el caso de varios objetos iguales, la lista devolverá solo el primer índice.

Utilizando el lastIndexOf() devolverá el último índice del elemento dado.

System.out.println(products.indexOf(5));

Salida:

-1

Elementos iterativos

Aunque es posible iterar con for y enhanced-for bucles, la interfaz proporciona dos nuevas clases de ayuda que nos permiten iterar a través de listas: Iterator y ListIterator:

for (Iterator<E> iterator = list.iterator(); iterator.hasNext(); ) {
    E element = iterator.next();
    element.someMethod();
    iterator.remove(element);
    //...
}

for (ListIterator<E> iterator = list.listIterator(); iterator.hasNext(); ) {
    E element = iterator.next();
    element.someMethod();
    iterator.remove(element);
    //...
}

Nota: Los ListIterator ofrece más control sobre la iteración de la lista, ya que permite el recorrido en ambas direcciones, mientras que Iterator solo permite el recorrido en una dirección.

Además, Java 8 nos presenta una forma realmente sencilla de imprimir los elementos utilizando una referencia de método:

list.forEach(System.out::println);

Implementaciones y diferencias

Lista de arreglo: implementos java.util.List como una matriz de redimensionamiento dinámico:

  • Buena implementación de propósito general
  • Usado como predeterminado
  • Más simpático caché de CPU

Lista enlazada: implementos java.util.List como una lista doblemente enlazada:

  • Peor rendimiento para muchas operaciones
  • Úselo al agregar elementos al principio
  • Úselo al agregar / quitar mucho

Generalmente hablando, ArrayList es mucho más utilizado que LinkedList. Y para citar a Joshua Bloch, el hombre que escribió LinkedList:

“¿Alguien realmente usa LinkedList? Yo lo escribí y nunca lo uso”.

Comparación de rendimiento

Debido a sus diferentes naturalezas, estas implementaciones tienen diferentes enfoques y tiempos de ejecución de métodos.

Dependiendo de los requisitos, tendrá que elegir cuál usar. En general, por su doble vinculación, LinkedList es bueno para adiciones y remociones frecuentes mientras que ArrayList es bueno para buscar debido al acceso aleatorio.

Conclusión

El marco de las Colecciones de Java es un marco fundamental que todo desarrollador de Java debería saber utilizar.

En el artículo, hemos hablado de las colecciones en general, los problemas con las matrices y cómo el framework las combate. Luego, pasamos a las implementaciones de esta interfaz, sus ventajas y desventajas, así como las operaciones que seguramente usará en un momento u otro.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad