Vaše jistota na trhu IT Výčtové a interní datové typy Rudolf Pecinovský
Vaše jistota na trhu IT Obsah s odkazy ►Výčtové typyVýčtové typy ►Interní datové typyInterní datové typy ►Vnořené typy (nested, static inner)Vnořené typy (nested, static inner) ►Vnitřní třídy (inner classes)Vnitřní třídy (inner classes) ►Anonymní třídyAnonymní třídy ►Pojmenované lokální třídyPojmenované lokální třídy ►Rozhraní Comparable a ComparatorRozhraní Comparable a Comparator
Vaše jistota na trhu IT Výčtové typy ►Jednoduchý výčet hodnot ►Jak to vypadá uvnitř ►„Chytřejší“ výčtové typy ►Příklad: třída Směr8 67–72 253–256
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 4 Syntaxe výčtových typů ►V definicích výčtových typů je klíčové slovo class nahrazeno slovem enum ►Za hlavičkou třídy následuje seznam hodnot daného typu ►Za čistým výčtem dokonce nemusí následovat středník ►Uvedený typ překladač přeloží stejně, jak by byl definován jako potomek třídy java.lang.Enum public enum Období { JARO, LÉTO, PODZIM, ZIMA; }
Přeložený tvar čistého výčtu VŠE – 05 Copyright © 2006, Rudolf Pecinovský 5 VŠE – 05 Přeložený tvar čistého výčtu package výčty; public final class Období extends Enum { public static final Období JARO; public static final Období LÉTO; public static final Období PODZIM; public static final Období ZIMA; private static final Období $VALUES[]; static { JARO = new Období("JARO", 0); LÉTO = new Období("LÉTO", 1); PODZIM = new Období("PODZIM", 2); ZIMA = new Období("ZIMA", 3); $VALUES = new Období[] { JARO, LÉTO, PODZIM, ZIMA }; } public static final Období[] values() { return (Období[])((Období []) ($VALUES)).clone(); } public static Období valueOf(String name) { return (Období)Enum.valueOf(výčty.Období, name); } private Období(String s, int i) { super(s, i); } Pole hodnot daného typu Deklarace hodnot (veřejných konstant) daného typu Statický inicializační blok inicializující konstanty a pole s odkazy na ně Metoda vracející pole hodnot daného typu Metoda vracející hodnotu po zadání jejího názvu Soukromý konstruktor zabraňující vytváření dalších instancí
Metody zděděné od třídy Enum ► String name() Vrátí název dané instance ► int ordinal() Vrátí pořadí deklarace dané instance (začíná se nulou) ► boolean equals(Object other) Vrací true je-li instance totožná s parametrem ► int compareTo(E o) Vrátí -1, 0 či +1 podle toho, je-li deklarace daná instance menší, rovna či větší než parametr (porovnává se ordinal ) ► E[] values() ► E valueOf(String name) VŠE – 05 Copyright © 2006, Rudolf Pecinovský 6 Jsou zde uvedeny pro úplnost, nedědí se, dodá je překladač (viz předchozí snímek)
„Chytřejší“ výčtové typy ►Potřebujeme-li definovat parametry konstruktoru, uvádíme za názvem hodnoty standardní seznam parametrů ● Překladač vždy definuje, který na počátek seznam přidá parametry String name, int index aby mohl začít tělo konstruktoru příkazem super(name, index) ►Často je výhodné, aby hodnoty výčtového typu vykazovaly jistou „dodatečnou inteligenci“ ►Výčtové typy nemusí být pouze čistým výčtem hodnot, jsou to standardní typy ● Mohou mít vlastní atributy a vlastnosti ● Mohou mít vlastní metody ● Mohou využívat konstruktoru s parametry ►Příklad: Směr8 VŠE – 05 Copyright © 2006, Rudolf Pecinovský 7
Vaše jistota na trhu IT VŠE – 05Copyright © 2006, Rudolf Pecinovský 8 Výběr rozšiřujících metod třídy Směr8 public Směr8 čelemVzad() { return SMĚRY[MASKA & (4+ordinal())]; } public int dx() { return posun[ordinal()][0]; } public int dalšíX( int x, int vzdálenost ) { return x + dx()*vzdálenost; } public Pozice dalšíPozice( Pozice pozice, int vzdálenost ) { return new Pozice( dalšíX( pozice.x, vzdálenost ), dalšíY( pozice.y, vzdálenost ) ); }
Vaše jistota na trhu IT Interní datové typy ►Charakteristika ►Rozdělení ►Globální zanořené třídy ►Vnořené třídy ►Vnitřní třídy – omezení, důvody zavedení ►Anonymní třídy – definice, omezení, použití ►Pojmenované lokální třídy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 10 Charakteristika ►Typy definované uvnitř jiných typů ►Typy mají členy: ● Datové – atributy ● Funkční – metody ● Typové – interní typy ►Každý typ, tj. i interní, má vlastní soubor *.class ►Mohou být potomky libovolné viditelné třídy a implementovat libovolné viditelné rozhraní ►Jsou uvnitř svých vnějších typů, a proto vidí i na jejich soukromé (private) členy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 11 Rozdělení interních tříd ►Globální – mimo bloky kódu, tj. na úrovni atributů a metod ● Statické – Vnořené (nested, embedded, static inner) ● Nestatické – Vnitřní (inner) ►Lokální – uvnitř metod a bloků kódu ● Pojmenované (named) ● Anonymní (anonymous)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 12 Globální interní typy ►Pro jejich dostupnost a její nastavení platí totéž, co pro dostupnost ostatních členů, tj. atributů a metod ►Mohou mít nastaveny kterýkoliv modifikátor přístupu ● public ● protected ● „package private“ ● private ►Zvenku se k nim přistupuje stejně jako k ostatním členům, tj. kvalifikují se svoji třídou či instancí (např. java.awt.geom.Point2D.Double )
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 13 Lokální třídy ►Deklarovány uvnitř bloků kódu ● Nejen uvnitř metod, ale uvnitř libovolného bloku kódu ►Jsou soukromou záležitostí svého bloku ● Obdobně jako lokální proměnné jsou zvenku nedosažitelné ►Mohou to být pouze třídy, nelze definovat lokální interface ►Instance lokální třídy je možno vyvážet mimo daný blok; tam se vydávají za instance svého předka či implementovaného rozhraní ● Hlavní důvod definice lokálních tříd
Vaše jistota na trhu IT Vnořené typy (nested, static inner)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 15 Charakteristika ►Deklarovány s modifikátorem static (rozhraní static nepotřebují, protože jiná být nemohou) ►Jsou to zcela obyčejné typy se všemi jejich možnostmi a omezeními, s výjimkou viditelnosti / dosažitelnosti ►Vnoření typu do jiného ovlivní pouze ● Viditelnosti daného typu z okolí ● Dosažitelnost objektů z definic ve vnořené třídě (z rozhraní není kam dosahovat) ►Vnoření je pouze otázka jmenného prostoru => vnořené typy můžeme definovat i uvnitř rozhraní (např. java.util.Map.Entry )
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 16 Důvody zavedení: ►Třída potřebuje definovat vlastní datový typ, nejčastěji přepravku (pak bývají soukromé) ►Potřebujeme definovat datový typ, jehož instance budou mít přístup k soukromým atributům své vnější třídy ►Pro rozhraní je občas vhodné definovat typickou implementaci deklarovaných metod (adaptér) ►Vnější třída je rodičem svých vnitřních, které přímo přistupují k jejím soukromým atributům
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 17 Příklad 1: třída Směr8 public enum Směr8 { //== HODNOTY VÝČTOVÉHO TYPU ================================================== VÝCHOD ( 1, 0, "S", "VÝCHOD", "VYCHOD"), SEVEROVÝCHOD( 1, -1, "SV", "SEVEROVÝCHOD", "SEVEROVYCHOD"), SEVER ( 0, -1, "S", "SEVER", "SEVER"), SEVEROZÁPAD ( -1, -1, "SZ", "SEVEROZÁPAD", "SEVEROZAPAD"), ZÁPAD ( -1, 0, "Z", "ZÁPAD", "ZAPAD"), JIHOZÁPAD ( -1, 1, "JZ", "JIHOZÁPAD", "JIHOZAPAD"), JIH ( 0, 1, "J", "JIH", "JIH"), JIHOVÝCHOD ( 1, 1, "JV", "JIHOVÝCHOD", "JIHOVYCHOD"), ; //== KONSTANTNÍ ATRIBUTY TŘÍDY =============================================== public static final int SMĚRŮ = 8; private static final int MASKA = 7; private static final Map názvy = new HashMap ( SMĚRŮ*3 ); private static final int[][] posun = new int[SMĚRŮ][2]; private static final Směr8[] SMĚRY = values(); static { for( Směr8 s : SMĚRY ) { posun[s.ordinal()][0] = s.přepravka.dx; posun[s.ordinal()][1] = s.přepravka.dy; názvy.put( s.přepravka.zkratka, s ); názvy.put( s.přepravka.název, s ); názvy.put( s.přepravka.názevBHC,s ); s.přepravka = null; } //== DOČASNÉ ATRIBUTY INSTANCÍ =============================================== private static class Přepravka { int dx, dy; String zkratka, název, názevBHC; } Přepravka přepravka; //== KONSTRUKTORY A TOVÁRNÍ METODY =========================================== private Směr8( int dx, int dy, String zkratka, String název, String názevBHC ) { přepravka = new Přepravka(); přepravka.dx = dx; přepravka.dy = dy; přepravka.zkratka = zkratka; přepravka.název = název; přepravka.názevBHC = názevBHC; } Deklarace hodnot (veřejných konstant) daného typu Mapa pro odvození instance ze zadaného názvu Instance si svá data nepamatují ve vlastních atributech, ale v polích, které jsou atributy třídy Statický inicializační blok inicializující pole a mapu Přepravka pro dočasné uchování hodnot zadaných konstruktoru, než je bude možno uložit do mapy a příslušných polí Konstruktor ukládá všechny parametry do přepravky, aby je bylo možno vyzvednout ve statickém inicializačním bloku
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 18 Příklad 2: IPosuvný.Adaptér public interface IPosuvný extends IKreslený { public Pozice getPozice(); public void setPozice( Pozice pozice ); public void setPozice( int x, int y ); public static class Adaptér implements IPosuvný { public Pozice getPozice() { throw new UnsupportedOperationException(); } public void setPozice( Pozice pozice ) { throw new UnsupportedOperationException(); } public void setPozice( int x, int y ) { throw new UnsupportedOperationException(); } public void nakresli( Kreslítko kreslítko ) { throw new UnsupportedOperationException(); } public class Třída extends IPosuvný.Adaptér { // Definice těla třídy }
Vaše jistota na trhu IT Vnitřní třídy (inner classes)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 20 Charakteristika ►Deklarovány bez modifikátoru static ►Instance vnitřní třídy jsou navázány na instanci vnější třídy –> mají deklarován skrytý konstantní atribut obsahující odkaz na příslušnou instancí vnější třídy ►Tato vazba potřebuje implementaci => jako vnitřní typ není možno definovat rozhraní ►Atribut je skrytý, tj. neuvádí se, ale můžeme jej používat –> získání odkazu na instanci vnější třídy: Vnější.this
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 21 Konstrukce instance vnitřní třídy ►V metodě instance ● Odkaz na příslušnou instanci vnější třídy předá konstruktoru překladač (vezme this a předá je) ►V metodě třídy ● Odkaz na příslušnou instanci vnější třídu musí konstruktoru vnitřní třídy předat programátor – učiní tak kvalifikací operátoru new instancí vnější třídy, na níž bude vytvářená instance vnitřní třídy napojena – např.: Vně vně = new Vně(); Vně.Vni vni = vně.new Vně.Vni();
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 22 Omezení ►Nesmějí mít statické atributy a metody – nevědělo by se, jak moc jsou statické ● Pouze v rámci napojené instance ● V rámci celé vnější třídy ►Místo zavádění statických atributů a metod je třeba definovat potřebné atributy a metody v příslušné vnější třídě ►Při dědění od vnitřní třídy je třeba dceřinému konstruktoru předat v parametru odkaz na její instanci – složité, nepoužívat
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 23 Důvody zavedení ►Je třeba exportovat objekt zadaného typu, který by měl přístup k soukromým složkám instance (např. iterátor) ►Je potřeba pomocný (=soukromý) typ, jehož instance budou mít přímou vazbu na instance své vnější třídy ►Alternativa pro některé anonymní třídy (někdo nemá anonymní třídy rád, protože znepřehledňují kód)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 24 Příklad: Iterátor public class ItPole implements Iterable { private final Položka [] pole; //Pole položek typu Položka public ItPole(Položka[] pole) { this.pole = pole.clone() } public Iterator iterator() { return new Iter(); } private class Iter implements Iterator { int index = 0; public boolean hasNext() { return (index < pole.length ); } public Položka next() { return pole[ index++ ]; } public void remove() { throw new UnsupportedOperationException(); } private static void test() { ItPole ip = new ItPole ( new Integer[] { 1, 3, 5, 7, 11, 13, 17, 19 } ); for( Integer i : ip ) { System.out.println( i + "^2 = " + i*i ); }
Vaše jistota na trhu IT Anonymní třídy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 26 Charakteristika ►Jejich definice je součástí příkazu k vytvoření instance; je to na poslední chvíli uvedená definice třídy vytvářené instance ►Definice anonymní třídy jsou součástí příkazu vytvoření instance, a proto vystupují ve zdrojovém textu jako výraz (píše se za nimi středník či čárka) ►Nemohou mít vlastní konstruktor; je-li potřeba, používá se místo něj nestatický inicializační blok ►Mohou používat pouze konečné lokální proměnné (konstanty) některého z bloků, v nichž je anonymní třída definována ● Důvod: doba života bloku × instance
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 27 Zápis ►Tváříme se, že voláme konstruktor rodiče, ale protože ve skutečnosti chceme zkonstruovat potomka, jehož třída navíc ještě neexistuje, tak si ji narychlo vytvoříme ►Podle zadaných parametrů se pozná, který z rodičovských konstruktorů vytvoří příslušný podobjekt ►Definice tříd implementujících rozhraní se „tváří“, že rozhraní má implicitní konstruktor; ve skutečnosti se volá konstruktor třídy Object new Rodič(parametry) { //Definice potřebných metod }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 28 Omezení1/2 ►Mohou používat pouze konečné proměnné (konstanty) bloků, v nichž jsou definovány ● Důvod: doba života bloku × instance ● Je-li použitou proměnnou parametr, i on musí být definován jako konečný ►Nemohou mít vlastní konstruktor; je-li potřeba, používá se místo něj inicializační blok IPojmenovaný vytvoř( final String název ) { return new IPojmenovaný() { String jméno; { jméno = název; } public String getNázev() { return jméno; } }; } IPojmenovaný vytvoř( final String název ) { return new IPojmenovaný() { public String getNázev() { return název; } }; } Lepší řešení
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 29 Omezení2/2 ►Nemohou definovat statické metody ● Teoreticky je místo nich třeba definovat potřebné metody ve vnější třídě, ale tak složité anonymní třídy se nepoužívají ►Nemohou definovat statické atributy ● Místo proměnných statických atributů je třeba definovat atributy ve vnější třídě ● Místo konstantních atributů lze použít konstanty některého z bloků v nichž je definice anonymní třídy zanořena
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 30 Použití 1: Posluchači událostí1/3 ►Nejčastěji se s jejich pomocí na poslední chvíli vyrábí instance požadovaného typu ● Posluchači událostí ● Vlákna ● … JButton tlačítko = new JButton( OK ); tlačítko.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent ae ) { potvrzeno(); } ); Instance anonymní tříd je použita jako parametr
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 31 Použití 2: Vytvoření ihned použitého objektu ►Objekt vlákna (instance třídy Thread) monu nejprve vytvořit a v dalším příkazu použít ►Stejně dobře ale mohu čerstvě vytvořený objekt ihned, tj. v témže příkazu použít Thread t = new Thread( "Ukázka" ) { public void run() { metoda(); } }; t.start(); new Thread( "Ukázka" ) { public void run() { metoda(); } }.start();
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 32 Použití 3: Funkční výčtové typy2/3 ►Instance funkčního výčtového typy jsou instancemi potomka tohoto typu ►Z venku není dovnitř potomků vidět, takže nevím, jaké metody deklarují => ►Metody instancí funkčních výčtových typů musí být v rodiči deklarovány jako abstraktní – tím se zviditelní public enum Operace { PLUS { public int proveď( int a, int b) { return a + b; } }, MINUS { public int proveď( int a, int b) { return a - b; } }; public abstract proveď( int a, int b ); } //... Operace op = PLUS; int výsledek = op.proveď( x, y ); //...
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 33 Použití 4: Pole metod3/3 public interface IOperace { public int proveď( int a, int b ); } IOperace[] op = { new IOperace() { public int proveď( int a, int b ) { return a * b; } }, new IOperace() { public int proveď( int a, int b ) { return a / b; } } }; Random rnd = new Random(); //... int výsledek = op[ rnd.nextInt(op.length) ].proveď(x,y); //...
Vaše jistota na trhu IT Pojmenované lokální třídy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 35 Charakteristika ►Jsou velmi podobné anonymním třídám ►Odchylky: ● Mohou mít vlastní konstruktor ● Mají jména, takže jejich instance mohu vytvářet na více místech programu ►Společná omezení ● Nemohou mít statické členy ● Z lokálních proměnných bloků, v nichž jsou definovány, mohou používat pouze konstanty
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 36 Příklad: Filtr souborů private static void najdiVeSlozce( File koren, Class predek, String balicek, Collection >tridy ) { // Filtr souboru k dalsi analyze - pousti jen class-soubory class Prelozene implements java.io.FileFilter { public boolean accept( File soubor ) { boolean slozka, trida, zajimavy; zajimavy = (slozka = soubor.isDirectory()) || (trida = soubor.getName().endsWith( ".class" ) ); return zajimavy; } for( File f : koren.listFiles( new Prelozene() ) ) { zpracujSoubor( f ); }
Vaše jistota na trhu IT Rozhraní Comparable a Comparator ►Typy s definovaným pořadím ►Rozhraní Comparable ►Nativní třídění polí a seznamů ►Problémy související s tříděním ►Požadavky rozhraní Comparator ►Třídění s pomocí komparátoru ►Další metody využívající porovnání ►Návrhový vzor Příkaz 89–93
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 38 Typy s definovaným pořadím ►Řada hodnotových objektových typů má definované porovnávání hodnot ►Porovnatelnost hodnot instancí deklaruje třída implementací rozhraní java.lang.Comparable ►Rozhraní vyžaduje implementaci jediné metody int compareTo( T t ) ►Vracená hodnota: ● < 0 je-li this < t ● = 0 je-li this == t ● > 0 je-li this > t
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 39 Požadavky na metodu compareTo( T) ►Antisymetričnost: sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) ● Vztahuje se i na výjimky, tj. když jedno porovnání vyhodí výjimku, mělo by ji vyhodit i to sdružené ►Transitivnost: (x.compareTo(y)>0 && y.compareTo(z)>0) => x.compareTo(z)>0 ►Odvoditelnost: x.compareTo(y)==0 => sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ►Vřelé doporučení: konsistence s equals(Object) : (x.compareTo(y)==0) == (x.equals(y))
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 40 Nativní třídění polí a seznamů ►K třídění polí slouží metody java.util.Arrays.sort(T[] ta) java.util.Arrays.sort(T[] ta, int from, int to) kde typ T může být libovolný primitivní či objektový typ ►K třídění seznamů slouží metoda java.util.Coolections.sort(List lt) kde typ T může být libovolný objektový typ implementující Comparable ►U objektových typů se předpokládá, že ● Všechny porovnávané instance implementují rozhraní Comparable ● Instance jsou vzájemně porovnatelné V opačném případě metoda vyvolá ClassCastException
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 41 Problémy související s tříděním ►V různých fázích práce programu potřebuji třídit podle různých kritérií ● Např. jednou s rozlišováním velikosti písmen a podruhé bez něj ►Potřebuji porovnávat instance tříd, které nativně vzájemné porovnání nepodporují ● Např. hrušky s jablky podle jejich váhy ►Potřebuji třídit podle jiného kritéria, než je nativní kritérium implementované metodou compareTo(Object) ● Zákazníci jsou nativně tříděni dle abecedy, ale já je potřebuji setřídit podle jejich dosažitelnosti, solventnosti apod. ►Třída žádné porovnávací kritérium nedefinuje, ale pro danou situaci mám nějaké vymyšlené ● Třídím experimenty podle odhadované doby trvání
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 42 Rozhraní java.util.Comparator ►Předchozí problémy lze řešit definicí třídy implementující rozhraní java.util.Comparator ►Rozhraní Comparator vyžaduje definici metody int compare(T t1, T t2) ►Vracená hodnota i požadavky na metodu jsou stejné jako u metody compareTo(Object) zaměníme-li u ní this za t1 ►Třída implementující rozhraní Comparator bývá často definována jako interní (většinou vnořená)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 43 Třídění polí a seznamů pomocí komparátoru ►K třídění polí slouží metody Arrays.sort(T[] ta, Comparator c) Arrays.sort(T[] ta, int from, int to, Comparator c) ►K třídění seznamů slouží metoda Coolections.sort(List lt, Comparator c) ►Instance komparátoru předaná jako parametr musí umět vzájemně porovnat všechny prvky v tříděném poli či seznamu; v opačném případě metoda vyvolá ClassCastException
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 44 Příklad: Třídění nativní a modulo public class Modulo2 implements Comparable { private final int hodnota; private final int modul; public Modulo2( int h ) { hodnota = h; modul = h % 10; }//============================================================= public String toString() { return String.format( "%2s", hodnota); }//============================================================= private static void tiskni( String s, Modulo2[] mm) { System.out.println( s + Arrays.asList( mm ) ); }//============================================================= public static final void test() { Random rnd = new Random(); Modulo2[] mm = new Modulo2[20]; for( int i=0; i < mm.length; mm[i++] = new Modulo2(rnd.nextInt(100)) ); tiskni( "Výchozí: ", mm ); Arrays.sort( mm ); tiskni( "Setříděné: ", mm ); Arrays.sort( mm, new Comp() ); tiskni( "Comparator:", mm ); }//============================================================= public int compareTo(Modulo2 m) { return (hodnota - m.hodnota); }//============================================================= private static class Comp implements Comparator { public int compare( Modulo2 a, Modulo2 b) { if( a.modul != b.modul ) return (a.modul - b.modul); else return a.hodnota - b.hodnota; }
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 45 Příklad: Třídění nativní a modulo public class Modulo2 implements Comparable { private final int hodnota; private final int modul; public Modulo2( int h ) { hodnota = h; modul = h % 10; }//============================================================= public String toString() { return String.format( "%2s", hodnota); }//============================================================= private static void tiskni( String s, Modulo2[] mm) { System.out.println( s + Arrays.asList( mm ) ); }//============================================================= public static final void test() { Random rnd = new Random(); Modulo2[] mm = new Modulo2[20]; for( int i=0; i < mm.length; mm[i++] = new Modulo2(rnd.nextInt(100)) ); tiskni( "Výchozí: ", mm ); Arrays.sort( mm ); tiskni( "Setříděné: ", mm ); Arrays.sort( mm, new Comp() ); tiskni( "Comparator:", mm ); }//============================================================= public int compareTo(Modulo2 m) { return (hodnota - m.hodnota); }//============================================================= private static class Comp implements Comparator { public int compare( Modulo2 a, Modulo2 b) { if( a.modul != b.modul ) return (a.modul - b.modul); else return a.hodnota - b.hodnota; } Výchozí: [99, 79, 18, 81, 47, 88, 88, 42, 56, 85, 61, 23, 41, 44, 3, 46, 74, 52, 17, 23] Setříděné: [ 3, 17, 18, 23, 23, 41, 42, 44, 46, 47, 52, 56, 61, 74, 79, 81, 85, 88, 88, 99] Comparator:[41, 61, 81, 42, 52, 3, 23, 23, 44, 74, 85, 46, 56, 17, 47, 18, 88, 88, 79, 99]
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 46 Další metody využívající porovnání1/2 ►K vyhledání prvku v setříděném polí slouží metody Arrays.binarySearch(T[] ta, T klíč) Arrays.binarySearch(T[] ta, T klíč, Comparator c) kde typ T může být libovolný primitivní či objektový typ ►K vyhledání prvku v setříděném seznamu slouží metody Collections.binarySearch(List lt, T klíč) Collections.binarySearch(List ta, T klíč, Comparator c) ►K získání komparátoru, který třídí v obráceném pořadí, slouží Collections.reverseOrder() Collections.reverseOrder(Comparator cmp)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 47 Další metody využívající porovnání2/2 ►K vyhledání největšího prvku v kolekci slouží metody Collections.max(Collection coll) Collections.max(Collection coll, Comparator c) ►K vyhledání nejmenšího prvku v kolekci slouží metody Collections.max(Collection coll) Collections.max(Collection coll, Comparator c)
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 48 Zdrojový kód metody max(Collection ) //Deklarace typových parametrů jsou zjednodušené public static > T max(Collection coll) { Iterator i = coll.iterator(); T candidate = i.next(); while(i.hasNext()) { T next = i.next(); if (next.compareTo(candidate) > 0) candidate = next; } return candidate; } Kolekcí budeme procházet pomocí iterátoru Připravíme si kandidáta na maximum Procházíme zbytkem kolekce, a je-li někdo větší než kandidát, prohlásíme jej za lepšího kandidáta
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 49 Zdrojový kód verze s komparátorem //Deklarace typových parametrů jsou zjednodušené public static T max(Collection coll, Comparator comp) { if (comp==null) return (T)max((Collection ) (Collection) coll); Iterator i = coll.iterator(); T candidate = i.next(); while(i.hasNext()) { T next = i.next(); if (comp.compare(next, candidate) > 0) candidate = next; } return candidate; } private interface SelfComparable extends Comparable {} Je-li zadán prázdný odkaz na komparátor, zkusíme verzi bez komparátoru Verze bez komparátoru vyžaduje nativně porovnatelné objekty – definuje si soukromé vnořené rozhraní, na něž se pokusí instance přetypovat Je-li dodán komparátor, připraví si iterátor a kandidáta na maximum Pak pokračuje stejně jako minule, jenom s jinou metodou porovnání hodnot
Vaše jistota na trhu IT Děkuji za pozornost ►Rudolf Pecinovský mail: ICQ:
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 51 Pgm Používaná písma a objekty ► Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Demi) ● Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Medium) ● Pgm Příliš žluťoučký kůň úpěl ďábelské ódy (Cond) ►Příliš žluťoučký kůň úpěl ďábelské ódy (Heavy) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Franklin Gothic Book) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Comic Sans MS) ● Příliš žluťoučký kůň úpěl ďábelské ódy (Consolas) Program Keyword Opakování Příliš žluťoučký kůň úpěl ďábelské ódy
VŠE – 05 Copyright © 2006, Rudolf Pecinovský 52 Konvence syntaktických definic Syntaktická definice = pravidla zápisu konstrukce jazyka Název–Název definované součásti součást –Název součásti definované jinde program –Text, který se přímo použije (opíše) [ ]–Obsah hranatých závorek je volitelný { | }–Výběr z několika možností oddělených | –Druhou možností je psaní možností pod sebe …–Předchozí položka se může opakovat ¶–Definice pokračuje na dalším řádku kde bude navíc odsazená Příklad:Identifikátor:písmeno [ { písmeno | číslice } ] … Číslice: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Originál: P02_Prvni_kod.ppt#23. Konvence syntaktických definicP02_Prvni_kod.ppt#23. Konvence syntaktických definic