02.5 - Arrays, colecciones y maps
Hasta ahora hemos trabajado con variables simples. En Java existen estructuras de datos que permiten agrupar múltiples valores: arrays, colecciones y maps.
1. Arrays
Los array permiten almacenar un conjunto finito de elementos del mismo tipo con un tamaño fijo asignado desde su creación.
- Declaración:
tipo[] nombre;
- Creación (instanciación):
nombre = new tipo[tamaño];
Las posiciones se numeran desde la 0 hasta tamaño - 1. Para acceder o modificar un valor usamos los corchetes [].
int[] numbers;
numbers = new int[10];
//int[] numbers = new int[10];
Para almacenar valores en cada una de las posiciones del array, usamos corchetes ([]) indicando en su interior la posición en la que queremos leer o escribir.
numbers[3] = 10;
Para acceder a los datos de un array accedemos mediante nombre[posicion].
int number;
number = numbers[3];
Propiedad length y recorridos
La propiedad length nos devuelve el número total de elementos. Podemos recorrer el array mediante un bucle for convencional o con un bucle for-each:
// Recorrido con for tradicional
for (int i = 0; i < numbers.length; i++) {
IO.println("Índice " + i + ": " + numbers[i]);
}
// Recorrido con for-each (más limpio para lectura)
for (int number : numbers) {
IO.println(number);
}
Inicializar array:
int[] numbers = new int[5];
for(int i=0; i<numbers.length; i++) {
numbers[i] = Integer.parseInt(IO.readln("Introduce un número entero: "));
}
Otra forma de inicializar un array es definiendo sus valores como una lista separada por comas encerrada entre llaves. Ésto lo debemos hacer a la hora de la declaración del array, y no hace falta indicarle la longitud, ya que se lo indicamos con el número de elementos que le pasemos:
int[] numbers = {1, 3, 312, 15, 69, 7, 8, 9, 0, 1};
Arrays multidimensionales
Podemos declarar un array de más de una dimensión (como tablas o matrices):
// Inicialización directa
int[][] table = {
{3, 5, 6},
{2, 4, 9}
};
// Recorrido con bucles anidados
for (int[] row : table) {
for (int cell : row) {
IO.print(cell + " ");
}
IO.println("");
}
Paso de arrays a funciones
A diferencia de los tipos primitivos, los arrays son objetos. Al pasarlos como parámetro a un método, se copia la referencia a la memoria original. Por tanto, cualquier cambio dentro del método modificará el array original.
static void main() {
int[] numbers = {1, 2, 3};
updateFirst(numbers);
IO.println(numbers[0]); // Muestra 99
}
static void updateFirst(int[] data) {
data[0] = 99; // Modifica el array original
}
2. Colecciones
Las colecciones son estructuras de datos avanzadas que pueden cambiar de tamaño dinámicamente. Parten de la interfaz base java.util.Collection.
Principales métodos comunes:
int size(): Devuelve el número de elementos.
boolean isEmpty(): Indica si está vacía.
boolean contains (Object element): retorna verdadero si la colección tiene el elemento pasado como parámetro.
boolena add(Object element): Añade un elemento.
boolean remove(Object elementt): Elimina un elemento.
void clear(): Vacía la colección.
Conjuntos (Set)
Un Set es una colección que NO permite elementos duplicados.
Implementaciones más comunes:
HashSet: Muy rápido. No garantiza ningún orden de los elementos.
LinkedHashSet: Rápido. Mantiene el orden en el que se insertaron los elementos.
TreeSet: Ordena los elementos automáticamente según su valor.
Set<Integer> numbers = new HashSet<Integer>(); //Una práctica habitual es definir el tipo de datos conjunto como la interfaz genérica (Set) numbers.add(10); numbers.add(5); numbers.add(10); // Devuelve false y NO se añade porque está duplicado
Otra forma más cómoda de inicializar un conjunto (válido a partir de Java 9) es utilizar el método of():
Set<Integer> numbers = Set.of(2, 10, 3, 23, 99);
of(), el conjunto que se crea es inmutable, es decir, no podemos cambiarlo, con lo que no podremos añadir, eliminar ni modificar elementos.
Para recorrerlo, podemos usar for-each:
for (Integer number : numbers) {
IO.println(number);
}
Listas (List)
Un List es una colección ordenada que SÍ permite elementos duplicados y cuenta con acceso posicional mediante índice.
Implementaciones principales:
ArrayList: Basada enarraysredimensionables. Muy rápida para acceder a posiciones concretas (get).
LinkedList: Lista doblemente enlazada. Muy eficiente al insertar o eliminar elementos frecuentemente.
Métodos clave de List:
E get(int index): Obtiene un elemento partiendo de su posición (index).
E set(int index, E element): Cambia el elemento almacenado en una posición de la lista (index), por otro (element).
void add(int index, E element): Inserta un elemento (element) en la lista en una posición concreta (index), desplazando los existentes. Si le pasamos solo el elemento (element) la inserción la hará al final de la lista.
E remove(int index): Elimina un elemento indicando su posición (index) en la lista.
boolean addAll(int index, Collection<? extends E> c): Inserta una colección pasada por parámetro en una posición de la lista, desplazando el resto de elementos.
int indexOf(Object o): Devuelve la posición de un elemento en la lista o $-1$ si el elemento no está en la lista.
int lastIndexOf(Object o): Devuelve la última ocurrencia del objeto en la lista (dado que la lista si puede almacenar duplicados) o $-1$ si el elemento no está en la lista.
List<E> subList(int from, int to): Genera una sublista (una vista parcial de la lista) con los elementos comprendidos entre la posición inicial (from, incluida) y la posición final (to, no incluida).
Los elementos de una lista empiezan a numerarse por 0. Es decir, que el primer elemento de la lista es el 0.
Las listas se utilizan de forma muy parecida a los conjuntos:
List<Integer> numbers = new ArrayList<>();
numbers.add(1); // Añade un elemento al final de la lista.
numbers.add(3); // Añade otro elemento al final de la lista.
numbers.add(1,2); // Añade en la posición 1 el elemento 2.
numbers.add(numbers.get(1)+numbers.get(2)); // Suma los valores contenidos en la posición 1 y 2, y lo agrega al final.
numbers.remove(0); // Elimina el primer elementos de la lista.
for (Integer number: numbers)
IO.println("Elemento:" + number); // Muestra la lista.
}
Igual que con los conjuntos, podemos usar el método of() para crear listas inmutables:
List<Integer> numbers = List.of(1, 3, 5, 67);
3. Maps
Un Map almacena parejas de clave-valor (Key → Value). Las claves son únicas y sirven para acceder directamente al valor asociado.
Implementaciones principales:
HashMap: Sin orden específico en las claves.
TreeMap: Ordena las claves por valor.
LinkedHashMap: Mantiene el orden de inserción de las claves.
Métodos clave de Map:
V put(K key, V value): Asocia el valor (value) con la clave (key) en elmap. Si la clave no existe en elmapcrea un nuevo par clave-valor. Si ya existe, reemplazará el valor.
V get(Object key): Obtiene el valor asociado a una clave (key) ya almacenada en el mapa. Si no existe la clave, retornaránull.
V remove(Object key): Elimina la clave (key) y el valor (value) asociado. Retorna el valor asociado a la clave, por si lo queremos utilizar para algo, onull, si la clave no existe.
boolean containsKey(Object key): Devuelvetruesi elmaptiene almacenada la clave (key). En caso contrario devolveráfalse.
boolean containsValue(Object value): Devuelvetruesi elmaptiene almacenada el valor (value). En caso contrario devolveráfalse.
int size(): Devuelve el número de pares clave-valor almacenado en elmap.
boolean isEmpty(): Devuelvetruesi elmapestá vacío,falseen cualquier otro caso.
void clear(): Vacía elmap.
Set<K> keySet(): Devuelve el conjunto de claves contenidas en elmap.
Map<String, Integer> ages = new HashMap<String, Integer>();
ages.put("Ana", 20);
ages.put("Pedro", 25);
ages.put("María", 21);
ages.put("Ana", 21); // Actualiza la edad de Ana a 21
for (String name : ages.keySet()) {
IO.println(name + ": " + ages.get(name));
}
Igual que con los conjuntos y las listas, también podemos crear maps inmutables con el método Map.of()
Map<String, Integer> ages = Map.of("Ana", 20, "Pedro", 25, "María", 21);
Ejercicios
Ejercicio 22.a
Crea un array de enteros con los siguientes números:
{1, 2, 3, 5, 8, 13, 21, 34, 55}
Haz que se muestre por pantalla el cuadrado de cada número del array utilizando un bucle for.
Ejercicio 22.b
Utiliza un bucle for-each para mostrar el cuadrado de los números del ejercicio anterior.
Ejercicio 22.c
Haz que el array del ejercicio 1.a se modifique con el cuadrado de cada número y muéstralo por pantalla.
Ejercicio 23.a
Crea un array de cinco enteros. Haz que la aplicación pida al usuario cada elemento del array y, al acabar, muéstralo por pantalla.
Ejercicio 23.b
Modifica el ejercicio anterior para que la aplicación para que el usuario pueda elegir el tamaño del array.
Ejercicio 23.c
Haz que la inicialización del array y mostrar los elementos del ejercicio anterior sean dos funciones separadas.
Ejercicio 24.a
Crea una matriz de 5×8 de boolean con los siguientes valores:
{true, true, true, true, true},
{true, false, false, false, true},
{true, false, false, false, true},
{true, false, false, false, true},
{true, false, false, false, true},
{true, false, false, false, true},
{true, false, false, false, true},
{true, true, true, true, true}
Haz que se muestre por pantalla la matriz según la siguiente regla:
- Si el valor es
true, se mostrará un $0$ - Si el valor es
falsese mostrará un espacio en blanco.
Ejemplo de salida:
OOOOO O O O O O O O O O O O O OOOOO
Ejercicio 24.b
Crea otra matriz a partir del ejercicio anterior con los siguientes valores:
{false, false, false, false, true},
{false, false, false, true, true},
{false, false, true, false, true},
{false, true, false, false, true},
{true, false, false, false, true},
{false, false, false, false, true},
{false, false, false, false, true},
{false, false, false, false, true}
Muestra las dos matrices por pantalla según las reglas anteriores.
Ejercicio 24.c
Haz una aplicación que pida un número binario al usuario. El programa mostrará los bits (empezando por el de la derecha) utilizando las matrices anteriores. La aplicación mostrará la frase “No se puede representar el bit” si éste no es un $1$ o un $0$.
Ejercicio 24.d
Modifica la aplicación anterior para que el usuario introduzca por pantalla un número decimal y la aplicación muestre el número en binario (utilizando los métodos anteriores).
Ejercicio 25.a
Crea un conjunto de números enteros. Pide por pantalla el tamaño del conjunto, y haz que el usuario vaya metiendo números al conjunto hasta alcanzar el tamaño introducido. Muestra el conjunto final por pantalla.
Ejercicio 25.b
Modifica la aplicación anterior para que el tamaño del conjunto sea variable. El usuario introducirá números en el conjunto hasta que escriba un $0$. El $0$ no debe formar parte del conjunto final.
Ejercicio 25.c
Haz que la aplicación muestre la frase “El número está repetido y no se añadirá al conjunto” si el usuario introduce un número que ya existe en el conjunto.
Ejercicio 25.d
Separa los números en dos conjuntos: pares e impares. Muestra los dos conjuntos resultantes por pantalla.
Ejercicio 26.a
Haz un programa que contenga una lista de alumnos con los siguientes valores:
("Ana", "Pedro", "Antonio", "Amparo", "Luis", "María")
Por cada alumno, el programa pedirá la nota y mostrará la frase “El alumno nombre_alumno está aprobado con nota_alumno” si la nota es mayor o igual a $5$.
Ejercicio 26.b
Modifica el programa anterior para que los alumnos aprobados se añadan a otra lista. Muestra la lista de aprobados cuando se hayan introducido todas las notas (no hace falta mostrar la frase anterior por cada alumno aprobado).
Ejercicio 26.c
Modifica el ejercicio anterior para que la aplicación muestre un menú con las opciones “Introducir alumno” y “Salir”. Cuando se introduce un alumno, el programa pedirá el nombre del alumno y su nota. Si la nota es mayor o igual a $5$, se añadirá a una lista de alumnos aprobados. En caso contrario, se añadirá a la lista de suspendidos. Cuando el usuario elija la opción “Salir”, el programa mostrará ambas listas (aprobados y suspendidos).
Ejercicio 27
Crea un Map con los nombres de los alumnos y sus notas. El programa deberá pedir la nota de un listados predefinido de alumnos (puedes utilizar los anteriores) y a continuación mostrará el Map por pantalla.