Comparator è un’Interfaccia funzionale che definisce un criterio di ordinamento esterno a una classe, permettendo di confrontare due oggetti distinti senza che questi implementino Comparable. Permette di ordinare collezioni o array, passando il comparatore a metodi come Collections.sort() o ai costruttori di strutture dati ordinate (es. TreeSet, TreeMap).

Package: java.util


CARATTERISTICHE PRINCIPALI

  • Ordinamento esterno: A differenza di Comparable, non richiede di modificare la classe degli oggetti da ordinare.
  • Più criteri: È possibile definire diversi comparatori per lo stesso tipo di oggetto, cambiando il criterio di ordinamento a seconda delle necessità.
  • Interfaccia funzionale: Ha un solo metodo astratto (compare) ed è quindi compatibile con espressioni lambda e reference a metodi.
  • Utilizzo con collezioni: Può essere passato ai costruttori di collezioni ordinate (ad esempio TreeSet) per determinare l’ordine degli elementi.

METODI PRINCIPALI

MetodoDescrizione
compare(T o1, T o2)Metodo base per confrontare due oggetti
equals(Object obj)Verifica di uguaglianza dei comparatori
comparing(...)Crea un comparatore da una chiave
comparing(...) (con comparator di chiave)Permette compare personalizzato della chiave
reverseOrder()Ordine naturale inverso
nullsFirst(...)null ordinati per primi
nullsLast(...)null ordinati per ultimi
reversed()Inverte l’ordine di un comparatore esistente
thenComparing(...)Aggiunge criteri di ordinamento secondari

ESEMPIO

Classe Persona:

import java.util.*;
 
class Persona {
    String nome;
    int eta;
 
    Persona(String nome, int eta) {
        this.nome = nome;
        this.eta = eta;
    }
 
    public String getNome() {
        return nome;
    }
 
    public int getEta() {
        return eta;
    }
 
    @Override
    public String toString() {
        return nome + " (" + eta + ")";
    }
}

Main:

public class Main {
    public static void main(String[] args) {
        List<Persona> persone = Arrays.asList(
            new Persona("Giulio", 20),
            new Persona("Simone", 15),
            new Persona("Andrea", 25),
            new Persona("Simone", 30)
        );
 
        // Ordinamento per età crescente
        persone.sort(Comparator.comparing(Persona::getEta));
        System.out.println("Età crescente: " + persone);
 
        // Ordinamento per età decrescente (reverseOrder)
        persone.sort(Comparator.comparing(Persona::getEta).reversed());
        System.out.println("Età decrescente: " + persone);
 
        // Ordinamento per nome alfabetico
        persone.sort(Comparator.comparing(Persona::getNome));
        System.out.println("Nome crescente: " + persone);
 
        // Ordinamento per nome alfabetico ignorando maiuscole/minuscole
        persone.sort(Comparator.comparing(
	        Persona::getNome, String.CASE_INSENSITIVE_ORDER));
        System.out.println("Nome (case-insensitive): " + persone);
 
        // Ordinamento per nome, poi per età se i nomi sono uguali
        persone.sort(
            Comparator.comparing(Persona::getNome)
                      .thenComparing(Persona::getEta)
        );
        System.out.println("Nome, poi età: " + persone);
    }
}

Output:

Età crescente: [Simone (15), Giulio (20), Andrea (25), Simone (30)]
Età decrescente: [Simone (30), Andrea (25), Giulio (20), Simone (15)]
Nome crescente: [Andrea (25), Giulio (20), Simone (15), Simone (30)]
Nome (case-insensitive): [Andrea (25), Giulio (20), Simone (15), Simone (30)]
Nome, poi età: [Andrea (25), Giulio (20), Simone (15), Simone (30)]