Comparatore, raccolta di ordinamento - 1

"Ciao, Amico!"

"Ciao Bilaabo!"

"Oggi esamineremo un argomento piccolo, ma interessante e utile: l'ordinamento delle raccolte."

"Smistamento? Ne ho sentito parlare."

"Molto tempo fa, ogni programmatore doveva essere in grado di scrivere algoritmi di ordinamento. Poteva e doveva scriverli. Ma quei giorni sono finiti. Oggi, scrivere il proprio codice di ordinamento è considerato una cattiva forma, proprio come riscrivere qualsiasi altra cosa che ha già stato inventato».

"In Java (e altri linguaggi di programmazione), l'ordinamento è già implementato.  Il tuo compito è imparare a utilizzare correttamente ciò che già esiste. "

"OK."

"La classe helper Collections ha un metodo di ordinamento statico che viene utilizzato per ordinare le raccolte o, più precisamente, gli elenchi. Gli elementi in Maps and Sets non hanno un ordine/indice, quindi non c'è nulla da ordinare."

"Sì, mi ricordo. Ho usato questo metodo una volta per ordinare un elenco di numeri."

"Fantastico. Ma questo metodo è molto più potente di quanto sembri a prima vista. Può ordinare non solo numeri, ma anche qualsiasi oggetto, in base a qualsiasi criterio. Due interfacce aiutano il metodo a farlo: Comparable e Comparator . "

"A volte devi ordinare oggetti, non numeri. Ad esempio, supponi di avere un elenco di persone e di volerle ordinare per età. Abbiamo l' interfaccia Comparable per questo."

"Lascia che ti mostri prima un esempio, e poi tutto diventerà più chiaro:"

Esempio
public class Woman implements Comparable<Woman>
{
public int age;

public Woman(int age) {
this.age = age;
}

public int compareTo(Woman o)
{
return this.age - o.age;
}
}
Un esempio di come potrebbe essere utilizzato:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Collections.sort(women);
}

"Per ordinare gli oggetti, devi prima sapere come confrontarli. Per questo, usiamo Comparable. L' interfaccia Comparable è generica, il che significa che accetta un argomento di tipo. Ha un solo metodo generico: compareTo(T o). Questo metodo confronta l'oggetto corrente (this) e un oggetto passato come argomento (o).In altre parole, dobbiamo implementare questo metodo nella nostra classe e poi usarlo per confrontare l'oggetto corrente (this) con l'oggetto passato. "

"E come funziona compareTo? Mi aspettavo che restituisse vero o falso a seconda che l'oggetto passato fosse maggiore o minore."

"Le cose sono più complicate qui. Il metodo compareTo non restituisce true/false. Invece, restituisce un int. Questo in realtà è fatto per semplicità.

"Quando un computer deve determinare se un numero è maggiore di un altro, semplicemente sottrae il secondo numero dal primo e poi guarda il risultato. Se il risultato è 0, allora i numeri sono uguali. Se il risultato è minore di zero , allora il secondo numero è maggiore. E se il risultato è maggiore di zero, allora il primo numero è maggiore."

"La stessa logica si applica qui. Secondo la specifica, il metodo compareTo deve restituire zero se gli oggetti confrontati sono uguali. Se il metodo compareTo restituisce un numero maggiore di zero, allora il nostro oggetto è maggiore dell'oggetto passato. "Se il metodo compareTo restituisce metodo restituisce un numero minore di zero, quindi 'questo' è minore dell'oggetto passato."

"È un po' strano."

"Sì, ma se stai confrontando oggetti semplicemente basandoti su qualche proprietà numerica, allora puoi semplicemente restituire la differenza tra loro sottraendo l'uno dall'altro. Proprio come è stato fatto nell'esempio sopra."

public int compareTo(Woman o)
{
return this.age - o.age;
}

"Credo di capire tutto. Ma forse no. Ma quasi tutto."

"Fantastico. Ora consideriamo un problema più pratico. Supponiamo che tu abbia scritto un bel sito web per fare abbigliamento femminile in Cina. Utilizzi una classe Donna per descrivere i tuoi clienti. Hai persino creato una pagina web con una tabella dove puoi vederli tutti . Ma c'è un problema…”

"Il tuo oggetto Donna contiene non solo un'età, ma anche tutta una serie di altri dati: nome, cognome, altezza, peso, numero di figli, ecc."

"La tabella degli utenti ha molte colonne, ed ecco la domanda: come ordini i tuoi utenti in base ai vari criteri? Per peso, per età, per cognome?"

"Hmm. Sì, vedo spesso tabelle che ti permettono di ordinare per colonna. Quindi, come si fa?"

"Per questo, abbiamo la seconda interfaccia di cui volevo parlarvi oggi: l'interfaccia Comparator. Ha anche un metodo di confronto, ma richiede due argomenti, non uno: int compare(T o1, T o2). Ecco come funziona lavori:"

Esempio
public class Woman
{
public int age;
public int childrenCount;
public int weight;
public int height;
public String name;

public Woman(int age) {
this.age = age;
}
}
Un esempio di come potrebbe essere utilizzato:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Comparator<Woman> compareByHeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.height - o2.height;
}
};

Collections.sort(women, compareByHeight);
}

"L'interfaccia Comparator non nasconde la logica di confronto degli oggetti all'interno della classe degli oggetti confrontati. Invece, è implementata in una classe separata."

"Quindi, potrei creare diverse classi che implementano l'interfaccia Comparator e fare in modo che ciascuna di esse confronti proprietà diverse? Peso in una, età in un'altra e altezza in una terza?"

"Sì, è molto semplice e conveniente."

"Chiamiamo semplicemente il metodo Collections.sort , passando un elenco di oggetti e un altro oggetto speciale come secondo argomento, che implementa l' interfaccia Comparator e ti dice come confrontare correttamente le coppie di oggetti nel processo di ordinamento."

"Hmm. Penso di capire tutto. Fammi fare un tentativo. Diciamo che devo ordinare gli utenti in base al peso. Sarebbe qualcosa del genere:"

Esempio di ordinamento degli utenti in base al peso:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Si, esattamente."

"Fantastico. Ma se volessi riordinare in ordine inverso?"

"Pensaci. La risposta è molto semplice!"

"Ce l'ho! In questo modo:"

Ordinamento in ordine crescente:
return o1.weight - o2.weight;
Ordinamento in ordine decrescente:
return o2.weight – o1.weight;

"Giusto. Ben fatto."

"E se voglio ordinare per cognome? Come faccio a ordinare le stringhe, Bilaabo?"

"La classe String implementa già il metodo compareTo. Devi solo chiamarlo:"

Esempio di ordinamento degli utenti per nome:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

"È stata una grande lezione, Bilaabo. Grazie mille."

"E grazie a te, amico mio!"