1. Búsqueda de elementos en colecciones
Búsqueda con métodos estándar
Cuando tenemos una lista, por ejemplo, de nombres:
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
Java ofrece varios métodos prácticos para buscar:
- contains(Object o) — comprueba si un elemento está en la colección.
- indexOf(Object o) — devuelve el primer índice de aparición del elemento (o -1 si no se encuentra).
- lastIndexOf(Object o) — devuelve el último índice de aparición del elemento (o -1).
Ejemplos:
System.out.println(names.contains("Anna")); // true
System.out.println(names.indexOf("Anna")); // 0
System.out.println(names.lastIndexOf("Anna")); // 3
System.out.println(names.contains("Sergey")); // false
Hecho: Para colecciones del tipo Set no existen los métodos indexOf y lastIndexOf — en un Set no hay índices en absoluto, solo valores únicos.
Búsqueda por condición
A veces hay que encontrar no un valor concreto, sino un elemento que cumpla una condición. Por ejemplo, hallar el primer nombre de más de 6 caracteres. Un bucle for normal va perfecto: en cuanto encuentres un elemento adecuado — usa break.
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // Hemos encontrado el primero que encaja; podemos salir del bucle
}
}
System.out.println(found); // Viktoriya
Búsqueda de los valores máximo y mínimo
Para colecciones con elementos comparables (por ejemplo, números) se puede encontrar rápidamente el máximo y el mínimo con la clase Collections.
List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);
int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3
System.out.println("Máximo: " + max);
System.out.println("Mínimo: " + min);
Importante: Los elementos deben ser comparables (implementar Comparable), de lo contrario será necesario pasar un comparador.
2. Ordenación de colecciones
Ordenación de una lista por defecto
Solo se pueden ordenar listas mutables (por ejemplo, ArrayList, LinkedList). Colecciones del tipo Set y Map no admiten ordenación directamente.
Por defecto la ordenación sigue el «orden natural»: para números — ascendente; para cadenas — alfabético.
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
Lo mismo se puede hacer mediante el método de lista sort:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null significa: usar el orden natural
System.out.println(numbers); // [1, 3, 5, 7]
Ordenación con Comparator
Si necesitas tu propia regla — por ejemplo, ordenar cadenas por longitud:
List<String> words = new ArrayList<>(List.of("gato", "elefante", "mosca", "rinoceronte"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [gato, mosca, elefante, rinoceronte]
En orden inverso:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [rinoceronte, elefante, mosca, gato]
Estilo antiguo mediante Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. Particularidades de la ordenación de distintas colecciones
La ordenación solo modifica la lista
Los métodos de ordenación (sort, Collections.sort) funcionan únicamente con colecciones que mantienen el orden de los elementos (por ejemplo, List). Para Set y Map no existen tales métodos.
Intento de ordenar un Set:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // Error de compilación: sort espera un List!
Si necesitas obtener una lista ordenada a partir de Set:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Ordenar un Map: por claves y por valores
No se puede ordenar un Map directamente, pero se puede:
- Obtener una lista de pares «clave-valor»
- Ordenarla como necesites
- Si hace falta, construir un nuevo Map
Ejemplo: ordenación por valores
Map<String, Integer> scores = Map.of(
"Anna", 15,
"Boris", 20,
"Vika", 12
);
List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Vika: 12
// Anna: 15
// Boris: 20
Ordenación de objetos por un campo
Supongamos que tenemos una clase de usuario:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
Y una lista de usuarios:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Boris", 18),
new User("Vika", 25)
));
Ordenamos por edad:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Boris (18), Anna (22), Vika (25)]
En orden inverso:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Vika (25), Anna (22), Boris (18)]
4. Errores típicos al buscar y ordenar colecciones
Error n.º 1: ordenar una lista inmutable. Las listas creadas con List.of(...) no se pueden modificar — al llamar a sort obtendrás UnsupportedOperationException.
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // ¡Lanzará una excepción!
Error n.º 2: ordenar un Set o un Map directamente. Los métodos de ordenación no funcionan con Set ni con Map. Si necesitas ordenar, primero transforma los datos en una lista.
Error n.º 3: comparación incorrecta de objetos. No restes enteros «a lo bruto» al comparar — puede haber desbordamientos. En lugar de u1.age - u2.age usa Integer.compare o Comparator.comparingInt.
// users.sort((u1, u2) -> u1.age - u2.age); // Funciona, pero es peligroso por desbordamiento.
Error n.º 4: usar contains para búsquedas complejas. El método contains solo comprueba la coincidencia exacta (según equals). Si necesitas buscar por parte de una cadena o por un campo de un objeto — usa un bucle con una condición o comparadores/streams.
GO TO FULL VERSION