Gyakorlati alapok III.

A Comparable interfész (objektumok alapértelmezett rendezése)


Az előző fejezetek némelyikében felhasználtunk olyan algoritmust is, amelyik az objektum rendezéséért volt felelős. Ebben a fejezetben azt vizsgáljuk meg, hogy a Java-rendszer miképpen valósítja ezt meg egységes keretek között!

 

A programozás-technikai trükk nagyon egyszerű:

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

alapértelmezésben mindegyik kollekció megvalósítja a Comparable interfészt, amelyik egyrészről tartalmazza a legáltalánosabb rendezési algoritmusokat, másrészről biztosít bizonyos rendezési szempontokat is.

 

Mit értünk az utóbbi alatt? Nyilvánvalóan más rendezési szempont alá tartozik egy Integer és egy String típus. A Comparable interfész felismeri ezt és az objektumot egy alapértelmezett sorrend szerint képes rendezni. Ez a beépített sorrend a következő:

Rendezési varázsigénk pedig a következő:

 

Collections.sort(obj);

 

Ezután nincs más hátra, mint a fentieket leellenőrizzük egy List objektumon keresztül! Először vizsgáljunk meg egy Integer típusú objektumot! Az elemeket rendezetlenül adagoljuk az objektumba:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<Integer> lista = new ArrayList<Integer>();
    lista.add(23);   

    lista.add(11);
    lista.add(53);

    lista.add(41);
    lista.add(36);

    System.out.println("Lista rendezés nélkül: " + lista);   

    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}

 

Végeredmény:

Lista rendezés nélkül: [23, 11, 53, 41, 36]

Lista rendezéssel: [11, 23, 36, 41, 53]

 

Ha a listaelemeket és a típust átírjuk mondjuk String-re, a String típusra jellemző ABC szerinti rendezést kapunk. Ez a számok esetében egyenesen megtévesztő lehet, hiszen úgy tűnik, mintha számok szerinti rendezés történt volna:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<String> lista = new ArrayList<String>();
    lista.add("23");
    lista.add("11");
    lista.add("53");
    lista.add("41");
    lista.add("36");
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}
 

Végeredmény:

Lista rendezés nélkül: [23, 11, 53, 41, 36]

Lista rendezéssel: [11, 23, 36, 41, 53]

 

A turpisság rögtön kiderül, ha továbbvariáljuk a listaelemeket:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<String> lista = new ArrayList<String>();
    lista.add("23");
    lista.add("11");
    lista.add("53");
    lista.add("414");
    lista.add("36");
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}
 

Végeredmény:

Lista rendezés nélkül: [23, 11, 53, 414, 36]

Lista rendezéssel: [11, 23, 36, 414, 53]

 

Ekkor már nincs szám szerinti (növekvő) rendezés, illetve a végeredményből az is kiderül, hogy a rendezési elv valóban ABC szerinti, amely tábla garantáltan tartalmazza a következő szekvenciát is:

 

"1", "2", "3", "4", stb.

 

A fentiekben tehát értelmezésbeli hibákat követtünk el a típusokban. "Echte" String-objektumok rendezése valóban ABC-szerinti lesz:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<String> lista = new ArrayList<String>();
    lista.add("Béla");
    lista.add("Andrea");
    lista.add("Zsolt");
    lista.add("Tamás");
    lista.add("Nóra");
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}
 

Végeredmény:

Lista rendezés nélkül: [Béla, Andrea, Zsolt, Tamás, Nóra]

Lista rendezéssel: [Andrea, Béla, Nóra, Tamás, Zsolt]

 

Érdekes, bár haszontalan kísérlet a Boolean típus vizsgálata, de fontos észrevennünk, hogy minden a fenti szabályok szerint fog történni:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<Boolean> lista = new ArrayList<Boolean>();
    lista.add(false);
    lista.add(true);
    lista.add(false);
    lista.add(true);
    lista.add(true);
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}
 

Végeredmény:

Lista rendezés nélkül: [false, true, false, true, true]

Lista rendezéssel: [false, false, true, true, true]

 

Próbáljuk meg a fentiek ellenőrzését egy kvázi bonyolultabb objektumtípussal is (Date - Dátum). 2 db Date típusú objektumba az aktuális dátumot tároljuk, de 5 másodperces késéssel, így nem lesznek teljesen ugyanazok. Minden az ismertetett alapelvek szerint történik: az 5 másodperccel későbbi dátum rendezés után természetesen hátrébb fog kerülni; a rendszer helyesen ismeri fel és rendezi ezt a bonyolult kollekciótípust is:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<Date> lista = new ArrayList<Date>();
    Date dateCurrent1 = new Date();
    try{
        System.out.println("Várakozás 5 másodpercig...");
        Thread.sleep(5000);
    }catch(InterruptedException ie){}
    Date dateCurrent2 = new Date();
    lista.add(dateCurrent2);
    lista.add(dateCurrent1);
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
    }
}

 

Végeredmény:

Várakozás 5 másodpercig...

Lista rendezés nélkül: [Tue Jul 16 21:48:17 CEST 2019, Tue Jul 16 21:48:12 CEST 2019]

Lista rendezéssel: [Tue Jul 16 21:48:12 CEST 2019, Tue Jul 16 21:48:17 CEST 2019]

Még mindig a Date osztálynál vagyunk: a jelenlegi (értsd: a mindenkori futtatási) dátum kivételével az összes, nála korábbi dátumot a Java-szabványok szerinti, 1970.01.01 00:00:00 GMT dátumtól számított milliszekundumokkal írjuk be. Minden a szabályok szerint történik:

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.*;

public class Main {
public static void main(String[] args) {
    List<Date> lista = new ArrayList<Date>();
    Date dateCurrent = new Date();
    Date dateEarlier = new Date(1513353064025L);
    Date dateMoreEarlier = new Date(1163313064025L);
    lista.add(dateCurrent);
    lista.add(dateEarlier);
    lista.add(dateMoreEarlier);
    System.out.println("Lista rendezés nélkül: " + lista);
    Collections.sort(lista);
    System.out.println("Lista rendezéssel: " + lista);
   }
}
 

Végeredmény:

Lista rendezés nélkül: [Wed Jul 17 10:48:03 CEST 2019, Fri Dec 15 16:51:04 CET 2017, Sun Nov 12 07:31:04 CET 2006]

Lista rendezéssel: [Sun Nov 12 07:31:04 CET 2006, Fri Dec 15 16:51:04 CET 2017, Wed Jul 17 10:48:03 CEST 2019]

 

Olyan objektum esetén, amelyik nem valósítja meg a Comparable interfészt, a Collections.sort(objektum) hívásakor ClassCastException kivétel fog dobódni. Persze ez a metódushívás nagy baki, hiszen voltaképpen olyan dologgal próbáljuk az objektumot rendezni, amelyik nem is létezik, legalábbis nincs hozzácsatlakoztatva. A megoldás a Comparable interfész becsatlakoztatása és önálló összehasonlítási (vele rendezési) szempontok megadása. Az utóbbit a következő fejezetben nézzük meg.