- Aprender
- Informática
- Programación
- Programación orientada a objetos con Java
- HashMap y colecciones en Java
HashMap y colecciones en Java
HashMap, contar y agrupar valores y conservar valores únicos con HashSet. Descubre qué garantizan las interfaces List, Set y Map, ordena listas, dota a tus propias clases de un orden natural con Comparable y elige la colección que se ajuste a cada tarea.PrincipianteUnidad 7 de 11 del curso Curso de Programación orientada a objetos con Java
Lo que aprenderás
- Crea mapas hash, añade, lee, actualiza y elimina pares clave-valor, recorre el contenido de un mapa y utiliza tus propias clases como claves que el mapa pueda volver a encontrar.
- Crea un HashMap e inserta, consulta, actualiza y elimina entradasDeclara un HashMap con sus tipos de clave y valor, almacena pares con put, léelos con get y gestiona las claves ausentes.
- Recorre claves, valores y entradasRecorre todos los pares de un mapa con keySet, values y entrySet, identifica qué orden puedes esperar y modifica un mapa de forma segura mientras lo recorres.
- Utiliza tus propios objetos como claves de mapasHaz que los objetos de tus propias clases funcionen como claves sobrescribiendo equals y hashCode conjuntamente, y mantén las claves sin cambios mientras estén en un mapa.
- Crea un HashMap e inserta, consulta, actualiza y elimina entradas
- Utiliza mapas para contar cuántas veces aparecen elementos, reunir valores relacionados bajo una misma clave y crear tablas de consulta que encuentren objetos rápidamente.
- Cuenta apariciones y acumula totales por claveConstruye tablas de frecuencias y sumas acumuladas con el patrón getOrDefault e interpreta correctamente los resultados.
- Agrupa valores bajo una misma clave utilizando listas y conjuntos como valoresConstruye mapas cuyos valores sean listas o conjuntos, añade elementos al grupo correcto y evita los errores que hacen perder o dañan grupos.
- Busca objetos y precios rápidamente con un índice basado en un mapaUtiliza mapas como tablas de consulta e índices que encuentran objetos mediante una clave única, mantenlos dentro de una clase y conserva la coherencia entre varios índices.
- Cuenta apariciones y acumula totales por clave
- Utiliza HashSet para almacenar valores sin duplicados, comprobar rápidamente la pertenencia y combinar conjuntos mediante unión, intersección y diferencia.
- Almacena valores únicos y comprueba la pertenencia con HashSetAñade, comprueba y elimina valores en un HashSet, utiliza el resultado de add y elimina duplicados de una lista.
- Combina conjuntos y mantén su ordenCalcula uniones, intersecciones y diferencias sin alterar los conjuntos originales, compara conjuntos y elige un conjunto ordenado cuando el orden importe.
- Almacena valores únicos y comprueba la pertenencia con HashSet
- Declara colecciones mediante sus tipos de interfaz, identifica qué garantiza cada interfaz y utiliza los métodos compartidos que funcionan en distintas implementaciones.
- Declara variables y parámetros con tipos de interfazExplica qué es un tipo de interfaz, declara colecciones como List, Set o Map y escribe métodos que acepten cualquier implementación.
- Identifica qué garantizan List, Set y MapCompara las garantías de las tres interfaces, reconoce sus principales implementaciones y trabaja con colecciones no modificables creadas con of.
- Declara variables y parámetros con tipos de interfaz
- Ordena listas según su orden natural, dota a tus propias clases de un orden natural implementando Comparable y utiliza ese orden en conjuntos y mapas ordenados.
- Ordena listas de números y cadenasOrdena una lista in situ con Collections.sort, predice el orden de las cadenas y ordena en sentido inverso o sin distinguir mayúsculas y minúsculas.
- Implementa Comparable en tu propia claseDota a una clase de un orden natural implementando Comparable y escribiendo compareTo con comparaciones seguras de números y cadenas.
- Resuelve empates y utiliza conjuntos y mapas ordenadosOrdena objetos por varios campos, mantén compareTo consistente con equals y utiliza TreeSet y TreeMap para mantener los datos ordenados.
- Ordena listas de números y cadenas
- Compara la rapidez de las operaciones habituales en cada colección y elige el tipo que se ajuste a lo que el programa debe hacer con sus datos.
- Compara el coste de las operaciones habituales con coleccionesEstima cómo crece el tiempo de las búsquedas, inserciones y eliminaciones con el tamaño de cada colección, e identifica patrones lentos.
- Selecciona una colección que se ajuste a la tareaResponde a unas preguntas sobre orden, duplicados y búsqueda para elegir entre arreglos, listas, conjuntos y mapas, y combínalos para datos más complejos.
- Compara el coste de las operaciones habituales con colecciones
Guía de estudio de HashMap y colecciones en Java
1Almacena y busca datos por clave con HashMap
Un código de producto puede llevar directamente a una cantidad en existencias, sin buscar en una lista. Los mapas hacen explícita esa relación, pero utilizarlos bien también implica gestionar claves ausentes, visitar pares de forma segura y definir cuándo dos objetos clave se consideran iguales. Empieza con un pequeño mapa de existencias y sigue cómo cambia su contenido y cómo Java vuelve a encontrar una clave almacenada. Las mismas reglas de igualdad importarán cuando utilices conjuntos.
1.1 Crea un HashMap e inserta, consulta, actualiza y elimina entradas
Un mapa almacena una relación entre cada clave y un valor. En un mapa de existencias, el nombre de un producto es la clave y su cantidad es el valor. Dos productos pueden tener la misma cantidad, pero una clave de producto no puede tener dos entradas separadas.
Crea el mapa
import java.util.HashMap;
HashMap<String, Integer> stock = new HashMap<>();
El primer tipo, String, describe las claves. El segundo, Integer, describe los valores. El diamante <> de la derecha permite que Java infiera esos tipos. Los argumentos de tipo deben ser tipos de referencia: utiliza Integer, Double, Character o Boolean en lugar de int, double, char o boolean. Java empaqueta un int normal cuando lo almacena como Integer y desempaqueta un Integer cuando se necesita un int.
Sigue cada cambio
stock.put("apple", 12);
stock.put("pear", 7);
Integer previous = stock.put("apple", 15);
La primera llamada crea apple=12; la segunda añade pear=7. La tercera encuentra la clave existente "apple" y reemplaza su valor. El mapa tiene ahora dos entradas y previous contiene 12. Un put para una clave sin asociación previa devuelve null.
stock.get("apple") devuelve ahora 15. stock.remove("pear") devuelve 7 y elimina esa entrada. Volver a eliminar "pear" devuelve null. size() cuenta las entradas, isEmpty() comprueba si no hay ninguna y clear() elimina todas las entradas.
Gestiona una clave ausente
stock.get("kiwi") devuelve null y stock.containsKey("kiwi") devuelve false. Esta sentencia se compila, pero falla al ejecutarse:
int quantity = stock.get("kiwi");
Java intenta desempaquetar null como un int, lo que provoca una NullPointerException. Para un mapa de cantidades no nulas, utiliza un valor predeterminado:
int quantity = stock.getOrDefault("kiwi", 0);
Esto proporciona 0 sin añadir "kiwi" al mapa. También puedes comprobar containsKey antes de leer. containsValue(15) pregunta si alguna entrada tiene ese valor; puede recorrer todos los valores, por lo que es diferente de buscar una clave conocida.
Un HashMap también permite una clave null y valores null. Si una clave está asociada explícitamente a null, getOrDefault devuelve ese null almacenado, no el valor predeterminado. containsKey distingue ese caso de una clave ausente. Los mapas de cantidades son más sencillos cuando todas las cantidades almacenadas son números reales.
Compara correctamente claves y valores
Las claves de tipo String distinguen mayúsculas y minúsculas: "apple", "Apple" y "apple " son diferentes. Aplica la misma limpieza antes de almacenar y buscar, por ejemplo, name.trim().toLowerCase(). Limpiar solo una clave de búsqueda no puede corregir claves almacenadas de forma inconsistente.
Compara los valores empaquetados por contenido con equals. Si dos entradas contienen cada una 1000, sus referencias Integer pueden ser distintas, por lo que == puede ser falso aunque sus contenidos numéricos coincidan. Después de comprobar que ambos valores son distintos de null, a.equals(b) compara sus contenidos.
Puntos clave
- Cada clave única se asocia a un valor; los valores pueden repetirse.
putreemplaza un valor existente y devuelve el valor anterior.getdevuelvenullpara una clave ausente; desempaquetarlo provoca unaNullPointerException.getOrDefaultproporciona un valor predeterminado solo para una clave ausente.- Compara las claves de cadena de forma consistente y los valores empaquetados por contenido.
1.2 Recorre claves, valores y entradas
Un mapa puede responder a una búsqueda individual o proporcionar todos sus datos a un bucle. Elige la vista que proporcione las partes que necesita el bucle. Las vistas están vinculadas al mapa, por lo que los cambios realizados a través de ellas también pueden cambiar el mapa.
Elige claves, valores o entradas
Utiliza keySet() para visitar las claves. Una búsqueda dentro de ese bucle puede recuperar cada valor:
for (String name : phoneBook.keySet()) {
System.out.println(name + ": " + phoneBook.get(name));
}
Utiliza values() cuando las claves no importen. Para las cantidades en existencias apple 15, pear 7 y fig 3:
int total = 0;
for (int quantity : stock.values()) {
total += quantity;
}
El total pasa a ser 25. Los valores repetidos siguen siendo contribuciones separadas: una vista de valores no es un conjunto.
Una entrada contiene una clave y su valor juntos. Importa java.util.Map y utiliza Map.Entry<K, V> con getKey() y getValue(). Esto evita una segunda búsqueda:
String best = null;
int bestScore = Integer.MIN_VALUE;
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
if (best == null || entry.getValue() > bestScore) {
best = entry.getKey();
bestScore = entry.getValue();
}
}
Para Ana 82, Ben 91 y Cai 77, el resultado es Ben con 91. La comprobación best == null también gestiona una primera puntuación igual al menor int posible. Un mapa vacío deja best como null.
Elige el orden de forma explícita
Un HashMap no garantiza ningún orden de iteración. No se puede dar por supuesto el orden de inserción, el orden ordenado ni el orden impreso hoy. Un LinkedHashMap conserva el orden de inserción; un TreeMap visita las claves ordenadas. Si dos puntuaciones empatan, el bucle anterior conserva la primera que visita. Con un HashMap, cualquiera de los nombres empatados podría ganar. Añade una regla de desempate explícita cuando el resultado deba ser predecible.
Elimina entradas mediante el iterador
Llamar a stock.remove(key) dentro de un bucle for-each sobre stock.keySet() cambia las claves que recorre el bucle. Puede provocar una ConcurrentModificationException. La detección no está garantizada; una ejecución sin excepción no hace válido ese patrón.
Utiliza el método de eliminación del propio iterador:
Iterator<Map.Entry<String, Integer>> it =
stock.entrySet().iterator();
while (it.hasNext()) {
if (it.next().getValue() == 0) {
it.remove();
}
}
Importa java.util.Iterator. Para apple 15, pear 0, fig 0 y kiwi 4, esto elimina pear y fig. Otro método seguro registra las claves en una lista, termina el bucle y después elimina esas claves.
Reemplazar un valor existente no añade ni elimina una clave. Durante un bucle sobre entradas, entry.setValue(entry.getValue() * 2) puede duplicar las cantidades de forma segura. No añadas claves nuevas a través del mapa durante ese bucle.
Distingue una vista de una copia
stock.keySet().remove("apple") elimina la entrada correspondiente del mapa. Una lista independiente creada con new ArrayList<>(stock.keySet()) es una copia de las claves actuales. Ordenar esa lista no cambia el orden del mapa, y eliminar un nombre de la lista no elimina su asociación.
Puntos clave
- Utiliza
keySet,valuesoentrySetsegún lo que necesite el bucle. HashMapno garantiza un orden de iteración; resuelve los empates de forma explícita.- Utiliza
removede un iterador para eliminar durante el recorrido. - Está permitido reemplazar un valor existente durante el recorrido.
- Las vistas están vinculadas al mapa; una lista de claves copiada es independiente.
1.3 Utiliza tus propios objetos como claves de mapas
Un identificador de producto almacenado como String ya tiene reglas de igualdad útiles. Una clave creada a partir de tu propia clase requiere una decisión: ¿representan dos objetos separados con los mismos datos la misma clave?
Los códigos hash acotan la búsqueda; la igualdad la confirma
Un HashMap utiliza hashCode() para ayudar a localizar una clave y equals() para comprobar una coincidencia. Las claves iguales deben tener códigos hash iguales. Las claves distintas pueden compartir un código hash; la igualdad sigue permitiendo distinguirlas. Las clases estándar de valores como String e Integer ya cumplen este contrato.
Sin sobrescrituras, una clase hereda de Object una igualdad basada en la identidad. Dos puntos creados por separado con coordenadas 2 y 3 son claves distintas aunque sus campos coincidan:
labels.put(new Point(2, 3), "door");
String label = labels.get(new Point(2, 3));
Con igualdad por identidad, label es null. La búsqueda creó un segundo objeto, distinto del utilizado para la inserción.
Sobrescribe el par conjuntamente
Aquí las coordenadas de un punto definen su contenido:
import java.util.Objects;
final class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Point)) {
return false;
}
Point point = (Point) other;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
La comprobación de identidad gestiona rápidamente el caso del mismo objeto. La comprobación de tipo rechaza null y los objetos de otros tipos. La comparación final comprueba ambas coordenadas. Objects.hash(x, y) construye el código hash a partir de esos mismos campos. Con esta clase, la búsqueda anterior devuelve "door".
Sobrescribir solo equals deja el cálculo del código hash heredado, que no garantiza códigos iguales para objetos separados con campos iguales. Un mapa puede entonces no encontrar una clave igual. Un código hash constante conservaría la corrección, pero haría lenta la búsqueda. Generar ambas sobrescrituras en un editor ayuda a evitar que se utilicen campos distintos.
Utiliza la firma exacta del método
public boolean equals(Point other) sobrecarga el método; no reemplaza equals(Object). La búsqueda en un mapa utiliza equals(Object), por lo que la nueva sobrecarga no proporciona al mapa igualdad por contenido. La anotación @Override convierte una firma incorrecta en un error del compilador en lugar de un error oculto de búsqueda.
Mantén estable la identidad de la clave
No cambies los campos que determinan la igualdad o el código hash de una clave mientras esté almacenada. Si un punto almacenado cambia de (2, 3) a (5, 3), puede que el mapa ya no lo encuentre con ninguno de los dos valores aunque size() no haya cambiado. Elimínalo antes de cambiarlo y luego vuelve a insertarlo. Declarar los campos de la clave como final, como arriba, evita este error.
Estas reglas también determinan la pertenencia a un HashSet. Un ArrayList utiliza equals para búsquedas por contenido como contains; no necesita códigos hash para esa búsqueda.
Puntos clave
- Los objetos iguales deben tener códigos hash iguales; los objetos distintos pueden compartir uno.
- Sobrescribe
equals(Object)yhashCode()utilizando los mismos campos. @Overridedetecta una sobrecarga deequalscreada por error.- Mantén sin cambios los campos de igualdad y código hash mientras una clave esté almacenada.
2Cuenta, agrupa e indexa datos con mapas
Un mapa puede construir información útil mientras un programa lee datos: un recuento por palabra, una lista por curso o un objeto por identificador. La elección importante es qué representa cada valor. Un número acumula un resultado; una lista o un conjunto reúne un grupo; una referencia a un objeto proporciona un índice. Sigue cada actualización desde un mapa vacío para que el comportamiento de las primeras apariciones, las claves repetidas y los objetos compartidos quede claro.
2.1 Cuenta apariciones y acumula totales por clave
Una tabla de frecuencias tiene una clave por cada elemento distinto y un número que indica cuántas veces aparece. La primera aparición inicia un recuento; cada aparición posterior actualiza esa misma entrada.
Construye un recuento elemento por elemento
HashMap<String, Integer> counts = new HashMap<>();
for (String word : text.split(" ")) {
int oldCount = counts.getOrDefault(word, 0);
counts.put(word, oldCount + 1);
}
Para el texto «el gato vio el perro y el gato corrió», la primera «el» no está en el mapa, por lo que su recuento anterior es 0 y el nuevo es 1. Sus dos apariciones siguientes cambian esa entrada a 2 y luego a 3. «gato» termina en 2; «vio», «perro», «y» y «corrió» terminan en 1 cada una. En el texto original, las claves correspondientes son "the", "cat", "saw", "dog", "and" y "ran".
Hay 6 palabras distintas, por lo que counts.size() es 6. Los valores suman 9, el número de apariciones de palabras. Estas medidas son diferentes: el tamaño del mapa no es la longitud de la secuencia original.
La actualización puede escribirse en una línea:
counts.put(word, counts.getOrDefault(word, 0) + 1);
Una forma equivalente más larga comprueba containsKey, incrementa un recuento existente y almacena 1 para una clave nueva. Todos los recuentos almacenados en este patrón son distintos de null.
Conserva el resultado anterior
Llamar a counts.put(word, 1) para cada palabra sobrescribe repetidamente cada recuento con 1. Registra que una palabra existe, pero pierde su frecuencia. Llamar a counts.get(word) + 1 sin gestionar la primera aparición intenta desempaquetar null y falla. El valor predeterminado pertenece al paso de lectura; después hay que volver a almacenar el recuento incrementado.
Decide qué se considera el mismo elemento
La igualdad de cadenas es exacta. "The" y "the" son claves distintas, al igual que "cat" y "cat,". Si la tarea las trata como la misma palabra, limpia cada unidad de entrada antes de contarla. Convierte el texto a minúsculas y elimina la puntuación que el programa trate como separadores. Utiliza una regla consistente para que los resultados no dependan de qué forma escrita apareció primero.
La clave también puede ser un carácter. Con HashMap<Character, Integer>, un bucle sobre "banana".toCharArray() produce a=3, n=2 y b=1 mediante el mismo patrón de leer, incrementar y almacenar.
Acumula cantidades en lugar de apariciones
Para obtener totales por categoría, suma la cantidad actual en lugar de 1:
HashMap<String, Double> totals = new HashMap<>();
double oldTotal = totals.getOrDefault(category, 0.0);
totals.put(category, oldTotal + amount);
Comida 12,50, transporte 3,20 y comida 7,25 dan comida 19,75 y transporte 3,20. El valor predeterminado es 0.0, que coincide con el tipo de valor Double. El mapa sigue teniendo una entrada por categoría, independientemente de cuántas cantidades contribuyan a ella.
Interpreta la tabla completa
Recorre las entradas para encontrar el mayor recuento o total, recordando la mejor clave y su valor. Especifica una regla de desempate si es necesario. Para un informe alfabético, new TreeMap<>(counts) copia las asociaciones en orden de clave. Los valores de los recuentos permanecen sin cambios; ordenar las claves no ordena las categorías por sus totales.
Puntos clave
- Un mapa de frecuencias almacena un recuento por cada clave distinta.
- Lee el recuento anterior con cero como valor predeterminado, suma uno y almacena el resultado.
- El tamaño del mapa cuenta elementos distintos; la suma de los recuentos mide las apariciones.
- Normaliza el texto de forma consistente antes de contar.
- Utiliza el mismo patrón de actualización para sumar cantidades por clave.
- Elige el orden del informe de forma independiente de los valores acumulados.
2.2 Agrupa valores bajo una misma clave utilizando listas y conjuntos como valores
El valor de un mapa puede ser una colección. Cuando varios estudiantes pertenecen a un curso, el curso es una clave y la lista asociada contiene a todos sus estudiantes. La regla de claves únicas del mapa sigue vigente: la lista es el único valor de ese curso.
Crea un grupo antes de añadir elementos
HashMap<Character, ArrayList<String>> groups = new HashMap<>();
for (String fruit : fruits) {
char letter = fruit.charAt(0);
if (!groups.containsKey(letter)) {
groups.put(letter, new ArrayList<>());
}
groups.get(letter).add(fruit);
}
Para «apple», «banana», «avocado», «cherry» y «blueberry», la primera fruta crea la lista de a y añade «apple». «Banana» crea la lista de b. «Avocado» encuentra la lista existente de a y se añade al final. El resultado es a → [apple, avocado], b → [banana, blueberry] y c → [cherry]. Cada lista conserva su propio orden de inserción aunque el HashMap no ordene sus claves.
La comprobación puede abreviarse:
groups.putIfAbsent(letter, new ArrayList<>());
groups.get(letter).add(fruit);
putIfAbsent conserva una lista existente distinta de null. El get siguiente devuelve esa lista, lista para la adición.
Conserva la lista que ya has construido
Un groups.put(letter, new ArrayList<>()) incondicional dentro del bucle reemplaza la lista anterior en cada aparición. Solo queda la última fruta de cada letra después del siguiente add. El error contrario es omitir la creación por completo: groups.get(letter).add(fruit) lanza una NullPointerException para una clave nueva porque aún no existe ninguna lista.
Comprende la referencia
get devuelve la referencia a la lista almacenada. Añadir elementos a ella modifica esa misma lista, por lo que no hay que volver a insertarla. Esto también explica un error al compartir:
ArrayList<String> shared = new ArrayList<>();
courses.put("Art", shared);
courses.put("Music", shared);
courses.get("Art").add("Jin");
Ambas claves conducen ahora a [Jin]. Dos claves no crearon dos listas. Crea una lista nueva para cada grupo nuevo cuando los grupos deban ser independientes.
Elige listas o conjuntos dentro de los grupos
Una lista conserva las adiciones repetidas. Un conjunto evita duplicados dentro de ese grupo. Por tanto, un HashMap<String, HashSet<String>> puede recopilar las inscripciones en cursos de cada estudiante sin contar dos veces al mismo estudiante en un curso. La regla del conjunto se aplica dentro de cada valor; el mapa externo sigue teniendo una entrada por curso.
Para leer un grupo que podría faltar, comprueba containsKey o utiliza groups.getOrDefault(letter, new ArrayList<>()). Una clave ausente produce entonces una lista vacía para esa llamada. La lista predeterminada no se inserta automáticamente; añadir elementos a ella no crea un grupo almacenado.
Eliminar el último elemento de un grupo deja la clave asociada a una colección vacía. Si el programa debe dejar de listar grupos vacíos, comprueba isEmpty() y elimina también esa clave. Cuenta los grupos con el tamaño del mapa externo y los elementos con los tamaños de las colecciones internas.
Puntos clave
- Asegúrate de que exista un grupo y después añade a su lista o conjunto almacenado.
- Crea una colección nueva para cada grupo independiente.
getdevuelve la referencia almacenada, por lo que los cambios internos no necesitan otroput.- Los valores de tipo lista conservan repeticiones; los de tipo conjunto conservan miembros distintos del grupo.
- Un grupo vacío almacenado sigue teniendo una entrada en el mapa.
2.3 Busca objetos y precios rápidamente con un índice basado en un mapa
Un índice asocia una clave identificadora con un objeto. Una biblioteca puede encontrar un libro por ISBN sin recorrer todos los libros de una lista. Una tabla de consulta utiliza la misma estructura para relacionar un código con un valor sencillo, como el precio de un producto.
Elige una clave identificadora
Un HashMap<String, Book> puede asociar un ISBN con su libro. Cada búsqueda solo necesita la clave. El nombre de una persona suele ser una mala clave única: almacenar a otra persona llamada «Sam Lee» bajo esa misma cadena reemplaza a la persona anterior. Utiliza un identificador único o un mapa de agrupación si un nombre debe conducir a varias personas.
Mantén un índice dentro de la clase responsable de los datos:
class Library {
private HashMap<String, Book> byIsbn;
Library() {
byIsbn = new HashMap<>();
}
void addBook(Book book) {
byIsbn.put(book.getIsbn(), book);
}
Book findByIsbn(String isbn) {
return byIsbn.get(isbn);
}
}
Aquí Book proporciona un método getIsbn(). Quienes llaman utilizan addBook y findByIsbn; no necesitan saber qué implementación de mapa se almacena. El campo privado también proporciona a la clase un único lugar donde mantener sus reglas para añadir y reemplazar libros.
Comprueba si falta un resultado
Si findByIsbn devuelve null, no se encontró ningún libro. Comprueba el resultado antes de llamar a un método sobre él:
Book found = library.findByIsbn("978-0-00-000000-2");
if (found != null) {
found.setOnLoan(true);
}
Llamar a setOnLoan directamente sobre un resultado ausente lanzaría una NullPointerException. Un método como hasBook(isbn) es otra forma de permitir que quienes llaman comprueben si existe una clave.
Sigue los objetos compartidos entre índices
Un mapa almacena una referencia a un objeto, no una copia nueva de ese objeto. Si el mismo libro está en una lista de todos los libros, un mapa por ISBN y una agrupación por autor, setOnLoan(true) cambia el único libro al que hacen referencia los tres. Esto evita que tres objetos de libro separados dejen de coincidir.
Las propias estructuras de las colecciones siguen necesitando mantenimiento. Eliminar un libro del mapa por ISBN no elimina su referencia de la lista de un autor. Si una biblioteca mantiene ambos índices, sus métodos de adición y eliminación deben actualizar los dos. Centralizar esos cambios en métodos como addBook y removeBook ayuda a mantener la coherencia de las búsquedas.
Utiliza una tabla en un cálculo
Supón que una tabla de precios contiene café 2,50, té 2,00 y magdalena 3,25 u.m. Para dos cafés y una magdalena:
double cost = 2 * prices.get("coffee") + prices.get("muffin");
El subtotal del café es 5,00; sumar 3,25 da 8,25 u.m. Las claves identifican productos y los valores proporcionan los importes. Un producto ausente requiere una decisión explícita antes del cálculo: un valor predeterminado de cero lo trataría como gratuito sin avisar. Por tanto, la misma técnica de búsqueda puede necesitar una regla para claves ausentes diferente de la de una tabla de frecuencias.
Puntos clave
- Un índice encuentra objetos mediante una clave identificadora.
- Utiliza una clave única o agrupa explícitamente varios objetos coincidentes.
- Los índices comparten referencias a objetos, pero las adiciones y eliminaciones deben actualizar cada índice.
- Mantén privados los mapas de datos y ofrece métodos que mantengan sus reglas.
3Conserva valores únicos con conjuntos
A veces la pregunta es simplemente si un valor ha aparecido antes. Los conjuntos responden directamente a esa pregunta y también pueden comparar grupos de valores, como las personas que asisten a dos eventos. La ausencia de elementos duplicados cambia tanto el código que escribes como el significado del tamaño final. Trabaja primero con la pertenencia y después combina conjuntos y elige si sus valores deben aparecer en orden de inserción o en orden.
3.1 Almacena valores únicos y comprueba la pertenencia con HashSet
Un conjunto contiene cada valor como máximo una vez. Es adecuado para preguntas como «¿ha aparecido antes este valor?» o «¿cuántos valores diferentes aparecen?». Un HashSet permite comprobaciones de pertenencia rápidas en promedio sin garantizar un orden de presentación.
Añade y comprueba valores
import java.util.HashSet;
HashSet<String> visited = new HashSet<>();
boolean first = visited.add("Oslo");
boolean second = visited.add("Lima");
boolean third = visited.add("Oslo");
visited.add("Pune");
Los tres booleanos almacenados son true, true y false. El segundo «Oslo» coincide con un elemento existente, por lo que no se añade. El tamaño del conjunto es 3. Una adición duplicada no reemplaza una posición numerada porque un conjunto no tiene índices.
visited.contains("Lima") devuelve true. visited.remove("Lima") lo elimina y devuelve true; repetir esa eliminación devuelve false. Utiliza un bucle for-each para visitar los valores. No existe get(0) para obtener el primer valor de un HashSet.
Elimina duplicados de una lista
ArrayList<Integer> values = new ArrayList<>();
values.add(3);
values.add(1);
values.add(3);
values.add(2);
values.add(1);
HashSet<Integer> distinct = new HashSet<>(values);
El conjunto tiene tres valores: {1, 2, 3}. Su orden de iteración real no está especificado. La lista original sigue teniendo cinco elementos porque el constructor crea una colección independiente.
Utiliza new LinkedHashSet<>(values) para conservar el orden de la primera aparición, lo que da 3, 1, 2. Utiliza new TreeSet<>(values) para obtener los valores ordenados, 1, 2, 3. Aquí los conjuntos se escriben entre llaves para destacar la pertenencia; el toString() estándar de los conjuntos de Java utiliza corchetes.
Detecta la primera repetición
El resultado de add puede realizar conjuntamente la comprobación de pertenencia y la inserción:
HashSet<Integer> seen = new HashSet<>();
for (int number : numbers) {
if (!seen.add(number)) {
System.out.println(number);
break;
}
}
Para [4, 7, 2, 7, 4], el bucle imprime 7. Es el primer valor encontrado por segunda vez, aunque 4 apareció antes en la secuencia. Antes de que se repita 7, el conjunto contiene 4, 7 y 2. La inserción fallida provoca la detención.
Identifica lo que un conjunto no puede decirte
Comprobar contains antes de cada add es innecesario porque add ya gestiona los duplicados. Una lista con una comprobación de contains también puede mantener valores únicos, pero cada búsqueda en la lista puede recorrer todos los elementos almacenados. Un HashSet expresa la regla directamente.
La igualdad importa para tus propios objetos. Un HashSet<Point> necesita un equals basado en el contenido y un hashCode coherente para reunir puntos creados por separado con coordenadas iguales. Sin esas sobrescrituras, las instancias separadas permanecen como elementos distintos.
Por último, size() mide valores distintos, no apariciones. Las nueve palabras de «el gato vio el perro y el gato corrió» producen seis palabras distintas. Un conjunto ya no te indica que «el» apareció tres veces; utiliza un mapa de frecuencias cuando esos recuentos importen.
Puntos clave
HashSetalmacena valores únicos sin índices ni orden garantizado.adddevuelve false cuando ya hay un valor igual.- Un conjunto copiado elimina duplicados sin modificar la lista original.
- Utiliza el resultado de
addpara detectar un valor repetido. - El tamaño de un conjunto cuenta valores distintos; las frecuencias necesitan un mapa.
3.2 Combina conjuntos y mantén su orden
Los conjuntos pueden describir grupos y comparar su pertenencia. Si dos listas de eventos contienen varias veces a la misma persona, un conjunto reduce primero cada lista a las personas que asistieron. Las operaciones de conjuntos responden después a preguntas sobre cualquiera de los dos eventos, ambos o solo uno.
Combina dos grupos
Sean los asistentes del lunes {Ana, Ben, Cai, Dee} y los del martes {Ben, Dee, Eva}.
| Pregunta | Método sobre una copia del lunes | Resultado |
|---|---|---|
| ¿Quién asistió cualquiera de los dos días? | addAll(tuesday) | {Ana, Ben, Cai, Dee, Eva} |
| ¿Quién asistió ambos días? | retainAll(tuesday) | {Ben, Dee} |
| ¿Quién asistió solo el lunes? | removeAll(tuesday) | {Ana, Cai} |
Estas operaciones son la unión, la intersección y la diferencia. Modifican el conjunto receptor y devuelven un booleano que indica si cambió. No devuelven un conjunto nuevo con el resultado.
Conserva el original
Haz una copia antes de cambiar la pertenencia si aún necesitas el conjunto del lunes:
HashSet<String> both = new HashSet<>(monday);
both.retainAll(tuesday);
both empieza con los cuatro nombres del lunes. retainAll elimina a Ana y Cai porque no están el martes. El conjunto del lunes permanece sin cambios. Para encontrar a quienes asistieron solo el martes, empieza con una copia del martes y elimina los nombres del lunes; el resultado es {Eva}. La diferencia tiene un sentido; invertirlo cambia la pregunta.
Comprueba subconjuntos e igualdad
monday.containsAll(group) pregunta si todos los valores de group están presentes el lunes. Para {Ben, Dee}, devuelve true: ese grupo es un subconjunto del lunes. No exige que el conjunto del lunes contenga solo a esas dos personas.
Dos conjuntos son iguales cuando sus elementos coinciden, independientemente del orden de inserción o de la implementación. Un HashSet que contiene «x» e «y» es igual a un TreeSet que contiene «y» y «x». La pertenencia determina la igualdad de conjuntos, por lo que el orden por sí solo no puede hacerlos distintos.
Elige un orden para el recorrido
| Implementación | Orden al visitar los elementos |
|---|---|
HashSet | Sin garantía |
LinkedHashSet | Orden de inserción |
TreeSet | Orden según los valores |
Los tres evitan duplicados. Utiliza LinkedHashSet cuando importe la primera vez que apareció cada nombre. Utiliza TreeSet cuando cada recorrido deba estar ya ordenado. Para las cadenas, la ordenación natural sigue los códigos de carácter: las formas en minúsculas y mayúsculas no se comportan como un único alfabeto que no distingue entre ellas.
Un TreeSet con su constructor predeterminado necesita elementos que tengan una comparación natural, como cadenas, números u objetos que implementen Comparable. En ese conjunto, un resultado de comparación igual a cero indica un duplicado. Una clase que no proporciona una comparación natural provoca una ClassCastException al insertarse. Proporcionar un comparador explícito es otra forma de definir el orden de una colección basada en árboles; los ejemplos predeterminados utilizan el orden natural.
Puntos clave
addAll,retainAllyremoveAllmodifican el conjunto receptor.- Copia primero un conjunto cuando aún necesites su pertenencia original.
containsAllcomprueba un subconjunto; la igualdad de conjuntos ignora el orden.- Elige implementaciones basadas en hash, enlazadas o en árbol para obtener un orden no especificado, de inserción u ordenado.
4Programa con las interfaces List, Set y Map
El tipo a la izquierda de una declaración de colección indica al resto del programa qué operaciones puede utilizar. La clase de la derecha proporciona esas operaciones y puede garantizar un orden concreto. Aprender a interpretar ambos lados facilita cambiar el código que utiliza colecciones y reutilizar métodos. También ayuda a explicar por qué una lista, un conjunto y un mapa se comportan de forma distinta incluso cuando contienen datos de aspecto similar.
4.1 Declara variables y parámetros con tipos de interfaz
Una interfaz describe las operaciones que proporciona una clase que la implementa. Permite que una variable describa lo que necesita el código y deja la elección del almacenamiento a una clase concreta. List, Set y Map son interfaces relacionadas con colecciones en java.util.
Interpreta los dos lados de una declaración
List<String> names = new ArrayList<>();
Set<String> tags = new HashSet<>();
Map<String, Integer> counts = new HashMap<>();
El lado izquierdo declara el tipo de la variable. El derecho crea un objeto de una clase que lo implementa. Importa ambos tipos, como java.util.List y java.util.ArrayList. No puedes escribir new List<>() ni new Map<>(): una interfaz no es un objeto concreto que se pueda construir.
El código que utiliza counts puede llamar a put, get y entrySet porque Map los declara. Si resulta útil tener las claves en orden alfabético, cambia la construcción a new TreeMap<>(). Las llamadas existentes siguen compilándose. Su orden puede cambiar porque las implementaciones pueden ofrecer distintas garantías de orden; la interfaz no hace que su comportamiento sea idéntico en todo.
Acepta la capacidad que necesita un método
Un método que solo cuenta palabras largas puede aceptar una Collection:
static int countLong(Collection<String> words, int min) {
int count = 0;
for (String word : words) {
if (word.length() >= min) {
count++;
}
}
return count;
}
Para [«a», «tree», «house»] y un mínimo de 4, devuelve 2. El mismo método puede recibir un ArrayList, un LinkedList, un HashSet o List.of(...) porque solo lee los elementos. Un conjunto puede haber eliminado ya los duplicados, por lo que puede proporcionar datos de entrada distintos de los de una lista.
Utilizar un parámetro de tipo interfaz evita exigir una clase de almacenamiento concreta cuando el método no la necesita. Si se necesitan posiciones, acepta List. Si se necesita buscar por clave, acepta Map.
Conoce los límites del tipo declarado
List<String> names = new ArrayList<>();
names.ensureCapacity(100); // does not compile
El objeto es un ArrayList, pero List no declara ensureCapacity. El compilador comprueba el tipo declarado de la variable. Utiliza un tipo de clase concreta cuando realmente necesites su operación especial; no cambies los parámetros de lista habituales solo para que coincidan con la clase de quien los llama.
Sitúa Map junto a Collection
List y Set extienden Collection, que describe un grupo de elementos. Declara métodos como add, remove, contains, size, isEmpty, addAll y clear. Que se admita una modificación depende de la colección real.
Map no extiende Collection. Almacena asociaciones y proporciona vistas que son colecciones: keySet() es un Set, values() es una Collection y entrySet() es un Set de entradas. Pasa counts.values() a un método que necesite una colección de valores, no counts directamente.
Una clase puede implementar varias interfaces. LinkedList implementa tanto List como Deque, una interfaz de cola de doble extremo. Tu propia clase indica las interfaces que se compromete a implementar después de implements, como en class Member implements Comparable<Member>.
Puntos clave
- Declara la interfaz necesaria a la izquierda y construye una clase que la implemente a la derecha.
- Los parámetros de tipo interfaz aceptan distintas implementaciones que proporcionan las operaciones necesarias.
- Una variable solo permite acceder a los métodos declarados por su tipo.
ListySetextiendenCollection;Mapproporciona vistas de colección.
4.2 Identifica qué garantizan List, Set y Map
Elige una interfaz según las reglas que necesiten tus datos. Que su contenido parezca similar no hace intercambiables una lista, un conjunto y un mapa: cada uno da un significado diferente a las posiciones, las repeticiones y la igualdad.
Compara las garantías
| Interfaz | Qué almacena | Regla importante |
|---|---|---|
List | Elementos en posiciones que empiezan en 0 | Se permiten elementos repetidos |
Set | Elementos distintos | No tiene una operación get por índice |
Map | Pares clave-valor | Las claves son únicas; los valores pueden repetirse |
ArrayList y LinkedList implementan List. HashSet, LinkedHashSet y TreeSet implementan Set. HashMap, LinkedHashMap y TreeMap implementan Map. Las versiones basadas en hash no garantizan ningún orden de recorrido; las versiones enlazadas conservan el orden de inserción; las versiones basadas en árboles mantienen ordenados los elementos o las claves. Volver a insertar una clave existente en un LinkedHashMap normal con orden de inserción conserva la posición de esa clave.
Examina con cuidado la eliminación en listas de enteros
Una List<Integer> tiene dos métodos sobrecargados relevantes:
List<Integer> numbers = new ArrayList<>(List.of(1, 5, 7));
numbers.remove(1);
El argumento 1 es un int, por lo que Java elimina el elemento del índice 1: el valor 5. El resultado es [1, 7]. Si vuelves a empezar con [1, 5, 7], numbers.remove(Integer.valueOf(1)) selecciona la eliminación por valor y deja [5, 7]. El objeto envoltorio deja claro qué método sobrecargado se pretende utilizar.
Compara el contenido con la regla adecuada
Dos listas son iguales cuando los mismos elementos aparecen en el mismo orden. Un ArrayList [1, 2] es igual a un LinkedList [1, 2], pero no a una lista [2, 1]. Dos conjuntos comparan la pertenencia e ignoran el orden. Dos mapas comparan las asociaciones, por lo que el orden de inserción no afecta a la igualdad de mapas. Sus clases concretas pueden ser distintas aunque sus contenidos sean iguales según la regla de la interfaz.
Reconoce las colecciones no modificables
List<String> labels = List.of("a", "b");
Set<Integer> levels = Set.of(1, 2, 3);
Map<String, Double> prices = Map.of("tea", 2.0, "coffee", 2.5);
Estas fábricas devuelven colecciones no modificables. Los intentos de añadir, eliminar, reemplazar u ordenar su contenido lanzan UnsupportedOperationException. Map.of acepta hasta diez pares clave-valor.
Las tres rechazan elementos, claves o valores null con NullPointerException. Set.of rechaza elementos duplicados y Map.of rechaza claves duplicadas con IllegalArgumentException. List.of permite duplicados porque una lista puede repetir un elemento. El orden de iteración de los conjuntos y mapas creados por estas fábricas no está especificado.
Haz una copia cuando necesites modificar
new ArrayList<>(labels) crea una lista modificable con los mismos elementos. new HashSet<>(someList) y new HashMap<>(someMap) también crean estructuras de colección independientes.
Estas copias son superficiales: contienen las mismas referencias a elementos. Eliminar un elemento de una copia deja intacta la estructura original, pero modificar un objeto mutable a través de cualquiera de las dos colecciones cambia el objeto compartido. Una colección no modificable impide editar su estructura; no congela todos los objetos almacenados en ella.
Puntos clave
- Las listas tienen posiciones y duplicados; los conjuntos tienen elementos distintos; los mapas tienen claves únicas.
remove(1)en una lista de enteros elimina por índice;remove(Integer.valueOf(1))elimina por valor.- La igualdad de listas comprueba el orden; la de conjuntos y mapas comprueba el contenido sin tener en cuenta el orden de inserción.
- Las fábricas
ofcrean colecciones no modificables y rechazan valores null. Set.ofrechaza elementos duplicados;Map.ofrechaza claves duplicadas.- Una copia modificable separa la estructura de la colección, pero comparte las referencias a elementos.
5Ordena colecciones con Comparable
La ordenación coloca los valores en un orden que otro código puede utilizar. Los números y las cadenas ya tienen un orden natural; los objetos de tus propias clases necesitan una regla explícita. Sigue una lista durante una ordenación y después escribe una comparación que gestione de forma segura números, texto y empates. La regla importa más allá de las listas: un conjunto o mapa ordenado también la utiliza para decidir cuándo dos elementos o claves ocupan la misma posición.
5.1 Ordena listas de números y cadenas
Una lista conserva un orden, pero ese orden puede simplemente reflejar cómo llegaron los valores. La ordenación reorganiza la lista mediante una regla de comparación. Java ya proporciona un orden natural para números y cadenas.
Ordena una lista modificable in situ
List<Double> values = new ArrayList<>(List.of(3.5, -1.0, 2.25));
Collections.sort(values);
Importa java.util.Collections. La misma lista contiene ahora [-1,0; 2,25; 3,5]. La ordenación devuelve void, por lo que values = Collections.sort(values) no se compila. values.sort(null) también ordena en orden natural. Para un arreglo, utiliza Arrays.sort(array); un arreglo que contiene 5, 2 y 8 pasa a contener 2, 5 y 8.
Predice el orden de las cadenas carácter por carácter
La comparación de cadenas examina el primer carácter diferente. Si una cadena es prefijo de otra, la más corta va primero. Así, «apple» precede a «apples».
La lista [«pear», «Banana», «apple», «10», «9»] se ordena como [«10», «9», «Banana», «apple», «pear»]. Para estos caracteres, los dígitos preceden a las letras mayúsculas y las mayúsculas preceden a las minúsculas. «10» precede a «9» porque «1» va antes que «9»; el orden de cadenas no interpreta las cadenas de dígitos como números enteros. Almacena los datos numéricos como números cuando necesites un orden numérico.
Utiliza órdenes alternativos ya disponibles
names.sort(String.CASE_INSENSITIVE_ORDER);
values.sort(Collections.reverseOrder());
La primera llamada ordena [«pear», «Banana», «apple»] como [«apple», «Banana», «pear»] sin cambiar las mayúsculas y minúsculas almacenadas. La segunda utiliza el orden natural descendente. Los números 4, 9 y 1 pasan a ser 9, 4 y 1. Estos argumentos son comparadores, objetos que proporcionan un orden alternativo.
Collections.reverse(list) solo invierte la secuencia actual. Produce un orden descendente si esa secuencia ya estaba ordenada de forma ascendente; por sí solo no ordena una lista cualquiera.
Conserva la estabilidad de los empates
La ordenación de listas es estable: los elementos que se comparan como iguales conservan su orden relativo anterior. Si una comparación basada solo en la puntuación empata a dos personas, se mantiene el orden que tenían en la lista. La estabilidad conserva ese orden de entrada; no inventa un criterio de desempate alfabético.
Reconoce fallos y métodos útiles
Una lista creada con List.of(...) no se puede ordenar in situ. Cópiala primero a un ArrayList. Para una clase que no implementa Comparable, Collections.sort(list) no supera la comprobación de tipos durante la compilación. Llamar a list.sort(null) sobre esos objetos falla en tiempo de ejecución con ClassCastException cuando se necesita comparar.
Collections.max(collection) y Collections.min(collection) encuentran los elementos mayor y menor en orden natural sin reorganizar la colección. Lanzan NoSuchElementException para una colección vacía.
Para obtener las claves de un mapa ordenadas, copia map.keySet() a un ArrayList y ordena la copia, o utiliza un TreeMap. Ordenar una lista de claves copiada deja sin cambios el orden de iteración del propio mapa.
Puntos clave
Collections.sortmodifica una lista modificable in situ y devuelvevoid.- El orden natural de las cadenas compara caracteres, no valores numéricos escritos como texto.
- Utiliza comparadores ya disponibles para el orden inverso o sin distinguir mayúsculas y minúsculas.
- La ordenación estable conserva el orden relativo anterior de los elementos empatados.
- Copia una lista no modificable antes de ordenarla.
minymaxencuentran valores extremos sin ordenar.
5.2 Implementa Comparable en tu propia clase
Java no puede adivinar si un miembro debe ir primero por nombre, altura u otro campo. Implementa Comparable para dotar a la clase de un orden natural. El código de ordenación puede entonces pedir a cada objeto que se compare con otro objeto de esa clase.
Escribe el método de comparación
class Member implements Comparable<Member> {
private String name;
private int height;
Member(String name, int height) {
this.name = name;
this.height = height;
}
@Override
public int compareTo(Member other) {
return Integer.compare(this.height, other.height);
}
}
La altura se mide en centímetros. Comparable<Member> especifica que el otro objeto es un Member; no se necesita una conversión explícita. public int compareTo(Member other) es el método requerido. La interfaz estándar Comparable está en java.lang, por lo que no necesita importación.
Para a.compareTo(b), un resultado negativo coloca a antes que b, cero los sitúa en la misma posición de comparación y un resultado positivo coloca a después de b. Solo importa el signo: -35 es un resultado negativo tan válido como -1.
Sigue el orden
Con la comparación por altura, Ana 172, Ben 165 y Cai 180 se ordenan como Ben 165, Ana 172 y Cai 180. Para colocar primero a los miembros más altos, intercambia los argumentos:
return Integer.compare(other.height, this.height);
Cambia la regla de forma deliberada. Invertir los argumentos invierte el sentido de ese campo; no cambia lo que significa la altura ni modifica los datos de ningún miembro.
Compara valores numéricos completos de forma segura
La resta parece cómoda, pero puede devolver el signo incorrecto cuando un int se desborda. Para -2 000 000 000 y 2 000 000 000, restar el segundo del primero produce por desbordamiento 294 967 296, un resultado positivo. Integer.compare devuelve correctamente un resultado negativo.
Para campos decimales, utiliza Double.compare(this.price, other.price). Convertir explícitamente una diferencia a int pierde información: (int) (1.8 - 1.5) es 0, por lo que precios distintos se convierten en un empate de comparación. Un método de comparación conserva el orden sin truncar la diferencia.
Compara texto y reutiliza la regla
Para ordenar por nombre, devuelve this.name.compareTo(other.name). Sigue el orden por unidades de código de la cadena. compareToIgnoreCase proporciona una comparación de texto que no distingue mayúsculas y minúsculas cuando esa es la regla prevista para el campo.
Una vez que una clase define su orden natural, operaciones como Collections.sort, Collections.max y las comparaciones predeterminadas de TreeSet o TreeMap pueden utilizarlo. Una clase también puede implementar otras interfaces, separadas por comas después de implements.
La clase tiene un único orden natural; no se selecciona un compareTo diferente para cada lista. Utiliza objetos comparadores separados cuando un contexto necesite ordenar por nombre y otro por altura. Una comparación solo por altura también empata todas las alturas iguales; decidir si ese empate es aceptable es especialmente importante en los conjuntos ordenados.
Puntos clave
- Implementa
Comparable<YourClass>con un método públicocompareTo. - Los resultados negativo, cero y positivo significan antes, empate y después.
- Utiliza
Integer.compareyDouble.comparepara ordenar números de forma segura. - Intercambia los argumentos de comparación para invertir el sentido de un campo.
- Una clase tiene un orden natural; los comparadores proporcionan otros órdenes.
5.3 Resuelve empates y utiliza conjuntos y mapas ordenados
Una comparación principal a menudo deja empates. Dos películas pueden compartir año o dos jugadores pueden compartir puntuación. Un criterio de desempate da paso al siguiente campo solo cuando los campos anteriores se comparan como iguales.
Compara los campos por orden de prioridad
@Override
public int compareTo(Film other) {
int byYear = Integer.compare(this.year, other.year);
if (byYear != 0) {
return byYear;
}
return this.title.compareTo(other.title);
}
El año es el criterio principal. El título solo importa cuando los años empatan. Up (2009), Avatar (2009) y Alien (1979) se ordenan como Alien (1979), Avatar (2009), Up (2009). Comparar primero los títulos les daría prioridad sobre el año y resolvería una tarea de ordenación diferente.
Los sentidos pueden ser distintos según el campo. Para poner primero los puntos más altos y ordenar los nombres de la A a la Z, empieza con Integer.compare(other.points, this.points). Si el resultado es cero, devuelve this.name.compareTo(other.name). Invertir toda la lista final también invertiría los nombres dentro de las puntuaciones empatadas.
Comprende la regla de duplicados de un conjunto ordenado
Un TreeSet<Member> predeterminado utiliza la comparación natural tanto para ordenar elementos como para decidir cuándo un elemento ya está presente. Si Member.compareTo utiliza solo la altura, Ana 172 y Dee 172 se comparan como cero. Añadir a Ana devuelve true; añadir a Dee devuelve false. Ana permanece como elemento almacenado aunque equals considere diferentes a las dos personas.
Una lista puede conservar ambos objetos empatados; un conjunto basado en árbol les asigna una sola posición de comparación. Añade el criterio de desempate necesario si deben ser distintos en el conjunto.
Alinea la comparación con la igualdad
Un orden es consistente con equals cuando la comparación devuelve cero si y solo si equals devuelve verdadero. Para una clase cuya igualdad utiliza altura y nombre, comparar la altura y luego el nombre puede cumplir esta regla. Si la igualdad utiliza una identidad diferente, como un identificador de miembro, añadir solo el nombre como criterio de desempate no establece la consistencia.
La comparación también debe comportarse como un orden correcto. Si a va antes que b, la comparación inversa debe colocar b después de a. Si a va antes que b y b antes que c, a debe ir antes que c. Utilizar métodos que comparan campos completos en un orden fijo de prioridad ayuda a cumplir estas reglas. Un método inconsistente puede ordenar mal los resultados o hacer que una ordenación lance IllegalArgumentException.
Mantén también ordenadas las claves de los mapas
Un TreeMap ordena las claves, no los valores. Para los recuentos de palabras de «el gato vio el perro y el gato corrió», la primera clave es «corrió» y la última es «y». firstKey() y lastKey() proporcionan esos extremos. Declara un TreeMap o una interfaz de mapa ordenado adecuada cuando llames a métodos que Map no declara.
La comparación de claves también define qué claves coinciden. Una segunda clave que se compare como cero actualiza la asociación existente, aunque equals distinga los objetos. Las colecciones basadas en árboles predeterminadas requieren elementos o claves comparables naturalmente; insertar un objeto sin una comparación adecuada lanza ClassCastException. Un comparador proporcionado explícitamente puede definir otro orden.
Puntos clave
- Compara primero el campo principal y consulta los siguientes solo si hay empate.
- Invierte solo los campos que necesiten orden descendente.
- Las colecciones basadas en árboles tratan una comparación igual a cero como el mismo elemento o clave.
- La consistencia con
equalsrequiere que la comparación dé cero exactamente cuando la igualdad sea verdadera. TreeMapordena las claves; sus métodos de extremos devuelven las claves extremas.- Una comparación debe invertir los signos de forma consistente y conservar el orden entre ternas.
6Elige la colección adecuada para una tarea
La elección de una colección comienza con las preguntas a las que debe responder el programa: por posición, por pertenencia o por una clave independiente. El orden y los duplicados acotan aún más la elección. Una vez que los datos se ajustan a la tarea, compara cómo crece el coste de las operaciones frecuentes a medida que llegan más valores. Un pequeño cambio, como crear un conjunto antes de un bucle, puede eliminar búsquedas repetidas sin dificultar la lectura del programa.
6.1 Compara el coste de las operaciones habituales con colecciones
El coste de una operación describe cómo crece su trabajo con el número de elementos almacenados. Ayuda a identificar código que es rápido para un ejemplo pequeño, pero lento cuando la colección crece.
Compara el crecimiento, no los segundos
El tiempo constante, O(1), se mantiene aproximadamente independiente del tamaño de la colección. El tiempo lineal, O(n), puede crecer en proporción al número de elementos. El tiempo logarítmico, O(log n), crece lentamente al aumentar el tamaño. Estas etiquetas describen el crecimiento, no tiempos de ejecución exactos en un equipo concreto.
| Colección | Operación | Coste |
|---|---|---|
ArrayList | get(i), set(i, x) | Constante |
ArrayList | Añadir al final | Constante en promedio |
ArrayList | contains, indexOf, eliminación por valor | Lineal |
ArrayList | Insertar o eliminar cerca del principio | Lineal |
HashMap / HashSet | Búsqueda básica por clave o pertenencia, inserción, eliminación | Constante en promedio con códigos hash bien distribuidos |
TreeMap / TreeSet | Búsqueda básica, inserción, eliminación | Logarítmico |
LinkedList | Añadir o eliminar en cualquiera de los extremos | Constante |
LinkedList | get(i) en general | Lineal |
Una búsqueda en un ArrayList puede comprobar todos los elementos; las modificaciones al principio desplazan los elementos posteriores. Un LinkedList debe recorrer la lista hasta llegar a una posición, por lo que acceder repetidamente por índice puede ser costoso. ArrayList es una opción predeterminada útil para el trabajo habitual con listas.
Detecta el recorrido repetido
Supón que un programa comprueba 10 000 nombres frente a una lista que contiene 100 000 nombres. Llamar a list.contains(name) para cada nombre puede requerir hasta 1 000 000 000 de comprobaciones de igualdad. Una llamada a un método que parece rápida sigue siendo una búsqueda completa cuando se utiliza de esta forma.
Construye una vez un conjunto para comprobar la pertenencia:
Set<String> allowed = new HashSet<>(allowedNames);
int matches = 0;
for (String name : incomingNames) {
if (allowed.contains(name)) {
matches++;
}
}
Hay trabajo para construir el conjunto de 100 000 elementos, seguido de 10 000 comprobaciones de pertenencia de tiempo constante en promedio. Contando ambas etapas, el total crece aproximadamente con la suma de los tamaños de las dos entradas, en lugar de con su producto. Volver a construir el conjunto dentro del bucle repetiría el trabajo de preparación y perdería esa ventaja.
Interpreta correctamente las garantías promedio
Las operaciones basadas en hash dependen de claves cuyos códigos hash distribuyan bien los valores. Devolver un código hash constante para todos los objetos puede seguir cumpliendo los requisitos de igualdad, pero hace lenta la búsqueda. No es una forma gratuita de evitar escribir un método hash útil.
Las colecciones basadas en árboles mantienen el orden con operaciones básicas de tiempo logarítmico. Duplicar el número de elementos añade solo una pequeña cantidad de trabajo de búsqueda. Para 100 000 elementos, un logaritmo en base dos es aproximadamente 16,6; esto sugiere la escala de la búsqueda, no una garantía exacta de 17 comparaciones en cada búsqueda en un árbol de Java.
Ten en cuenta toda la tarea
Construir un conjunto adicional cuesta tiempo y memoria. Para unos pocos elementos o una sola búsqueda, la lista original puede ser suficiente. Para comprobaciones de pertenencia repetidas, un conjunto reutilizable suele eliminar el coste principal. Empieza por el comportamiento requerido y después examina las operaciones que se repiten con más frecuencia.
Puntos clave
- Las etiquetas de crecimiento describen cómo escala el trabajo, no un número medido de segundos.
ArrayListofrece acceso rápido por índice, pero las búsquedas y las modificaciones al principio son lineales.- Las búsquedas basadas en hash son constantes en promedio con códigos hash adecuados; las búsquedas en árboles son logarítmicas.
- Construye una vez un conjunto para comprobar la pertenencia y sustituir recorridos repetidos de listas.
- Incluye el tiempo de preparación y la memoria al comparar soluciones completas.
6.2 Selecciona una colección que se ajuste a la tarea
La colección adecuada conserva la información que necesita el programa y facilita expresar sus preguntas principales. Decide las reglas de los datos antes de elegir el nombre de una clase conocida.
Pregunta qué identifica un elemento
| Necesidad principal | Elección inicial | Ejemplo |
|---|---|---|
| Encontrar un valor mediante una clave independiente | Map | Código de producto asociado a precio |
| Comprobar pertenencia sin duplicados | Set | Nombres de usuario ocupados |
| Conservar posiciones, orden o elementos repetidos | List | Una lista de reproducción que repite canciones |
| Conservar un número fijo de posiciones | Arreglo | Doce mediciones mensuales de precipitación |
Un double[12] puede contener la precipitación en milímetros cuando cada posición corresponde a un mes conocido. Un mapa cuyas claves son solo las posiciones 0, 1, 2 y así sucesivamente añade una capa que una lista o un arreglo ya proporciona.
Elige el orden que necesitas
Para mapas y conjuntos, utiliza HashMap o HashSet cuando no se requiera un orden, LinkedHashMap o LinkedHashSet para el orden de inserción y TreeMap o TreeSet para claves o elementos ordenados. Para una lista de uso general, empieza con ArrayList.
Los recuentos de palabras impresos en orden alfabético se ajustan a un TreeMap<String, Integer>. Una lista de etiquetas distintas en el orden en que aparecieron por primera vez se ajusta a un LinkedHashSet<String>. Las canciones repetidas necesitan una lista aunque también estén almacenadas en otro lugar en un conjunto: descartar las repeticiones cambiaría la lista de reproducción.
Combina colecciones cuando los datos tienen capas
Los estudiantes por curso pueden representarse con Map<String, List<String>>; cada valor es una lista ordenada de inscripciones. Las etiquetas por artículo pueden representarse con Map<String, Set<String>>; cada artículo obtiene etiquetas distintas. Una clasificación puede ser una List<Player> ordenada según la comparación natural del jugador.
Las elecciones externas e internas responden a preguntas diferentes. Si los cursos deben listarse en orden alfabético y los estudiantes deben conservarse en orden de inscripción, utiliza un TreeMap por fuera y una lista por dentro. Ordenar las claves no ordena las listas. Si deben ignorarse los registros de inscripción duplicados, utiliza un conjunto para los grupos internos.
Mantén juntos los datos relacionados
Dos listas paralelas, una para nombres y otra para números de teléfono, dependen de que las posiciones coincidan. Eliminar un nombre sin su número desajusta todos los pares posteriores. Si los nombres identifican de forma única a las personas, un mapa puede contener la asociación. Si los nombres se repiten o varios campos pertenecen a una persona, conserva objetos de persona en una lista o indéxalos mediante un identificador único.
Buscar una y otra vez en una lista por un campo es otra señal para considerar un índice basado en un mapa. Conserva también la lista si importan el orden de presentación y las entradas repetidas, pero mantén ambas estructuras coordinadas cuando se añadan o eliminen datos.
Comprueba las reglas de los elementos y el tipo declarado
Utiliza una declaración de interfaz como Map<String, Double> prices = new HashMap<>(); para que quienes llaman dependan de las operaciones de mapa que necesitan. Las colecciones basadas en hash necesitan una igualdad significativa y códigos hash coherentes para claves o elementos propios. Las colecciones basadas en árboles predeterminadas necesitan una comparación natural que distinga exactamente los valores que la colección debe conservar. Estas reglas forman parte de conseguir que la colección elegida represente los datos previstos.
Puntos clave
- Elige mapas para búsquedas por clave, conjuntos para pertenencia y listas para posiciones o repeticiones.
- Los arreglos pueden contener un número fijo de posiciones, incluidos valores primitivos.
- Elige de forma deliberada el orden de inserción o el orden según los valores.
- Las colecciones anidadas permiten que las claves externas y los grupos internos sigan reglas diferentes.
- Mantén juntos los campos relacionados y actualiza varios índices mediante métodos compartidos.
- Ajusta las reglas de igualdad y comparación a los valores que la colección debe conservar.
Ejemplos de HashMap y colecciones en Java
1Sigue un mapa de existencias desde el almacenamiento hasta la búsqueda
13 pasos
- 1IntroducciónEmpieza con una pregunta sobre un producto
Un programa de existencias necesita responder «¿cuántas carpetas hay disponibles?». Un mapa convierte el nombre del producto en la clave y su cantidad en el valor. Sigue un mapa durante un reemplazo, una búsqueda sin resultado y una limpieza. Después examina por qué una clave propia puede fallar aunque sus campos parezcan correctos. Cada búsqueda depende de lo que Java considera la misma clave.
- 2ExplicaciónCrea una asociación por clave
Crea
HashMap<String, Integer> stock = new HashMap<>();.Stringdescribe las claves;Integerdescribe los valores. El mapa utiliza tipos de referencia, por lo queintno puede ser el argumento de tipo del valor. Java empaqueta un literal como6cuandostock.put("folder", 6)lo almacena. El diamante de la derecha permite que Java infiera los dos tipos. - 3EjemploReemplaza una cantidad
Ejecuta estas actualizaciones en orden:
stock.put("folder", 6); stock.put("clip", 11); Integer old = stock.put("folder", 8);La última llamada encuentra la clave folder existente, almacena
8y devuelve6enold. Sigue habiendo dos claves. Un mapa registra el valor más reciente de una clave; no suma automáticamente las cantidades ni conserva un historial de ellas. - 4DesafíoLee sin insertar
¿Cuáles son los valores de
nystock.size()después de esta lectura? El mapa sigue teniendo folder 8 y clip 11.int n = stock.getOrDefault("tape", 0);---reveal---
nes0y el tamaño sigue siendo2. El valor predeterminado es un resultado para una clave ausente, no una entrada insertada. Leer conget("tape")devuelve null, que no se puede desempaquetar como unint. - 5ExplicaciónLee los pares juntos
Un bucle sobre entradas proporciona cada clave y su valor juntos:
for (Map.Entry<String, Integer> e : stock.entrySet()) { System.out.println(e.getKey() + ": " + e.getValue()); }Importa
java.util.Map. El bucle puede mostrar ambas asociaciones sin ungetadicional. Si solo se necesita un total, recorrestock.values()y suma las cantidades; las cantidades repetidas siguen contribuyendo por separado. - 6Idea claveNo des por supuesta la primera entrada
La salida podría mostrar folder antes que clip o clip antes que folder. HashMap no garantiza ninguno de los dos órdenes. Un resultado como una suma no se ve afectado, pero una regla que conserva la primera puntuación empatada puede depender del recorrido. Elige
LinkedHashMappara el orden de inserción oTreeMappara ordenar las claves, y establece una regla de desempate explícita para los máximos empatados cuando el ganador deba ser predecible. - 7EjemploElimina durante el recorrido
Supón que folder es ahora 0 y clip es 11. Elimina las cantidades cero con un iterador:
Iterator<Map.Entry<String, Integer>> it = stock.entrySet().iterator(); while (it.hasNext()) { if (it.next().getValue() == 0) { it.remove(); } }El iterador elimina su entrada actual y continúa de forma segura. Llamar a
stock.removedesde un recorrido for-each puede, en cambio, provocarConcurrentModificationException. - 8DesafíoDistingue una copia de claves
Antes de la limpieza,
keysse crea connew ArrayList<>(stock.keySet()). Si se llama akeys.remove("folder"), ¿qué ocurre con el mapa de existencias?---reveal---
El mapa conserva su asociación para folder.
keyses una lista independiente de las claves que existían cuando se hizo la copia. Eliminar destock.keySet()directamente eliminaría la entrada del mapa, porque ese objeto es una vista vinculada. - 9EjemploPrueba una clave propia
Imagina que
Bintiene los camposrowycolumny no sobrescribe los métodos de igualdad. Almacena una etiqueta utilizandonew Bin(3, 4)y después búscala utilizando otronew Bin(3, 4). La búsqueda devuelve null. Son dos objetos distintos yObject.equalsheredado utiliza la identidad. Los valores coincidentes de los campos todavía no se han convertido en una regla de coincidencia de claves. - 10ExplicaciónHaz coherentes la igualdad y el código hash
Para definir la identidad de un contenedor según sus coordenadas, sobrescribe
equals(Object other)para comparar la fila y la columna, y sobrescribehashCode()utilizando los mismos campos, por ejemplo,Objects.hash(row, column). Las coordenadas iguales deben producir códigos hash iguales. Un código hash coincidente por sí solo no establece la igualdad; la comprobación de igualdad sigue distinguiendo las claves con coordenadas diferentes. - 11DesafíoDetecta una sobrecarga
Una clase define
public boolean equals(Bin other)yhashCode()a partir de sus coordenadas. ¿Por qué puede seguir fallando una búsqueda con otro contenedor que parece igual?---reveal---
El parámetro debe ser
Objectpara sobrescribir el método de igualdad de Java. El método con parámetro Bin es una sobrecarga y deja vigente la igualdad por identidad heredada. Añadir@Overridea esa firma incorrecta hace que el compilador muestre el error. - 12DesafíoCorrige un diseño con claves que cambian
Una clave de contenedor utiliza la fila y la columna en ambos métodos de igualdad. El programa cambia su fila mientras está almacenada y después no puede encontrar su etiqueta. ¿Cómo debe actualizar la ubicación y luego eliminar de forma segura las etiquetas vacías durante el recorrido?
---reveal---
Elimina la asociación antes de cambiar la clave y después vuelve a insertarla. Para la limpieza durante el recorrido, utiliza el método de eliminación del propio iterador de entradas. La identidad estable de la clave y el recorrido seguro resuelven partes distintas de esta actualización.
- 13RepasoMantén una lista de comprobación para actualizar mapas
Para una búsqueda sin resultado, decide si un valor predeterminado o una comprobación explícita de ausencia se ajusta a la tarea. Para un bucle, decide si el orden importa y si se eliminarán claves. Para una clave propia, comprueba la firma exacta de
equals(Object), que se utilicen los mismos campos para el código hash y que la identidad sea estable. Estas comprobaciones localizan distintas causas de un mismo síntoma: una asociación que el programa no puede utilizar como se esperaba.
2Construye información de asistencia a medida que llegan registros
12 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónConvierte las llegadas en respuestas útiles
- 2EjemploInicia un recuento de sesiones
- 3EjemploDistingue las sesiones distintas de los registros
- 4DesafíoCorrige un recuento que se reinicia
- 5ExplicaciónCrea un grupo una sola vez
- 6EjemploSigue la referencia interna
- 7DesafíoEncuentra el error de grupo compartido
- 8ExplicaciónIndexa mediante una clave identificadora
- 9Idea claveModifica un objeto en varios lugares
- 10DesafíoMantén la coherencia al eliminar
- 11DesafíoCombina recuentos con pertenencia sin duplicados
- 12RepasoComprueba una primera llegada y una repetición
3Compara dos grupos de asistencia
9 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónPregunta quién asistió, no cuántas visitas hubo
- 2EjemploElimina los escaneos repetidos
- 3DesafíoDetente en la primera llegada repetida
- 4EjemploConserva solo los miembros compartidos
- 5ExplicaciónElige el sentido de la diferencia
- 6DesafíoComprueba un grupo seleccionado
- 7ConsejoElige un orden útil para el informe
- 8DesafíoCrea un informe ordenado de ausencias
- 9RepasoInterpreta el receptor como grupo inicial
4Interpreta declaraciones y copias de colecciones
10 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónInterpreta ambos lados de la declaración
- 2ExplicaciónDeclara lo que necesita quien llama
- 3EjemploUtiliza un parámetro más general para leer
- 4DesafíoIdentifica el problema del método ausente
- 5ConexiónElige el significado del contenido
- 6EjemploSigue la eliminación de enteros
- 7DesafíoCopia antes de ordenar
- 8Idea claveDistingue las modificaciones de objetos de las de listas
- 9DesafíoPasa la vista de mapa adecuada
- 10RepasoComprueba el tipo, la operación y el objeto
5Construye una clasificación que conserve los empates correctos
15 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónElige qué va primero
- 2EjemploOrdena la misma lista
- 3ExplicaciónExamina el primer carácter diferente
- 4DesafíoUtiliza un orden disponible
- 5ExplicaciónDota a una clase de un orden natural
- 6EjemploEvita un falso empate numérico
- 7DesafíoInvierte el campo numérico
- 8EjemploResuelve solo los empates reales
- 9EjemploSigue la clasificación paso a paso
- 10DesafíoObserva qué conserva un conjunto basado en árbol
- 11Idea claveAjusta la ordenación a la identidad
- 12ConexiónComprueba la clave de un mapa ordenado
- 13DesafíoConserva todos los resultados en una lista ordenada
- 14ConsejoHaz que la regla funcione con ternas
- 15RepasoComprueba una comparación en dos contextos
6Elige estructuras para una lista de participantes de cursos
10 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónEnumera las preguntas que hace el programa
- 2EjemploDetecta el recorrido dentro del bucle
- 3ExplicaciónPrepara una sola vez la comprobación de pertenencia
- 4DesafíoCompara entradas que crecen
- 5EjemploConserva los registros de inscripción repetidos
- 6ExplicaciónElige el orden externo e interno
- 7DesafíoCorrige la regla incorrecta para duplicados
- 8ConsejoAsume el coste del orden que necesitas
- 9DesafíoCombina el diseño final
- 10RepasoElige el comportamiento antes de medir la velocidad
Ejercicios de HashMap y colecciones en Java
Set 1: Construye recuentos y compara grupos10 Preguntas de Práctica
Pregunta 1 de 10
!seen.add(n). ¿Qué número se muestra?Mostrar respuestaOcultar respuesta
Pregunta 2 de 10
Device está almacenado en una lista y en un mapa por identificador. Se recupera del mapa y después cambia su campo de estado. ¿Qué estado muestra la referencia almacenada en la lista?Mostrar respuestaOcultar respuesta
put para cambiar un campo, aunque los cambios de pertenencia requieren mantenimiento por separado.Pregunta 3 de 10
"north" → 4, "south" → 2 y "west" → 3. ¿Cuántas claves distintas contiene?Mostrar respuestaOcultar respuesta
Pregunta 4 de 10
"cedar". ¿Qué devuelve otra llamada a add("cedar")?Mostrar respuestaOcultar respuesta
add devuelve false. Una primera adición que tiene éxito devuelve true. El valor de retorno indica si hubo un cambio, no es el propio elemento ni un recuento de las veces que el programa intentó añadirlo.Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Pregunta 6 de 10
"red", "gold", "red", "blue", "gold", "red" utilizando counts.put(word, counts.getOrDefault(word, 0) + 1). ¿Cuáles son el recuento de red y el tamaño del mapa?Mostrar respuestaOcultar respuesta
Pregunta 7 de 10
groups.put(team, new ArrayList<>()); seguido de groups.get(team).add(name);. Un equipo recibe a Omar, Pia y después Ren. ¿Qué queda bajo ese equipo?Mostrar respuestaOcultar respuesta
put reemplaza el grupo por una lista vacía nueva antes de añadir el nombre. Por tanto, la última llegada deja solo a Ren. Para conservar todos los nombres, crea la lista solo en la primera llegada y añade los nombres posteriores al mismo grupo almacenado en lugar de reiniciarlo.Pregunta 8 de 10
C.removeAll(B). ¿Qué contiene C?Mostrar respuestaOcultar respuesta
Pregunta 9 de 10
"Morning" como bajo "Evening". El programa añade "Lee" mediante Morning, después reemplaza la asociación de Evening por una lista nueva y añade "Jo" mediante Evening. ¿Cuáles son los grupos finales?Mostrar respuestaOcultar respuesta
Pregunta 10 de 10
retainAll(B). D se copia de B y ejecuta removeAll(C). ¿Cuáles son D y el resultado de A.containsAll(C)?Mostrar respuestaOcultar respuesta
containsAll permite el elemento adicional 1 de A. Sería incorrecto exigir tamaños iguales para esa comprobación de subconjunto.Set 2: Lee y actualiza mapas de forma fiable10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
HashMap<String, Integer> vacío recibe put("brush", 5) y después put("brush", 14). ¿Cuáles son su tamaño y el valor de "brush"?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
"tray". ¿Qué ocurre al ejecutar int n = map.get("tray");?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
equals correcto. ¿Cómo deben ser sus códigos hash?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
"beam" → 9. El programa ejecuta Integer old = map.put("beam", 13); y después Integer removed = map.remove("beam");. ¿Cuáles son old, removed y el tamaño final?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
entrySet() y debe eliminar cada entrada cuyo valor sea cero. ¿Cómo debe eliminar la entrada durante el recorrido?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Cell define equals(Cell other) y un hashCode basado en campos. Las celdas separadas con campos iguales no coinciden como claves de HashMap. ¿Qué cambio de método corrige el error de igualdad?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
"ink" → 4 y "paper" → 0. keys es un ArrayList nuevo copiado de su conjunto de claves. El programa elimina "ink" de keys, elimina "paper" mediante la vista de conjunto de claves del mapa y después duplica todos los valores que quedan en el mapa. ¿Qué queda en el mapa?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Location utilizan una coordenada mutable. Se almacena una clave y después se cambia su coordenada mientras está almacenada; ahora la búsqueda no encuentra su asociación. ¿Qué secuencia de actualización debe utilizar el diseño para evitar este fallo?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 3: Utiliza interfaces y ordena datos10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Set<String> codes = new HashSet<>();, ¿cuál es el tipo declarado de codes?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
a.compareTo(b)?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
List<Integer> mutable comienza como [4, 8, 12]. Ejecuta remove(1). ¿Qué queda?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
"zebra", "Apron", "18", "3", "ant"?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Collection<String>. Quien llama tiene Map<String, String> labels y quiere que el método procese cada valor de etiqueta. ¿Qué debe pasarse?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
(int) (this.price - other.price). ¿Qué falla para los precios 6,8 y 6,3?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
compareTo a continuación?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Ticket mutable. Se copia de ella un segundo ArrayList. El programa cambia la etiqueta del ticket mediante la copia y después vacía la copia. ¿Qué contiene la lista original?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Reading.equals utiliza el identificador de estación y la temperatura, pero su comparación natural utiliza solo la temperatura. Un TreeSet predeterminado recibe A con 16, B con 16 y después C con 12. ¿Cuáles son su tamaño y los identificadores conservados?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 4: Identifica problemas en el comportamiento de las colecciones10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
"pending" asociada explícitamente a null. ¿Qué devuelve getOrDefault("pending", 20)?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Set.of("draft", "final", "draft")?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
"Ari Chen" y ya no se puede recuperar al primero por ese nombre. ¿Qué diseño conserva directamente a ambos para búsquedas individuales?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Collections.reverse(list)?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
"Support". El programa evalúa List<String> result = groups.getOrDefault("Support", new ArrayList<>()); y después añade "Nia" a result. ¿Qué devuelve una llamada posterior a groups.get("Support")?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
ScoreKey utiliza equipo y puntos; su comparación natural utiliza solo puntos. Un TreeMap predeterminado recibe la clave East-30 con valor "old", West-30 con valor "new" y después North-18 con valor "low". ¿Cuáles son su tamaño y el valor encontrado mediante East-30?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
addAll(B) y después removeAll(A). ¿Qué es U y cambió alguno de los originales?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 5: Combina búsqueda, agrupación y orden10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
map.values()?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
get. ¿Qué corrección completa conserva los requisitos?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
¿Te atascas con una pregunta tuya? Ayuda con Tareas
Términos Clave
A
Agrupación
Arreglo
double[12] puede dar a cada mes una posición para su medición de precipitación en milímetros.B
Búsqueda por clave
C
Clase envoltorio
Integer como tipo de valor porque int no puede aparecer como argumento de tipo genérico.Clase HashMap
HashMap<String, Integer> puede buscar el recuento actual de un producto sin utilizar una posición de lista.Clase HashSet
HashSet<String> puede llevar el registro de los nombres ya procesados mientras un programa lee una secuencia de entrada más larga.Clase LinkedHashMap
LinkedHashMap con orden de inserción.Clase LinkedHashSet
LinkedHashSet pierde las repeticiones y conserva el orden en que aparecieron las etiquetas por primera vez.Clase TreeMap
firstKey().Clase TreeSet
Clave mutable
Colección anidada
Colección no modificable
List.of debe copiarse antes de ordenarla, pero la lista no congela un objeto mutable almacenado en ella.Comparador
String.CASE_INSENSITIVE_ORDER ordena una lista sin cambiar las mayúsculas y minúsculas almacenadas en cada cadena.Conjunto
Consistencia con equals
Contrato del código hash
equals devuelvan códigos hash iguales, y permite colisiones para objetos distintos.x e y tanto en su comprobación de igualdad como en su método de código hash.Copia superficial
Coste de preparación (costo de preparación)
Criterio de desempate
D
Desbordamiento de enteros
Integer.compare evita la inversión de signo que puede causar la resta.Desempaquetado
int el resultado de una búsqueda ausente de Integer falla porque el null devuelto no se puede desempaquetar.Diferencia de conjuntos
E
Elección de colección
Elemento distinto
"sun rain sun" contiene dos claves de palabras distintas, pero registra tres apariciones.Empaquetado automático
12 en un mapa de valores Integer empaqueta automáticamente ese número para almacenarlo.Encapsulación (encapsulamiento)
addBook los actualice conjuntamente en lugar de que los editen quienes llaman.Entrada duplicada
add devuelve false.I
Identificador único
Igualdad de contenido
equals(Object).Igualdad por identidad
Object.Implementación
HashMap y TreeMap implementan Map, pero ofrecen distintas garantías sobre el orden de las claves.Interfaz
List<String> puede recibir un ArrayList o un LinkedList sin cambiar su firma.Interfaz Collection
Collection<String> y recorrer tanto una lista como un conjunto.Interfaz Comparable
compareTo con tipo.Comparable<Member> para que la ordenación de listas pueda ordenar sus instancias por altura.Interfaz Map.Entry
Intersección
retainAll elimina de su receptor los valores no compartidos.Iterador
hasNext(), next() y remove() del iterador para eliminar cantidades cero.Í
Índice
L
Lista
Listas paralelas
M
Mapa
Método compareTo
Método getOrDefault
Método putIfAbsent
putIfAbsent puede asegurar que su clave tenga una lista sin reemplazar una existente.Método sobrecargado
remove(1) selecciona la eliminación por índice, mientras que remove(Integer.valueOf(1)) selecciona la eliminación por valor.Modificación estructural
N
Normalización de claves
O
Orden de iteración
Orden natural
"20" y "3" coloca "20" primero porque los caracteres iniciales deciden su orden.Orden por unidades de código
"7", "Bee" y "ant", el orden natural de cadenas coloca el dígito antes que las letras.Ordenación estable
Ordenación in situ
Collections.sort(values), la variable de lista existente muestra sus elementos en el nuevo orden.P
Par clave-valor
"pen" → 18 conecta un nombre de producto con la cantidad disponible actualmente.Parámetro de tipo interfaz
Map<String, Integer> mientras quienes lo llaman eligen almacenamiento basado en hash o en árbol.Pertenencia
contains mediante la regla de coincidencia de ese conjunto.R
Referencia compartida
S
Sintaxis de diamante
HashMap<String, Integer> m = new HashMap<>();, el diamante evita repetir los dos tipos.Subconjunto
a.containsAll(b) comprueba si b está contenido en a.Suma acumulada
T
Tabla de consulta
Tabla de frecuencias
Tiempo constante
ArrayList no requiere recorrer todas las posiciones anteriores de esa lista.Tiempo lineal
Tiempo logarítmico
Tipo declarado
ArrayList almacenado en una variable List no permite acceder a ensureCapacity mediante esa variable.Transitividad
Truncamiento
U
Unión
addAll de Java la forma modificando el conjunto receptor.V
Vista de colección
- 1Primeros programas en Java
- 2Condiciones y bucles en Java
- 3Métodos en Java
- 4Listas, arreglos y cadenas en Java
- 5Clases y objetos en Java
- 6Objetos y referencias en Java
- 7HashMap y colecciones en Java
- 8Herencia, interfaces y polimorfismo en Java
- 9Excepciones y archivos en Java
- 10Paquetes en Java
- 11Genéricos y expresiones lambda en Java
Sobre esta unidad
Crea tus propios Materiales de Estudio
Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.