Uploaded by rfatla82

ListasJava (1)

advertisement
Definición de listas
Las listas son colecciones ordenadas de objetos. Son similares a las secuencias en
matemáticas en ese sentido. Sin embargo, son diferentes a los conjuntos que no tienen
un cierto orden.
Un par de cosas a tener en cuenta: las listas pueden tener elementos duplicados y
nulos. Son tipos de referencia o de objeto y, como todos los objetos en Java, se
almacenan en las pilas.
Una lista en Java es una interfaz y hay muchos tipos de listas que implementan esta
interfaz.
Collection Hierarchy
Usaré ArrayList en los primeros ejemplos, porque es el tipo de lista más utilizado.
ArrayList es básicamente un arreglo de tamaño variable. Casi siempre, vas a querer
usar ArrayList en lugar de arreglos regulares, ya que brindan muchos métodos útiles.
La única ventaja de un arreglo solía ser su tamaño fijo (al no asignar más espacio del
que necesita). Pero las listas también admiten tamaños fijos ahora.
Cómo crear una lista en Java
Basta de charlas, empecemos por crear nuestra lista.
import java.util.ArrayList;
import java.util.List;
public class CreateArrayList {
public static void main(String[]
ArrayList<Integer>
args) {
list0 = new ArrayList<>();
// Makes use of polymorphism
List
list = new ArrayList<Integer>();
// Local variable with "var" keyword, Java 10
var
list2 = new ArrayList<Integer>();
}
}
En los corchetes angulares (<>) especificamos el tipo de objetos que vamos a
almacenar.
Tenga en cuenta que el tipo entre paréntesis debe ser un tipo de objeto y no un
tipo primitivo. Por lo tanto, tenemos que usar envoltorios de objetos, clase Integer en
lugar de int, Double en lugar de double, y así sucesivamente.
Hay muchas formas de crear una ArrayList, pero presenté tres formas comunes en el
fragmento anterior.
La primera forma es creando el objeto a partir de la clase ArrayList concreta,
especificando ArrayList en el lado izquierdo de la asignación.
El segundo fragmento de código hace uso del polimorfismo mediante el uso de la lista
en el lado izquierdo. Esto hace que la asignación se acople libremente con la clase
ArrayList y nos permite asignar otros tipos de listas y cambiar fácilmente a una
implementación de Lista diferente.
La tercera forma es la forma Java 10 de crear variables locales haciendo uso de la
palabra clave var. El compilador interpreta el tipo de variable comprobando el lado
derecho.
Podemos ver que todas las asignaciones dan como resultado el mismo tipo:
System.out.println(list0.getClass());
System.out.println(list.getClass());
System.out.println(list2.getClass());
Output:
class java.util.ArrayList
class java.util.ArrayList
class java.util.ArrayList
También podemos especificar la capacidad inicial de la lista.
List
list = new ArrayList<>(20);
Esto es útil porque cada vez que la lista se llena e intenta agregar otro elemento, la
lista actual se copia en una nueva lista con el doble de capacidad que la lista anterior.
Todo esto sucede detrás de escena.
Esta operación hace que nuestra complejidad sea O(n), por lo que queremos evitarla.
La capacidad por defecto es 10, por lo que si sabes que vas a almacenar más
elementos, debes especificar la capacidad inicial.
Cómo agregar y actualizar elementos de lista en
Java
Para agregar elementos a la lista podemos usar el método add. También podemos
especificar el índice del nuevo elemento, pero ten cuidado al hacerlo, ya que puedes
generar una excepción IndexOutOfBoundsException.
import java.util.ArrayList;
public class AddElement {
public static void main(String[]
ArrayList<String>
args) {
list = new ArrayList<>();
list.add("hello");
list.add(1, "world");
System.out.println(list);
}
}
Resultado:
[hello, world]
Podemos usar el método set para actualizar un elemento.
list.set(1, "from the otherside");
System.out.println(list);
Resultado:
[hello, world]
[hello, from the otherside]
Cómo recuperar y eliminar elementos de lista en
Java
Para recuperar un elemento de la lista, puedes usar el método get y proporcionar el
índice del elemento que desea obtener.
import java.util.ArrayList;
import java.util.List;
public class GetElement {
public static void main(String[]
List
args) {
list = new ArrayList<String>();
list.add("hello");
list.add("freeCodeCamp");
System.out.println(list.get(1));
}
}
Resultado:
freeCodeCamp
La complejidad de esta operación en ArrayList es O(1) ya que utiliza un arrelgo de
acceso aleatorio regular en segundo plano.
Para eliminar un elemento de ArrayList, se utiliza el método remove.
list.remove(0);
Esto elimina el elemento en el índice 0, que es "hola" en este ejemplo.
También podemos llamar al método remove con un elemento para buscarlo y
eliminarlo. Ten en cuenta que solo elimina la primera aparición del elemento si está
presente.
public static void main(String[]
List
args) {
list = new ArrayList();
list.add("hello");
list.add("freeCodeCamp");
list.add("freeCodeCamp");
list.remove("freeCodeCamp");
System.out.println(list);
}
Resultado:
[hello,
freeCodeCamp]
Para eliminar todas las ocurrencias, podemos usar el método removeAll de la misma
manera.
Estos métodos están dentro de la interfaz de List, por lo que todas las
implementaciones de List los tienen (ya sea ArrayList, LinkedList o Vector).
Cómo obtener la longitud de una lista en Java
Para obtener la longitud de una lista, o el número de elementos, podemos usar el
método size().
import java.util.ArrayList;
import java.util.List;
public class GetSize {
public static void main(String[]
List
args) {
list = new ArrayList();
list.add("Welcome");
list.add("to my post");
System.out.println(list.size());
}
}
Resultado:
2
Listas bidimensionales en Java
Es posible crear listas bidimensionales, similares a los arreglos 2D.
ArrayList<ArrayList<Integer>>
listOfLists = new ArrayList<>();
Usamos esta sintaxis para crear una lista de listas, y cada lista interna almacena
números enteros. Pero aún no hemos inicializado las listas internas. Necesitamos
crearlos y ponerlas en esta lista nosotros mismos:
int
numberOfLists = 3;
for (int
i = 0; i < numberOfLists; i++) {
listOfLists.add(new ArrayList<>());
}
Estoy inicializando mis listas internas y estoy agregando 3 listas en este caso. También
puedo agregar listas más adelante si es necesario.
Ahora podemos agregar elementos a nuestras listas internas. Para agregar un
elemento, primero debemos obtener la referencia a la lista interna.
Por ejemplo, digamos que queremos agregar un elemento a la primera lista.
Necesitamos obtener la primera lista y luego agregarla.
listOfLists.get(0).add(1);
Adding elements to 2D list
Aquí hay un ejemplo para ti. Intenta adivinar el resultado del siguiente segmento de
código:
public static void main(String[]
args) {
ArrayList<ArrayList<Integer>>
listOfLists = new ArrayList<>();
System.out.println(listOfLists);
int
numberOfLists = 3;
for (int
i = 0; i < numberOfLists; i++) {
listOfLists.add(new ArrayList<>());
}
System.out.println(listOfLists);
listOfLists.get(0).add(1);
listOfLists.get(1).add(2);
listOfLists.get(2).add(0,3);
System.out.println(listOfLists);
}
Resultado:
[]
[[], [], []]
[[1], [2], [3]]
Ten en cuenta que es posible imprimir las listas directamente (a diferencia de los
arreglos regulares) porque anulan el método ttoString().
Métodos útiles en Java
Existen otros métodos y atajos útiles que se utilizan con frecuencia. En esta sección
quiero familiarizarte con algunos de ellos para que te resulte más fácil trabajar con
listas.
Cómo crear una lista con elementos en Java
Es posible crear y completar la lista con algunos elementos en una sola línea. Hay dos
maneras de hacer esto.
La siguiente es la forma de la vieja escuela:
public static void main(String[]
List<String>
args) {
list = Arrays.asList(
"freeCodeCamp",
"let's",
"create");
}
Debes tener cuidado con una cosa al usar este método: Arrays.asList devuelve una
lista inmutable. Entonces, si intentas agregar o eliminar elementos después de crear el
objeto, obtendrás una excepción UnsupportedOperationException.
Es posible que tengas la tentación de usar la palabra clave final para que la lista sea
inmutable, pero no funcionará como se esperaba.
Simplemente, se asegura de que la referencia al objeto no cambie, no le importa lo que
sucede dentro del objeto. Por lo que permite poner y quitar.
final List<String>
list2 = new ArrayList<>();
list2.add("erinc.io is the best blog ever!");
System.out.println(list2);
Resultado:
[erinc.io is the best blog ever!]
Ahora veamos la forma moderna de hacerlo:
ArrayList<String>
friends =
new ArrayList<>(List.of("Gulbike", "Sinem", "Mete"));
El método List.of se envió con Java 9. Este método también devuelve una lista
inmutable, pero podemos pasarla al constructor ArrayList para crear una lista mutable
con esos elementos. Podemos agregar y quitar elementos a esta lista sin ningún
problema.
Cómo crear una lista con N copias de algún elemento en Java
Java proporciona un método llamado NCopies que es especialmente útil para la
evaluación comparativa. Puedes llenar un arreglo con cualquier número de elementos
en una sola línea.
public class NCopies {
public static void main(String[]
List<String>
args) {
list = Collections.nCopies(10, "HELLO");
System.out.println(list);
}
}
Resultado:
[HELLO, HELLO, HELLO, HELLO, HELLO, HELLO, HELLO, HELLO, HELLO, HELLO]
Cómo clonar una lista en Java
Como se mencionó anteriormente, las Listas son tipos de referencia, por lo que se les
aplican las reglas de paso por referencia.
public static void main(String[]
List
args) {
list1 = new ArrayList<String>();
list1.add("Hello");
List
list2 = list1;
list2.add(" World");
System.out.println(list1);
System.out.println(list2);
}
Resultado:
[Hello,
World]
[Hello,
World]
La variable list1 contiene una referencia a la lista. Cuando lo asignamos a list2 también
apunta al mismo objeto. Si no queremos que cambie la lista original, podemos clonar la
lista.
ArrayList
list3 = (ArrayList) list1.clone();
list3.add(" Of Java");
System.out.println(list1);
System.out.println(list3);
Resultado:
[Hello,
World]
[Hello,
World,
Of Java]
Dado que clonamos list1, list3 contiene una referencia a su clon en este caso. Por lo
tanto, list1 permanece sin cambios.
Cómo copiar una lista a un arreglo en Java
A veces necesita convertir su lista en un arreglo para pasarla a un método que acepte
un arreglo. Puedes usar el siguiente código para lograrlo:
List<Integer>
Integer[]
list = new ArrayList<>(List.of(1, 2));
toArray = list.toArray(new Integer[0]);
Debe pasar un arreglo y el método toArray devuelve ese arreglo después de llenarla
con los elementos de la lista.
Cómo ordenar una lista en Java
Para ordenar una lista podemos usar Collections.sort. Ordena en orden ascendente de
forma predeterminada, pero también puedes pasar un comparador para ordenar con
lógica personalizada.
List<Integer>
toBeSorted = new ArrayList<>(List.of(3,2,4,1,-2));
Collections.sort(toBeSorted);
System.out.println(toBeSorted);
Resultado:
[-2, 1, 2, 3, 4]
Cómo elejir qué tipo de lista usar?
Antes de terminar este artículo, quiero brindarte una breve comparación de rendimiento
de diferentes implementaciones de listas para que puedas elegir cuál es mejor para tu
caso de uso.
Vamos a comparar ArrayList, LinkedList y Vector. Todos ellos tienen sus altibajos, así
que asegúrate de considerar el contexto específico antes de decidir.
Java ArrayList vs LinkedList
Aquí hay una comparación de tiempos de ejecución en términos de complejidad
algorítmica.
|
| ArrayList
| LinkedList |
|-----------------------|----------------------------|------------|
| GET(index)
| O(1)
| O(n)
|
| GET from Start or End | O(1)
| O(1)
|
| ADD
| O(1), if list is full O(n) | O(1)
|
| ADD(index)
| O(n)
| O(1)
|
| Remove(index)
| O(n)
| O(1)
|
| Search and Remove
| O(n)
| O(n)
|
Generally, the get operation is much faster on ArrayList but add and remove are faster
on LinkedList.
En general, la operación get (obtener) es mucho más rápida en ArrayList,
pero add (agregar) y remove (eliminar) son más rápidos en LinkedList.
ArrayList usa un arreglo detrás de escena, y cada vez que se elimina un elemento, los
elementos de el arreglo deben cambiarse (que es una operación O (n)).
Elegir estructuras de datos es una tarea compleja y no existe una receta que se
aplique a todas las situaciones. Aún así, intentaré proporcionar algunas pautas para
ayudarte a tomar esa decisión más fácilmente:
Si planeas hacer más operaciones de obtener y agregar que no sean eliminar, usa
ArrayList ya que la operación de obtener es demasiado costosa en LinkedList. Tenga
en cuenta que la inserción es O(1) solo si la llamas sin especificar el índice y la agreg
al final de la lista.
Si vas a eliminar elementos y/o insertarlos en el medio (no al final) con frecuencia,
puedes considerar cambiar a LinkedList porque estas operaciones son costosas en
ArrayList.
Ten en cuenta que si accedes a los elementos secuencialmente (con un iterador), no
experimentarás una pérdida de rendimiento con LinkedList mientras obtienes
elementos.
Benchmark source: programcreek
Java ArrayList vs Vector
Vector es muy similar a ArrayList. Si provienes de un entorno de C++, es posible que
tengas la tentación de usar un Vector, pero su caso de uso es un poco diferente al de
C++.
Los métodos de Vector tienen la palabra clave sincronizada, por lo que Vector
garantiza la seguridad de subprocesos, mientras que ArrayList no.
Es posible que prefieras Vector sobre ArrayList en la programación de subprocesos
múltiples o puedes usar ArrayList y manejar la sincronización usted mismo.
En un programa de subproceso único, es mejor quedarse con ArrayList porque la
seguridad de subprocesos tiene un costo de rendimiento.
Download