1. Ricerca di elementi nelle collezioni
Ricerca con i metodi standard
Quando abbiamo una lista, ad esempio di nomi:
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
Java offre alcuni metodi comodi per la ricerca:
- contains(Object o) — verifica se l'elemento è presente nella raccolta.
- indexOf(Object o) — restituisce il primo indice di occorrenza dell'elemento (oppure -1, se non trovato).
- lastIndexOf(Object o) — restituisce l'ultimo indice di occorrenza dell'elemento (oppure -1).
Esempi:
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
Fatto: Per le raccolte di tipo Set non esistono i metodi indexOf e lastIndexOf — in un Set non ci sono indici, solo valori unici.
Ricerca per condizione
A volte serve trovare non un valore specifico, ma un elemento che soddisfa una condizione. Per esempio, trovare il primo nome più lungo di 6 caratteri. Un normale ciclo for va benissimo: non appena trovi l'elemento giusto — 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; // Trovato il primo idoneo, si può uscire dal ciclo
}
}
System.out.println(found); // Viktoriya
Ricerca del valore massimo e minimo
Per le collezioni con elementi confrontabili (ad esempio, numeri) si possono trovare rapidamente massimo e minimo con la classe 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("Massimo: " + max);
System.out.println("Minimo: " + min);
Importante: Gli elementi devono essere confrontabili (implementare Comparable), altrimenti occorre passare un comparator.
2. Ordinamento delle collezioni
Ordinamento predefinito di una lista
Si possono ordinare solo le liste mutabili (per esempio, ArrayList, LinkedList). Le raccolte di tipo Set e Map non supportano l'ordinamento direttamente.
Per impostazione predefinita l'ordinamento segue l'«ordine naturale»: per i numeri — crescente, per le stringhe — alfabetico.
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
Si può fare lo stesso tramite il metodo della lista sort:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null significa: usare l'ordine naturale
System.out.println(numbers); // [1, 3, 5, 7]
Ordinamento con un Comparator
Se serve una regola propria — per esempio, ordinare le stringhe per lunghezza:
List<String> words = new ArrayList<>(List.of("kot", "slon", "mukha", "nosorog"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [kot, slon, mukha, nosorog]
In ordine inverso:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [nosorog, mukha, slon, kot]
Stile vecchio tramite Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. Particolarità dell'ordinamento delle diverse collezioni
L'ordinamento modifica solo la lista
I metodi di ordinamento (sort, Collections.sort) funzionano solo con collezioni che supportano l'ordine degli elementi (ad esempio, List). Per Set e Map tali metodi non sono previsti.
Tentativo di ordinare un Set:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // Errore di compilazione: sort si aspetta List!
Se serve ottenere una lista ordinata da Set:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
Ordinare una Map: per chiavi e per valori
Non si può ordinare Map direttamente, ma si può:
- Ottenere una lista di coppie «chiave-valore»
- Ordinarla come serve
- Se necessario, costruire una nuova Map
Esempio: ordinamento per valori
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
Ordinamento di oggetti per campo
Supponiamo di avere una classe utente:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
E una lista di utenti:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Boris", 18),
new User("Vika", 25)
));
Ordiniamo per età:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Boris (18), Anna (22), Vika (25)]
In ordine inverso:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Vika (25), Anna (22), Boris (18)]
4. Errori tipici nella ricerca e nell'ordinamento delle collezioni
Errore n. 1: ordinare una lista immutabile. Le liste create con List.of(...) non si possono modificare — chiamando sort otterrete UnsupportedOperationException.
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // Solleverà un'eccezione!
Errore n. 2: ordinare direttamente Set o Map. I metodi di ordinamento non funzionano con Set e Map. Se serve ordinare, trasformate prima i dati in una lista.
Errore n. 3: confronto scorretto degli oggetti. Non sottraete gli interi nel confronto — si possono avere overflow. Invece di u1.age - u2.age usate Integer.compare o Comparator.comparingInt.
// users.sort((u1, u2) -> u1.age - u2.age); // Funziona, ma è pericoloso in caso di overflow!
Errore n. 4: usare contains per una ricerca complessa. Il metodo contains verifica solo la corrispondenza completa (tramite equals). Se serve cercare per sottostringa o per un campo dell'oggetto — usate un ciclo con una condizione oppure comparatori/stream.
GO TO FULL VERSION