Komparator, sortering af samlinger - 1

"Hej, Amigo!"

"Hej, Bilaabo!"

"I dag vil vi undersøge et lille, men interessant og nyttigt emne: sortering af samlinger."

"Sortering? Det har jeg hørt noget om."

"Længe siden skulle enhver programmør være i stand til at skrive sorteringsalgoritmer. Kunne og måtte skrive dem. Men de dage er forbi. I dag betragtes det at skrive sin egen sorteringskode som dårlig form, ligesom at omskrive alt andet, der allerede har blevet opfundet."

"I Java (og andre programmeringssprog) er sortering allerede implementeret.  Din opgave er at lære, hvordan man korrekt bruger det, der allerede eksisterer. "

"OKAY."

" Samlinger- hjælperklassen har en statisk sorteringsmetode, der bruges til at sortere samlinger – eller mere præcist lister. Elementer i Maps og Sets har ikke en rækkefølge/indeks, så der er ikke noget at sortere."

"Ja, det kan jeg huske. Jeg brugte denne metode en gang til at sortere en liste over tal."

"Fantastisk. Men denne metode er meget mere kraftfuld, end den ser ud ved første øjekast. Den kan sortere ikke kun tal, men også alle objekter, baseret på et hvilket som helst kriterium. To grænseflader hjælper metoden med at gøre dette: Comparable og Comparator . "

"Nogle gange har du brug for at sortere objekter, ikke tal. Antag for eksempel, at du har en liste over personer, og du vil sortere dem efter alder. Vi har den sammenlignelige grænseflade til dette."

"Lad mig først vise dig et eksempel, og så bliver alt tydeligere:"

Eksempel
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;
}
}
Et eksempel på hvordan det kan bruges:
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);
}

"For at sortere objekter skal du først vide, hvordan du sammenligner dem. Til dette bruger vi Comparable. Comparable- grænsefladen er en generisk, hvilket betyder, at den accepterer et type-argument. Den har kun én generisk metode: compareTo(T o). Denne metode sammenligner det aktuelle objekt (dette) og et objekt sendt som et argument (o). Med andre ord skal vi implementere denne metode i vores klasse og derefter bruge den til at sammenligne det aktuelle objekt (dette) med det beståede objekt. "

"Og hvordan fungerer compareTo? Jeg forventede, at det ville returnere sandt eller falsk afhængigt af, om det passerede objekt var større eller mindre."

"Tingene er sværere her. CompareTo-metoden returnerer ikke sand/falsk. I stedet returnerer den en int. Dette er faktisk gjort for nemheds skyld.

"Når en computer skal afgøre, om et tal er større end et andet, trækker den simpelthen det andet tal fra det første og ser derefter på resultatet. Hvis resultatet er 0, så er tallene ens. Hvis resultatet er mindre end nul , så er det andet tal større. Og hvis resultatet er større end nul, så er det første tal større."

"Den samme logik gælder her. Ifølge specifikationen skal compareTo-metoden returnere nul, hvis de sammenlignede objekter er ens. Hvis compareTo-metoden returnerer et tal større end nul, så er vores objekt større end det beståede objekt. "Hvis compareTo-metoden metoden returnerer et tal mindre end nul, så er 'dette' mindre end det beståede objekt."

"Det er lidt underligt."

"Ja, men hvis du sammenligner objekter blot baseret på en numerisk egenskab, så kan du bare returnere forskellen mellem dem ved at trække den ene fra den anden. Ligesom det blev gjort i eksemplet ovenfor."

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

"Jeg tror, ​​jeg forstår alt. Men måske ikke. Men næsten alt."

"Fint. Lad os nu overveje et mere praktisk problem. Antag, at du har skrevet en fed hjemmeside til fremstilling af dametøj i Kina. Du bruger en kvindeklasse til at beskrive dine kunder. Du har endda lavet en webside med en tabel, hvor du kan se dem alle sammen . Men der er et problem..."

"Dit Woman-objekt indeholder ikke kun en alder, men også en hel masse andre data: fornavn, efternavn, højde, vægt, antal børn osv."

"Tabellen over brugere har masser af kolonner, og her er spørgsmålet: hvordan sorterer du dine brugere efter de forskellige kriterier? Efter vægt, efter alder, efter efternavn?"

"Hmm. Ja, jeg ser ofte tabeller, der lader dig sortere efter kolonne. Så hvordan gør du det?"

"Til dette har vi den anden grænseflade, jeg ville fortælle dig om i dag: Comparator-grænsefladen. Den har også en sammenligningsmetode, men den kræver to argumenter, ikke ét: int compare(T o1, T o2). Sådan kan det arbejder:"

Eksempel
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;
}
}
Et eksempel på hvordan det kan bruges:
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);
}

"Comparator-grænsefladen skjuler ikke objektsammenligningslogikken inde i klassen for de objekter, der sammenlignes. I stedet implementeres den i en separat klasse."

"Så jeg kunne lave flere klasser, der implementerer Comparator-grænsefladen og få hver af dem til at sammenligne forskellige egenskaber? Vægt i en, alder i en anden og højde i en tredje?"

"Ja, det er meget enkelt og bekvemt."

"Vi kalder bare Collections.sort- metoden og sender en liste over objekter og et andet specielt objekt som det andet argument, som implementerer Comparator- grænsefladen og fortæller dig, hvordan du korrekt sammenligner par af objekter i sorteringsprocessen."

"Hmm. Jeg tror, ​​jeg forstår alt. Lad mig prøve det. Lad os sige, at jeg skal sortere brugere efter vægt. Det ville være sådan her:"

Eksempel på sortering af brugere efter vægt:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Ja præcis."

"Fint. Men hvad nu hvis jeg vil sortere i omvendt rækkefølge?"

"Tænk over det. Svaret er meget enkelt!"

"Jeg har det! Sådan her:"

Sortering i stigende rækkefølge:
return o1.weight - o2.weight;
Sortering i faldende rækkefølge:
return o2.weight – o1.weight;

"Godt. Godt gået."

"Og hvis jeg vil sortere efter efternavn? Hvordan sorterer jeg strenge, Bilaabo?"

"String-klassen implementerer allerede compareTo-metoden. Du skal bare kalde den:"

Eksempel på sortering af brugere efter navn:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

"Det var en stor lektion, Bilaabo. Mange tak."

"Og tak til dig, min ven!"