Poslední semestrální úlohu budete řešit v Javě. Tu už znáte z Programování 1 a tak si jen v rychlosti ukážeme pár rozdílů v syntaxi oproti Pythonu:
void setValue(int value){
this.value = value
}
| třída | podtřída | balík | ostatní |
public | x | x | x | x |
protected | x | x | x | |
package | x | | x | |
private | x | | | |
final
třída - nelze od ní dědit
metoda - nelze ji měnit v odděděných třídách
proměnná - po inicializaci nemůže být její hodnota změněna
static
Značí že proměnná(nebo metoda) není proměnnou instance, ale proměnnou třídy.
Každá instance třídy (objekt) má vlastní kopii proměnné instance. Proměnná třídy je pouze jedna a instance přistupují stále k té samé proměnné.
Statické metody je možné narozdíl od nestatických volat i tehdy, neexistuje-li žádná instance dané třídy. Podobně se statickými proměnnými.
K proměnným třídy přistupujeme jménem třídy.
Statické metody nemůžou přistupovat k proměnným instance (objektu), protože není definváno k proměnným kterého objektu přistupovat.
Java poskytuje množství datových struktur (objektů), které ulehčují základní operace nad základními datovými strukturami (přidávání, odebírání, procházení atd.)
Datové struktury jsou typované - při deklaraci se definuje jaký typ objektu bude v datové struktuře uložen, tzn. jakého typu budou jednotlivé položky. Položka může být opět datová struktura a tím mohou vznikat vícerozměrné datové struktury.
LinkedList reprezentuje spojový seznam (seznam položek spojených ukazateli) položek (objektů). Na začátku není třeba definovat velikost - přidáním nové položky se jen přidá ukazatel (link) na nový prvek. Procházení spojového seznamu je sekvenční. Lze přistupovat přímo na prostřední prvky, ale implementace musí projít celý seznam od začátku až po hledaný prvek. Odebírání prvku probíhá efektivně v konstatním čase.
Ukázka metod pro LinkedList
List<Integer> seznam; // deklarace
seznam = new LinkedList<Integer>(); // vytvoreni
seznam.add(14); // pridani prvku 14 na konec
seznam.addFirst(9); // pridani prvku 9 na zacatek
seznam.add(23); // pridani prvku 23 na konec
seznam.addFirst(15); // pridani prvku 15 na zacatek (seznam vypada 15,9,14,23)
int size = seznam.size(); // vrati velikost - 4
int i = seznam.get(2); // vrati treti! prvek (neefektivne pruchodem od zacatku) - 14
boolean empty = seznam.isEmpty(); // vrati true, pokud je seznam prazdny
seznam.remove(); // smaze prvni prvek
seznam.clear(); // smaze vse
ArrayList reprezentuje datovou strukturu pole. U ArrayListu není třeba definovat velikost (možné to ale je), Java vytvoří defaultní velikost a pokud velikost pole nestačí, tak ho automaticky zvětší na dvojnásobek. To může vést ke zbytečné alokaci velkého množství paměti. ArrayList se dá procházet sekvečně, ale dá se také přímo přistupovat na konkrétní prvek jeho indexem v poli. Odebírání prvku je neefektivní, protože po odebrání prvku je nutné zbytek pole posunout.
Ukázka metod pro ArrayList
class Osoba { // defince tridy Osoba
}
ArrayList<Osoba> pole; // deklarace pole obsahujici osoby.
pole = new ArrayList<Osoba>(30); // vytvoreni pole obsahujici osoby.
// ArrayList je inicializovan na velikost 30 (ale neni to nutne)
pole.add(new Osoba()); // pridani nove osoby na konec
pole.add(new Osoba()); // pridani nove osoby na konec
int size = pole.size(); // vrati velikost
Osoba os = pole.get(1); // vrati druhy! prvek (efektivne primym pristupem)
boolean empty = pole.isEmpty(); // vrati true, pokud je pole prazdny
pole.set(1, new Osoba()); // nastavi druhy prvek pole na novou hodnotu
pole.clear(); // smaze vse
HashMap reprezentuje hashovací tabulku. Hashovací tabulka je seznam dvojic, která přiřazuje zvolenému klíči danou hodnotu. Klíč musí být v rámci tabulky unikátní. HashMap umožňuje přimý přístup (v konstaním čase) k hodnotě pomocí klíče. Tzn. že se můžeme zeptat jaká je přiřazená hodnota danému klíči a HashMap v konstatním čase vrátí hodnotu nebo oznámí, že klíč není v tabulce. HashMap lze procházet sekvenčně, ale není garantováno pořadí prvků.
Ukázka metod pro HashMap
HashMap<Double, String> mapa; // deklarace
mapa = new HashMap<Double, String>(); // vytvoreni
mapa.put(2.5, "prvni"); // vlozi do mapy klic 2.5 s hodnotou "prvni"
mapa.put(3.5, "prvni"); // vlozi do mapy klic 3.5 s hodnotou "prvni" (hodnota se muze opakovat)
mapa.put(4.0, "druhy"); // vlozi do mapy klic 4.0 s hodnotou "druhy"
mapa.put(-1.1, null); // vlozi do mapy klic -1.1 s hodnotou null (null muze nahradit libovolny objekt)
mapa.put(4.0, "novy"); // vlozi a prepise do mapy klic 4.0 s hodnotou "novy" a tim prepise hodnotu "druhy" (klic se neopakuje)
int size = mapa.size(); // vrati velikost
boolean empty = mapa.isEmpty(); // vrati true, pokud je mapa prazdna
boolean obsahuje =
mapa.containsKey(2.5); // vrati true - klic je v mape // ERROR
String hodnota = mapa.get(2.5); // vrati String "prvni"
obsahuje = mapa.containsKey(6.7); // vrati false - klic neni v mape // ERROR
hodnota = mapa.get(6.7); // vrati null - klic neni v mape
// ale POZOR
obsahuje = mapa.containsKey(-1.1); // vrati true - klic je v mape
hodnota = mapa.get(-1.1); // vrati null - hodnota ulozena pod klicem -1.1
mapa.remove(4.0); // odstrani z mapy klic 4.0 a jeho hodnotu
Set<Double> klice = mapa.keySet(); // vrati mnozinu klicu (podrobneji pozdeji)
Collection<String> hodnoty =
mapa.values(); // vrati mnozinu hodnot (podrobneji pozdeji)
Set<Map.Entry<Double, String>> dvojice =
mapa.entrySet(); // vrati mnozinu vsech dvojic (klic, hodnota) v mape // ERROR
mapa.clear(); // smaze vse
Ukázka metod pro LinkedHashMap
LinkedHashMap<Integer, LinkedList<String>> mapa; // deklarace mapy cisel, ktera ma jako hodnoty seznamy
mapa = new LinkedHashMap<Integer, LinkedList<String>>();// vytvoreni mapy
LinkedList<String> seznam = new LinkedList<String>(); // vytvoreni noveho seznamu
seznam.add("prvni"); // pridani prvku do seznamu
mapa.put(35, seznam); // vlozeni seznamu do mapy pod klic 35
seznam.add("druhy"); // pridani dalsiho prvku do seznamu.
// projevi se i v mape, protoze je to ukazatel na stale stejny objekt
LinkedList<String> seznam2 = new LinkedList<String>(); // vytvoreni noveho seznamu
seznam2.add("ahoj"); // pridani prvku do seznamu
mapa.put(12, seznam2); // vlozeni noveho seznamu pod klic 12
Konstrukce Javy, která umožňuje snadné procházení kolekcemi - např. LinkedList, ArrayList, LinkedHashMap, Set
Postupně prochází danou kolekci a v každé iteraci vrací jeden prvek
Ukázka použití iterátoru
LinkedList<String> seznam = new LinkedList<String>();
seznam.add("prvni");
seznam.add("druhy");
seznam.add("treti");
for (String item : seznam) { // vpravo od dvojtecky musi byt objekt typu Collection
System.out.println(item); // vlevo je promenna, ktera je stejneho typu, jakym je typovana kolekce
} // cyklus provede pocet iteraci podle poctu prvku v kolekci
// a v kazde iteraci vrati do promenne item jednu polozku kolekce
LinkedHashMap<Integer, String> mapa = new LinkedHashMap<Integer, String>();
for (Integer key : mapa.keySet()) { // prochazi mnozinu vsech klicu
}
for (String value : mapa.values()) { // prochazi mnozinu vsech hodnot
}
for (Map.Entry<Integer, String> entry : mapa.entrySet()) { // prochazi mnozinu vsech dvojic klic/hodnota
int key = entry.getKey(); // klic z dvojice
String value = entry.getValue(); // hodnota z dvojice
}
Ukázka použití komplexního iterátoru
LinkedList<String> seznam = new LinkedList<String>();
seznam.add("prvni");
seznam.add("druhy");
seznam.add("treti");
Iterator<String> iter = seznam.iterator(); // zalozi novy iterator pro seznam
while (iter.hasNext()) { // pokracuje v cyklu dokud exituji nejake dalsi polozky
String item = iter.next(); // do item nacte dalsi polozku
if (item.equals("druhy")) {
iter.remove(); // smaze polozku, ktera byla prave nactena pomoci funkce next()
} // lze pouzit maximalne jednou, pak se musi zavolat znovu next()
}