Komparátor és összehasonlítható Java-ban
1. Bemutatkozás
A Java-ban történő összehasonlítás meglehetősen egyszerű - amíg nem.
Ha egyéni típusokkal dolgozunk, vagy megpróbáljuk összehasonlítani azokat az objektumokat, amelyek nem közvetlenül összehasonlíthatók, használnunk kell egy összehasonlítási stratégiát. Egyszerűen felépíthetjük, de felhasználva a Összehasonlító vagy Hasonló interfészek.
2. A példa beállítása
Vegyünk egy példát egy futballcsapatra - ahol a játékosokat rangsor szerint akarjuk felsorakoztatni.
Kezdjük egy egyszerű létrehozásával Játékos osztály:
nyilvános osztály Player {private int ranking; privát karakterlánc neve; privát int kor; // kivitelező, getters, setters}
Ezután hozzunk létre egy PlayerSorter osztály létrehozni a gyűjteményünket, és megkísérelni rendezni a felhasználásával Gyűjtemények.rendezés:
public static void main (String [] args) {List footballTeam = new ArrayList (); Player player1 = új játékos (59, "John", 20); Player2 = új játékos (67, "Roger", 22); Player3 = új játékos (45, "Steven", 24); footballTeam.add (player1); footballTeam.add (player2); footballTeam.add (player3); System.out.println ("Rendezés előtt:" + footballTeam); Gyűjtemények.rendezés (footballTeam); System.out.println ("Rendezés után:" + footballTeam); }
A várakozásoknak megfelelően ez fordítási időbeli hibát eredményez:
A Gyűjtemények típusú sort (Lista) a argumentumokra nem lehet alkalmazni (ArrayList)
Értsük meg, mit tettünk itt rosszul.
3. Hasonló
Ahogy a neve is sugallja, Hasonló egy interfész, amely meghatározza az objektum más azonos típusú objektumokkal való összehasonlításának stratégiáját. Ezt hívják az osztály „természetes rendezésének”.
Ennek megfelelően, a rendezéshez - meg kell határoznunk a sajátunkat Játékos objektum, mint összehasonlítható a Hasonló felület:
public class Player megvalósítja a Comparable {// -ot, mint korábban @Orride public int CompareTo (Player otherPlayer) {return Integer.compare (getRanking (), otherPlayer.getRanking ()); }}
A rendezési sorrendet a. Visszatérési értéke határozza meg összehasonlítani()módszer. A Egész. Összehasonlítás (x, y) -1-et ad vissza x kevesebb mint y, 0-t ad vissza, ha egyenlőek, és 1-et ad vissza.
A módszer számot ad vissza, jelezve, hogy az összehasonlítandó objektum kisebb-e, egyenlő vagy nagyobb-e, mint az argumentumként átadott objektum.
Végül, amikor futunk PlayerSorter most láthatjuk a mi Játékosok rangsor szerint rendezve:
Rendezés előtt: [John, Roger, Steven] Rendezés után: [Steven, John, Roger]
Most, hogy világos megértésünk van a természetes rendezésről Hasonló, lássuk hogyan használhatunk más típusú megrendeléseket rugalmasabban mint egy interfész közvetlen megvalósítása.
4. Összehasonlító
A Összehasonlító interfész meghatározza a összehasonlít (arg1, arg2) módszer két argumentummal, amelyek összehasonlított objektumokat képviselnek és hasonlóan működnek, mint a Comparable.compareTo () módszer.
4.1. Teremtés Összehasonlítók
A Összehasonlító, végre kell hajtanunk a Összehasonlító felület.
Első példánkban létrehozunk egy Összehasonlító használni a rangsor attribútuma Játékos a játékosok rendezéséhez:
public class PlayerRankingComparator implementálja a Comparator {@Orride public int összehasonlítás (Player firstPlayer, Player secondPlayer) {return Integer.compare (firstPlayer.getRanking (), secondPlayer.getRanking ()); }}
Hasonlóképpen létrehozhatunk egy Összehasonlító használni a kor attribútuma Játékos a játékosok rendezéséhez:
public class PlayerAgeComparator implementálja a Comparator {@Orride public int Compare (Player firstPlayer, Player secondPlayer) {return Integer.compare (firstPlayer.getAge (), secondPlayer.getAge ()); }}
4.2. Összehasonlítók akcióban
A koncepció bemutatásához módosítsuk PlayerSorter egy második érv bevezetésével a Gyűjtemények.rendezési módszer ami valójában a Összehasonlító használni akarjuk.
Ezzel a megközelítéssel felülírhatjuk a természetes sorrendet:
PlayerRankingComparator playerComparator = új PlayerRankingComparator (); Collections.sort (footballTeam, playerComparator);
Most futtassuk PlayerRankingSorter to lásd az eredményt:
Rendezés előtt: [John, Roger, Steven] Rendezés rangsorolás után: [Steven, John, Roger]
Ha más rendezési sorrendet akarunk, akkor csak a Összehasonlító használjuk:
PlayerAgeComparator playerComparator = új PlayerAgeComparator (); Collections.sort (footballTeam, playerComparator);
Most, amikor futunk PlayerAgeSorter, láthatunk egy másik rendezési sorrendet kor:
Rendezés előtt: [John, Roger, Steven] Kor szerinti rendezés után: [Roger, John, Steven]
4.3. Java 8 Összehasonlítók
A Java 8 új módszereket kínál a meghatározásra Összehasonlítók lambda kifejezések és a összehasonlítás () statikus gyári módszer.
Lássunk egy gyors példát arra, hogyan használhatunk lambda kifejezést a Összehasonlító:
Comparator byRanking = (Player Player1, Player Player2) -> Egész szám.összehasonlítás (player1.getRanking (), player2.getRanking ());
A Összehasonlító.összehasonlítás A metódus elvégzi az elemek összehasonlításához használt tulajdonság kiszámításának módszerét, és egyezést ad vissza Összehasonlító példa:
Comparator byRanking = Összehasonlító .comparing (Player :: getRanking); Comparator byAge = Összehasonlító .összehasonlítás (Player :: getAge);
A Java 8 funkcionalitását a Java 8 Comparator.comparing útmutatóban találja meg alaposan.
5. Összehasonlító vs. Hasonló
A Hasonló Az interfész jó választás az alapértelmezett sorrend meghatározásához vagy más szavakkal, ha ez az objektumok összehasonlításának fő módja.
Ezután fel kell tennünk magunknak a kérdést, miért használjuk az a Összehasonlító ha már megvan Hasonló?
Ennek számos oka van:
- Néha nem tudjuk módosítani annak az osztálynak a forráskódját, amelynek objektumait rendezni szeretnénk, így kihasználva Hasonló lehetetlen
- Használata Összehasonlítók lehetővé teszi számunkra, hogy ne adjunk további kódot a domain osztályainkhoz
- Több különböző összehasonlítási stratégiát határozhatunk meg, amelyek használata nem lehetséges Hasonló
6. Kerülje el a kivonási trükköt
A bemutató során a Integer.compare () módszer két egész szám összehasonlítására. Azt állíthatnánk, hogy ehelyett ezt az okos egybélést kell használnunk:
Összehasonlító összehasonlító = (p1, p2) -> p1.getRanking () - p2.getRanking ();
Bár sokkal tömörebb a többi megoldáshoz képest, a Java egész számának túlcsordulásának áldozata lehet:
Player player1 = új játékos (59, "John", egész szám.MAX_VALUE); Player2 = új játékos (67, "Roger", -1); Játékosok listája = Arrays.asList (player1, player2); játékosok.rendezés (összehasonlító);
Mivel -1 sokkal kisebb, mint a Egész.MAX_VALUE, „Roger” -nek a válogatott gyűjtemény „John” elé kell kerülnie. Az egész szám túlcsordulása miatt azonban a „Egész.MAX_VALUE - (-1)” kevesebb lesz, mint nulla. Tehát a Összehasonlító / összehasonlítható szerződés, az Egész.MAX_VALUE kisebb mint -1, ami nyilvánvalóan helytelen.
Ezért, annak ellenére, amit vártunk, „John” a válogatott gyűjtemény „Roger” elé kerül:
assertEquals ("John", játékosok.get (0) .getName ()); assertEquals ("Roger", játékosok.get (1) .getName ());
7. Következtetés
Ebben az oktatóanyagban a Hasonló és Összehasonlító interfészeket, és megvitatták a közöttük lévő különbségeket.
A válogatás fejlettebb témáinak megértéséhez olvassa el a többi cikkünket, például a Java 8 Comparator, a Java 8 Comparison with Lambdas.
És, mint általában, a forráskód megtalálható a GitHubon.