CodeGym /Corsi /JAVA 25 SELF /Filtraggio degli elementi delle collezioni

Filtraggio degli elementi delle collezioni

JAVA 25 SELF
Livello 28 , Lezione 0
Disponibile

1. Introduzione

Nella programmazione ci troviamo continuamente nella situazione in cui, da un grande insieme di dati, occorre selezionare solo gli elementi necessari — questo è il filtraggio. Volete mantenere solo i numeri pari, trovare le stringhe che contengono la parola "Java", oppure selezionare gli utenti con più di 18 anni — tutto ciò sono compiti di filtraggio.

In Java operazioni di questo tipo sono ovunque; è quindi importante padroneggiare con sicurezza i diversi modi di eseguirle e capirne le peculiarità.

2. Filtraggio con il ciclo

Cominciamo dal metodo più basilare — il normale ciclo for. Questo approccio è detto imperativo perché si specifica esplicitamente cosa fare e come farlo. È ben leggibile e semplice da comprendere.

Esempio: mantenere solo i numeri pari

import java.util.*;

public class FilterExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> evenNumbers = new ArrayList<>(); // Creiamo una nuova lista per il risultato

        for (Integer n : numbers) {
            if (n % 2 == 0) { // Verifichiamo la condizione: numero pari
                evenNumbers.add(n);
            }
        }

        System.out.println("Numeri pari: " + evenNumbers);
    }
}

Risultato:

Numeri pari: [2, 4, 6, 8, 10]

È importante ricordare che la collezione originaria (numbers) non cambia. Formiamo una nuova lista risultato.

Esempio: filtrare le stringhe per sottostringa

List<String> words = Arrays.asList("java", "python", "javascript", "kotlin", "c++");
List<String> javaWords = new ArrayList<>();

for (String word : words) {
    if (word.contains("java")) {
        javaWords.add(word);
    }
}
System.out.println(javaWords); // [java, javascript]

Stesso principio: percorriamo la lista di stringhe e verifichiamo la presenza della sottostringa con il metodo contains.

3. Rimozione di elementi da una collezione: perché non è così semplice?

Qual è l'insidia?

A volte si vuole eliminare dalla collezione originaria tutti gli elementi superflui. Ma se si prova a farlo durante l'iterazione in un ciclo for-each, si ottiene l'eccezione ConcurrentModificationException.

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));

for (Integer n : numbers) {
    if (n < 0) {
        numbers.remove(n); // PERICOLOSO! ConcurrentModificationException!
    }
}

Risultato:

Exception in thread "main" java.util.ConcurrentModificationException

Le collezioni «non gradiscono» essere modificate durante questo tipo di iterazione — l'iterazione si interrompe.

Come rimuovere correttamente elementi da una collezione?

Metodo 1: usare Iterator.remove()

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));

Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
    Integer n = it.next();
    if (n < 0) {
        it.remove(); // Rimozione sicura!
    }
}
System.out.println(numbers); // [1, 3, 5]

Qui creiamo un iteratore con il metodo iterator(), percorriamo la collezione tramite hasNext() e next(), e rimuoviamo gli elementi indesiderati chiamando it.remove().

Metodo 2: creare una nuova lista solo con gli elementi necessari

List<Integer> numbers = Arrays.asList(1, -2, 3, -4, 5);
List<Integer> positive = new ArrayList<>();

for (Integer n : numbers) {
    if (n >= 0) {
        positive.add(n);
    }
}
System.out.println(positive); // [1, 3, 5]

Non tocchiamo la collezione originaria e costruiamo una nuova lista. L'approccio è sicuro, chiaro e si estende facilmente al crescere della complessità delle condizioni.

Metodo 3: usare removeIf (Java 8+)

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, -2, 3, -4, 5));
numbers.removeIf(n -> n < 0);
System.out.println(numbers); // [1, 3, 5]

Con una sola riga passiamo la condizione: «rimuovi tutto ciò che è minore di zero». I dettagli interni della modifica sicura sono gestiti dalla collezione.

In sintesi: per rimuovere elementi non utilizzare for-each. Scegli tra Iterator.remove(), la creazione di una nuova lista o il conciso removeIf.

4. Quando usare quale metodo per il filtraggio?

L'approccio imperativo tramite un ciclo normale è comodo quando non solo devi selezionare gli elementi, ma vuoi anche farci subito qualcosa (ad esempio stamparli o trasformarli). È semplice e trasparente.

Se si tratta proprio di rimuovere dalla collezione originaria, evita di farlo dentro for-each. Usa Iterator.remove() per un controllo passo passo oppure il moderno removeIf() — il modo più breve ed espressivo.

Esempio: c'è una lista di parole, bisogna eliminare tutte le parole più corte di quattro caratteri:

List<String> words = new ArrayList<>(Arrays.asList("Java", "is", "fun", "awesome", "code"));
words.removeIf(word -> word.length() < 4);
System.out.println(words); // [Java, awesome, code]

Il metodo removeIf accetta un predicato — una regola di filtraggio — e rimuove tutto ciò che vi corrisponde.

5. Errori tipici nel filtraggio delle collezioni

Errore n. 1: tentare di rimuovere elementi dalla collezione in un ciclo for-each.
Un codice del genere porterà a ConcurrentModificationException:

for (Integer n : numbers) {
    if (n < 0) {
        numbers.remove(n); // BOOM! ConcurrentModificationException
    }
}

Alternative corrette: usa Iterator.remove() oppure removeIf.

Errore n. 2: condizione di filtraggio formulata in modo errato.
Bisogna rimuovere solo i numeri negativi:

List<Integer> numbers = new ArrayList<>(Arrays.asList(-3, -1, 0, 2, 4));
numbers.removeIf(n -> n < 0);
System.out.println(numbers); // [0, 2, 4]

Ma se per errore si scrivono i «non positivi» e si usa <=, sparirà anche lo zero:

numbers.removeIf(n -> n <= 0); // Risultato: [2, 4] — lo zero è stato rimosso per errore

Presta attenzione alla precisione delle condizioni: un solo confronto errato cambia completamente il risultato.

1
Compito
JAVA 25 SELF, livello 28, lezione 0
Bloccato
Pulizia dei fascicoli degli agenti dalle informazioni "negative" 🕵️‍♀️
Pulizia dei fascicoli degli agenti dalle informazioni "negative" 🕵️‍♀️
1
Compito
JAVA 25 SELF, livello 28, lezione 0
Bloccato
Ordiniamo i nomi degli animali per la nuova enciclopedia 🦒
Ordiniamo i nomi degli animali per la nuova enciclopedia 🦒
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION