Comparable og Comparator er interfaces som lar deg bestemme hvordan dine egne objekter skal rangeres i forhold til hverandre. Dette kommer spesielt godt til nytte når man bruker Collection-rammeverket, spesielt metoden Collections.sort.
Comparable<T>
Comparable er det vanlig at klassen din implementerer. Den krever at du har definert metoden .compareTo(T), hvor T er klassen som skal sammenlignes. CompareTo metoden skal returnere et Negativt tall hvis "this" er mindre enn det andre instanse. 0 hvis de er like, og et positivt tall dersom "this" er større enn det andre instanset.
Sett at du har en klasse som definerer et Land som deltar i OL. Klassen har felter for antall gull, sølv og bronsje. For at du skal kunne avgjøre hvilket land som kommer høyest opp på medalje rangeringen trenger man en metode for å avgjøre dette.
public class OlympicCountry implements Comparable<OlympicCountry> { //inne i klammene defineres hvilken klasse som skal sammenlignes i compareTo-metoden private String name; private int goldMedals; private int silverMedals; private int bronzeMedals; public OlympicCountry(String name, int goldMedals, int silverMedals, int bronzeMedals){ this.name = name; this.goldMedals = goldMedals; this.silverMedals = silverMedals; this.bronzeMedals = bronzeMedals; } public int getGoldMedals() { return goldMedals; } public int getSilverMedals() { return silverMedals; } public int getBronzeMedals() { return bronzeMedals; } @Override public String toString(){ return name + "\t: g: "+ goldMedals+", s: " + silverMedals + ", b: " + bronzeMedals; } //@Override public int compareTo(OlympicCountry o) { if(this.getGoldMedals() != o.getGoldMedals()) // hvis guld er ulike returnerer deres forskjell return this.getGoldMedals() - o.getGoldMedals(); else if(this.getSilverMedals() != o.getSilverMedals())//hvis sølv er ulike returneres deres forskjell return this.getSilverMedals() - o.getSilverMedals(); else return this.getBronzeMedals() - o.getBronzeMedals(); // hvis den er kommet hit er guld og sølv like, da returnerer den bronsje forskjellen. Om den også er lik returneres 0, som indikerer at instansene er like gode. } public static void main(String[] args) { OlympicCountry china = new OlympicCountry("China", 2, 4, 1); OlympicCountry japan = new OlympicCountry("Japan", 2, 5, 1); System.out.println(china.compareTo(Japan)); // printer ut -1. Dette betyr at Japan er bedre enn Kina. }
Så hvorfor er dette så fantastisk. Jo, som nevnt over så kan man bruke det i forbindelse med sortering. Collections.sort() krever bare at du sender med en liste som arver fra Collections og at denne listen inneholder et objekt som implementerer Comparable-interfacet.
Her ser dere en ny main-metode som bruker den allerede definerte klassen over OlympicCountry
public static void main(String[] args) { ArrayList<OlympicCountry> countries = new ArrayList<OlympicCountry>(); countries.add(new OlympicCountry("Norway", 5, 3, 7)); countries.add(new OlympicCountry("Sweden", 2, 9, 3)); countries.add(new OlympicCountry("Finland", 9, 2, 1)); countries.add(new OlympicCountry("Russia", 2, 9, 12)); countries.add(new OlympicCountry("Denmark", 7, 1, 6)); countries.add(new OlympicCountry("England", 5, 2, 10)); countries.add(new OlympicCountry("Canada", 5, 0, 4)); countries.add(new OlympicCountry("USA", 9, 2, 2)); print(countries); /* Printer ut: Norway : g: 5, s: 3, b: 7 Sweden : g: 2, s: 9, b: 3 Finland : g: 9, s: 2, b: 1 Russia : g: 2, s: 9, b: 12 Denmark : g: 7, s: 1, b: 6 England : g: 5, s: 2, b: 10 Canada : g: 5, s: 0, b: 4 USA : g: 9, s: 2, b: 2 Altså usortert, men ettersom klassen vår implementerer Comparable kan vi nå sortere instansene slik vi ønsker. */ Collections.sort(countries); print(countries); /* Sweden : g: 2, s: 9, b: 3 Russia : g: 2, s: 9, b: 12 Canada : g: 5, s: 0, b: 4 England : g: 5, s: 2, b: 10 Norway : g: 5, s: 3, b: 7 Denmark : g: 7, s: 1, b: 6 Finland : g: 9, s: 2, b: 1 USA : g: 9, s: 2, b: 2 Nå kan dere se at listen er sortert, men den er fortsatt ikke slik vi ønsker den, selvom compartTo klassen er helt rett. Les neste avsnitt for løsningen. } //for oversiktelig utskrift av ArrayListen public static void print(ArrayList<OlympicCountry> countries){ for (OlympicCountry country : countries) { System.out.println(country); } }
Comparator
Problemet over er at sorteringsalgoritmen automatisk sorterer i stigende rekkefølge. En enkel fiks ville vært å bytte om på objektene i compareTo()-metoden, men dette ville vært feil ettersom Comparable skal gjenspeile klassens naturlige ordning, og kan derfor ikke tilpasses for et spesielt problem. Løsningen er å bruke en Comparator. I motsetning til Comparable , så er Comparator tiltenkt å implementeres av en annen klasse enn den som skal sorteres. Den kan da også ha friere regler på utfallet av sammenligninger. For å bruke en comparator sendes den enkelt med som et andre argument til Collections.sort() kallet.
Sidetype | Ferdig |
---|---|
Teori | 50 |