Komparator, sortering av samlingar - 1

"Hej, Amigo!"

"Hej, Bilaabo!"

"Idag ska vi undersöka ett litet, men intressant och anvÀndbart Àmne: sortering av samlingar."

"Sortera? Jag har hört nÄgot om det."

"LÀnge sedan var varje programmerare tvungen att skriva sorteringsalgoritmer. Kunde och var tvungen att skriva dem. Men den tiden Àr över. Idag anses skriva din egen sorteringskod som dÄlig form, precis som att skriva om allt annat som redan har uppfunnits."

"I Java (och andra programmeringssprĂ„k) Ă€r sortering redan implementerad.  Din uppgift Ă€r att lĂ€ra dig hur man korrekt anvĂ€nder det som redan finns. "

"OK."

" HjĂ€lpklassen Samlingar har en statisk sorteringsmetod som anvĂ€nds för att sortera samlingar – eller mer exakt, listor. Element i kartor och uppsĂ€ttningar har ingen ordning/index, sĂ„ det finns inget att sortera."

"Ja, jag kommer ihÄg. Jag anvÀnde den hÀr metoden en gÄng för att sortera en lista med siffror."

"UtmÀrkt. Men den hÀr metoden Àr mycket kraftfullare Àn den verkar vid första anblicken. Den kan sortera inte bara siffror, utan ocksÄ alla objekt, baserat pÄ vilka kriterier som helst. TvÄ grÀnssnitt hjÀlper metoden att göra detta: Comparable och Comparator . "

"Ibland behöver du sortera objekt, inte siffror. Anta till exempel att du har en lista med personer och att du vill sortera dem efter Älder. Vi har det jÀmförbara grÀnssnittet för detta."

"LÄt mig först visa dig ett exempel, och sedan blir allt tydligare:"

Exempel
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;
}
}
Ett exempel pÄ hur det kan anvÀndas:
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);
}

"För att sortera objekt mÄste du först veta hur du jÀmför dem. För detta anvÀnder vi Comparable. Det jÀmförbara grÀnssnittet Àr ett generiskt, vilket betyder att det accepterar ett typargument. Det har bara en generisk metod: compareTo(T o). Den hÀr metoden jÀmför det aktuella objektet (detta) och ett objekt som skickas som ett argument (o). Med andra ord mÄste vi implementera denna metod i vÄr klass och sedan anvÀnda den för att jÀmföra det aktuella objektet (detta) med det skickade objektet. "

"Och hur fungerar compareTo? Jag förvÀntade mig att det skulle returnera sant eller falskt beroende pÄ om det passerade objektet var större eller mindre."

"Det Àr knepigare hÀr. CompareTo-metoden returnerar inte sant/falskt. IstÀllet returnerar den en int. Detta görs faktiskt för enkelhetens skull.

"NÀr en dator behöver avgöra om ett tal Àr större Àn ett annat, subtraherar den helt enkelt det andra talet frÄn det första och tittar sedan pÄ resultatet. Om resultatet Àr 0, sÄ Àr siffrorna lika. Om resultatet Àr mindre Àn noll , dÄ Àr det andra talet större. Och om resultatet Àr större Àn noll, Àr det första talet större."

"Samma logik gÀller hÀr. Enligt specifikationen mÄste compareTo-metoden returnera noll om de jÀmförda objekten Àr lika. Om compareTo-metoden returnerar ett tal större Àn noll, sÄ Àr vÄrt objekt större Àn det godkÀnda objektet. "Om compareTo metod returnerar ett tal mindre Àn noll, dÄ Àr 'detta' mindre Àn det skickade objektet."

"Det Àr lite konstigt."

"Ja, men om du jÀmför objekt helt enkelt baserat pÄ nÄgon numerisk egenskap, sÄ kan du bara returnera skillnaden mellan dem genom att subtrahera det ena frÄn det andra. Precis som det gjordes i exemplet ovan."

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

"Jag tror att jag förstÄr allt. Men kanske inte. Men nÀstan allt."

"Bra. LÄt oss nu övervÀga ett mer praktiskt problem. Anta att du har skrivit en cool webbplats för att tillverka damklÀder i Kina. Du anvÀnder en kvinnoklass för att beskriva dina kunder. Du har till och med skapat en webbsida med en tabell dÀr du kan se dem alla . Men det finns ett problem..."

"Ditt Woman-objekt innehÄller inte bara en Älder, utan ocksÄ en hel massa andra data: förnamn, efternamn, lÀngd, vikt, antal barn, etc."

"Tabellen över anvÀndare har mÄnga kolumner, och hÀr Àr frÄgan: hur sorterar du dina anvÀndare efter de olika kriterierna? Efter vikt, Älder, efternamn?"

"Hmm. Ja, jag ser ofta tabeller som lÄter dig sortera efter kolumn. SÄ, hur gör man det?"

"För detta har vi det andra grÀnssnittet jag ville berÀtta om idag: Comparator-grÀnssnittet. Det har ocksÄ en jÀmförelsemetod, men det tar tvÄ argument, inte ett: int compare(T o1, T o2). SÄ hÀr Arbetar:"

Exempel
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;
}
}
Ett exempel pÄ hur det kan anvÀndas:
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);
}

"JÀmförelsegrÀnssnittet döljer inte logiken för objektjÀmförelse i klassen för de objekt som jÀmförs. IstÀllet implementeras den i en separat klass."

"SÄ, jag skulle kunna skapa flera klasser som implementerar grÀnssnittet Comparator och lÄta var och en av dem jÀmföra olika egenskaper? Vikt i en, Älder i en annan och höjd i en tredje?"

"Ja, det Àr vÀldigt enkelt och bekvÀmt."

"Vi anropar bara metoden Collections.sort , och skickar en lista med objekt och ett annat specialobjekt som det andra argumentet, vilket implementerar grÀnssnittet Comparator och talar om för dig hur du korrekt jÀmför objektpar i sorteringsprocessen."

"Hmm. Jag tror att jag förstÄr allt. LÄt mig prova. LÄt oss sÀga att jag mÄste sortera anvÀndare efter vikt. Det skulle vara ungefÀr sÄ hÀr:"

Exempel pÄ att sortera anvÀndare efter vikt:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

"Ja exakt."

"JÀttebra. Men tÀnk om jag vill sortera i omvÀnd ordning?"

"TÀnk pÄ det. Svaret Àr vÀldigt enkelt!"

"Jag har det! SÄ hÀr:"

Sortering i stigande ordning:
return o1.weight - o2.weight;
Sortering i fallande ordning:
return o2.weight – o1.weight;

"RĂ€tt. Bra gjort."

"Och om jag vill sortera efter efternamn? Hur sorterar jag strÀngar, Bilaabo?"

"Klassen String implementerar redan compareTo-metoden. Du behöver bara kalla den:"

Exempel pÄ att sortera anvÀndare efter namn:
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 bra lektion, Bilaabo. Tack sÄ mycket."

"Och tack till dig, min vÀn!"