# Pole - **Strukturovaný datový typ pro uložení více prvků stejného typu** - Pro uložení více hodnot stejného typu se hodí pole ### Základní práce s (jednorozměrným) polem - Pole - Strukturovaný datový typ - Skládá se z **pevně daného počtu prvků** - **Je homogenní** – všechny prvky v něm uložené jsou stejného typu - **Počet prvků se stanoví při inicializaci** (vytvoření) pole a pak již **nelze změnit** - **Počet prvků je délka pole**, která je v **poli kromě prvků rovněž uložená** - Indexy - Jednotlivé prvky pole jsou **přístupné pomocí indexů** - V Javě má index vždy hodnoty 0 až délka pole - 1 #### Deklarace a vytvoření pole - Pole je podobné třídám a objektům - V podstatě se jedná o speciální třídu a při inicializaci pole vytváříme její „instanci“ uloženou na haldě - Je potřeba deklarovat referenční proměnou a vytvořit novou „instanci pole“ operátorem ```new``` - Stejně jako u objektů je možné udělat obojí najednou, nebo nejprve deklarovat referenční proměnou a později vytvořit nové pole - ```datovýTyp[] proměnná = new datovýTyp[početPrvků];``` - Při vytváření nového pole se udává počet prvků (v hranatých závorkách „[“ a „]“), které bude pole obsahovat - Typ prvků pole může být libovolný - Libovolný základní datový typ - Libovolná třída - Protože proměnná typu pole je referenční, může být ```null``` - Pokud se jedná o lokální proměnnou a nevytváříme pole hned při deklaraci jeho referenční proměnné, je rozumné inicializovat referenční proměnnou na ```null``` - Pokud se jedná o proměnnou instance nebo třídy, je inicializována na ```null``` implicitně - Při vytvoření pole jsou jeho jednotlivé prvky implicitně inicializovány na ```0, 0.0, false``` nebo ```null``` podle datového typu pole - I v případě, že referenční proměnná ukazující na pole je lokální - Vytvoření pole výčtem hodnot - Pole je kromě operátoru ```new``` možné vytvořit i výčtem jeho hodnot uvedeným ve složených závorkách ```„{“``` a ```„}“``` - Např. ```int[] fibonacci = {0, 1, 1, 2, 3, 5, 8, 13};``` - Pole má stejné vlastnosti jako pole vytvořené operátorem ```new``` – délku pole určí překladač podle počtu prvků - Často používáno jako vzorová data pro usnadnění ladění, nebo uložení pole konstantních hodnot - POZOR! – Takto definované pole nemá konstantní prvky, **jeho prvky lze libovolně měnit**, např. ```fibonacci[3] = -6;``` - POZOR! - Samotným výčtem hodnot lze pole vytvořit POUZE PŘI DEKLARACI - Pokud chceme přiřadit do existující referenční proměnné nové pole výčtem hodnot, musí samotnému výčtu předcházet vytvoření pole operátorem ```new``` bez udání počtu prvků - proměnná = ```new datovýTyp[] {hodn1, hodn2, …};``` - Např. ```fibonacci = new int[] {1, 1, 2, 3};``` - Konstantní pole - Použití klíčového slova ```final``` nezajistí, aby prvky pole po prvním přiřazení nešly změnit - ```final``` pouze zajistí konstantnost referenční proměnné – nelze do ní již přiřadit jinou hodnotu (tj. jiné pole) - Prvky pole, na které ukazuje ```final``` referenční proměnná lze ale měnit bez problémů - To samé platí pro referenční proměnné a instance tříd – hodnoty atributů (proměnných) instance lze měnit, i když je referenční proměnná ukazující na instanci označena jako ```final``` #### Přístup k prvkům pole a jeho délka - K jednotlivým prvkům pole se přistupuje pomocí indexu - Index se zapisuje za referenční proměnou do hranatých závorek - ```proměnná[index]``` - Prvek pole se chová stejně jako proměnná odpovídajícího datového typu - Lze do něj zapisovat hodnotu - Lze z něj číst hodnotu - Např. ```teploty[0] = 17.5;``` - Např. ```double teplota = teploty[0];``` - Délka pole - Každé pole má v sobě informaci o délce uloženou v proměnné ```length``` - Volá se přes tečkovou notaci stejně jako proměnná instance nad referenční proměnnou pole - Např. ```int pocetTeplot = teploty.length;``` - První prvek pole má index 0 - ```Např. double prvniTeplota = teploty[0];``` - Poslední prvek pole má index ```pole.length – 1``` - Např. ```double posledniTeplota = teploty[teploty.length - 1];``` - Index mimo rozsah pole - POZOR! – Při pokusu o přístup k prvkům se záporným indexem nebo indexem větším nebo rovným délce pole, dojde k chybě za běhu programu (nikoliv při překladu) – je vyhozena výjimka ```ArrayIndexOutOfBoundsException``` - Použití pole jako parametr metody - Pole může být použito jako parametr metody (stejně jako primitivní datový typ nebo třída) - POZOR! – Stejně jako u tříd a instancí platí, že změny provedené v hodnotách pole předaného do metody jako parametr se projeví vně metody #### Výpis celého pole, inicializace stejnou hodnotou - Pro práci s poli existuje utility třída ```java.util.Arrays``` - Obsahuje statické metody (podobně jako třída ```Math```) pro práci s poli - Výpis celého pole - Metoda ```Arrays.toString()``` - Převede celé pole na řetězec, který lze následně vypsat např. metodou ```System.out.println();``` - POZOR! - Sama metoda řetězec pouze vrací, nevypisuje ho - Podobně jako metoda instance toString() u objektů - Pokud necháme vypsat pole metodou ```System.out.println()``` přímo (bez metody ```Arrays.toString()```), vypíše se pouze identifikace „instance pole“ - Podobně jako implicitní implementace metody instance ```toString()``` u objektů - Např. volání ```System.out.println(vektor1);``` vypíše např. [D@1b6d3586 (čísla za „@“ se budou při různých spuštěních lišit) - Inicializace prvků pole stejnou hodnotou - Prvky pole jsou při vytvoření implicitně inicializovány na ```0, 0.0, false``` nebo ```null``` podle datového typu pole - Pokud je potřeba inicializovat pole jinou hodnotou (stejnou pro všechny prvky), je možné využít metodu ```Arrays.fill(pole, hodnota);``` - Např. ```Arrays.fill(ciselnaRada, 1);``` naplní všechny prvky pole ```ciselnaRada``` hodnotou ```1``` - Metoda je překrytá pro pole všech základních datových typů a pole typu ```Object``` - Existuje i varianta s určením počátečního a koncového indexu vyplnění pole ```Arrays.fill(pole, indexOd, indexDo, hodnota);``` Např. ```Arrays.fill(ciselnaRada, 0, 2, 10);``` naplní první dva prvky (**počáteční index je včetně**, **koncový není včetně**) pole ```ciselnaRada``` hodnotou ```10``` #### Použití zápisu ```for - each``` - Pokud nepotřebujeme pracovat s indexem pole a stačí nám postupný přístup ke všem jednotlivým prvkům, je možné použít zkrácený zápis cyklu ```for``` (známý též jako ```for - each```) - ```for (datovýTyp prvek: pole)``` - Cyklus zaručí, že se dostane na všechny prvky – projde se celé pole od začátku do konce - V každé obrátce cyklu je v proměnné prvek následující prvek pole - Běžně se používá pro pole (a kolekce – viz předmět KIV/PPA2) objektů #### Pole jako tabulka, přepočet indexů - Tabulka - Datová struktura obsahující dvojice klíč a hodnota - Pro daný klíč můžeme získat hodnotu - Viz předměty KIV/PPA2 a KIV/PT - Pole se dá použít jako jednoduchá tabulka - Index může sloužit jako klíč - Hodnota prvku pole jako hodnota - Indexy pole začínají vždy od 0 – pokud je potřeba jiný začátek klíčů, je potřeba přepočet #### Reprezentace množiny polem - Množina - Soubor prvků (např. čísel) chápaných jako celek - Každý prvek může být obsažen v množině maximálně jednou - Pro reprezentaci množiny lze využít pole typu ```boolean[]``` - Indexy odpovídají prvkům množiny - Hodnoty prvků pole udávají, zda prvek je přítomný v množině (```true```) nebo není (```false```) ### Pole objektů - Prvkem pole můžou být kromě základních datových typů i instance - Použití se nijak neliší, jen je potřeba nezapomenout vytvořit instance jednotlivých prvků, což se u základních datových typů nedělá #### Deklarace pole objektů a jeho inicializace - Deklarace a vytvoření pole se neliší od polí základních datových typů - Je potřeba deklarovat referenční proměnnou a vytvořit novou „instanci pole“ operátorem ```new``` - ```Třída[] proměnná = new Třída[početPrvků];``` - Např. ```Vysledek[] vysledky = new Vysledek[POCET];``` - Opět je možné nejprve deklarovat referenční proměnnou a později vytvořit nové pole - Jednotlivé prvky referenční proměnné na instance třídy odpovídající typu pole - Po vytvoření pole jsou všechny implicitně inicializovány na hodnotu ```null``` - POZOR! – V tomto okamžiku (po vytvoření pole) tedy jednotlivé instance prvků neexistují – dosud nebyly vytvořeny operátorem ```new``` - Vytvoření instancí prvků pole - Instanci každého prvku je potřeba vytvořit zvlášť, typicky v cyklu ```for``` #### Přístup k prvkům pole a k proměnným a metodám instance prvků - Přístup k prvkům pole je stejný jako u polí základních datových typů pomocí indexu v hranatých závorkách „[“ a „]“ - Jednotlivé prvky jsou referenční proměnné ukazující na jednotlivé instance - Přístup k atributům a metodám instance je přes tečkovou notaci použitou nad prvkem pole ### Vícerozměrná pole - Pole může mít více rozměrů - Často se využívají dvourozměrná (např. pro uložení matic), ale mohou být i tří a vícerozměrná - Pole s více než třemi rozměry většinou nemají reálné opodstatnění - Pro určení požadovaného prvku pole je potřeba více indexů - Počet odpovídá počtu rozměrů pole - Vícerozměrné pole jako **pole polí** - Dvourozměrné pole v Javě je ve skutečnosti jednorozměrné pole referenčních proměnných, kde každá ukazuje na jednorozměrná pole (tj. „řádku“) - Díky tomu má každé jednorozměrné pole svou délku, kterou je možné zjistit, a dvourozměrné pole ji má též - Z dvourozměrného pole tak lze zjistit jeho počet řádek i sloupců - Každé jednorozměrné pole může mít jinou délku - Trojrozměrné pole v Javě je pak jednorozměrné pole referenčních proměnných, kde každá ukazuje na dvourozměrné pole, atd. #### Deklarace a vytvoření vícerozměrného pole - Deklarace referenční proměnné pro vícerozměrné pole je podobná jako pro jednorozměrné - Pouze obsahuje více prázdných párů hranatých závorek „[]“ – jeden pár pro každý rozměr pole - ```datovýTyp[][]…[] proměnná;``` Např. ```double[][] prvkyMatice;``` - Vytvoření všech rozměrů najednou - Nejběžnější použití vícerozměrných polí - Počty prvků ve všech rozměrech pole udány najednou - V případě dvourozměrného pole má každý řádek stejnou šířku - Tzv. pravoúhlé pole – pole tvoří pravoúhlý obrazec – obdélník, kvádr, teserakt, atd. - ```proměnná = new datovýTyp[počet1][počet2]…[početN];``` - Např. ```prvkyMatice = new double[vyska][sirka];``` - Vytvoření rozměrů postupně - Počty prvků v jednotlivých rozměrech udány postupně - Nejprve vytvoříme „vnější“ pole a pak do jeho jednotlivých prvků přiřadíme nové „instance“ „vnitřních“ polí - V případě dvourozměrného pole může mít každý řádek různou délku - Pole je „zubaté“ - ```proměnná = new datovýTyp[počet1][]…[];``` - POZOR! - Musí se vždy začínat rozměrem nejvíc vně (tj. první závorky zleva) - Nelze ```proměnná = new datovýTyp[][počet2]…[];``` - Vytvoření pole výčtem hodnot - I vícerozměrné pole je možné vytvořit výčtem hodnot - Pole může být pravoúhlé i „zubaté“ - Platí stejná pravidla, jako při vytváření jednorozměrného pole - Použití samotného výčtu je možné pouze při deklaraci, při pozdějším vytvoření pole je nutné použít i operátor ```new``` #### Přístup k prvkům pole - Pro přístup k jednotlivým prvkům vícerozměrného pole se používá více indexů - Počet indexů odpovídá počtu rozměrů pole - Použití méně indexů než je rozměrů pole - Při použití méně indexů se nedostaneme k prvku pole, ale k poli s menším rozměrem - Např. pokud máme dvourozměrné pole a použijeme pouze jeden index, dostaneme se k jednorozměrnému („vnitřnímu“) poli, tj. k „řádce“ pole - V okamžiku, kdy se dostaneme na „vnitřní“ pole, můžeme zjistit jeho délku - To se velmi často využívá - Funguje dobře při procházení vícerozměrného pole, i pokud je pole „zubaté“ ### Pole v paměti - Pole je ve skutečnosti instance speciální třídy a je celé uloženo na haldě (heap) - Jak to vypadá v paměti při práci s poli, je demonstrováno na příkladu s polem primitivního datového typu a na příkladu s polem objektů - **Pole nulové délky** - Pole může mít délku 0 prvků - Pak nemá žádný prvek, do kterého by šla zapsat hodnota, ale může být použitelná informace o nulové délce - Rozdíl oproti referenční proměnné pole rovné ```null``` - **Referenční proměnná pole rovná null** neukazuje na žádné pole (**žádné pole není na haldě**) - Pole nulové délky na haldě existuje a ukazuje na něj referenční proměnná, neobsahuje ale žádný prvek #### Pole primitivních datových typů v paměti - Pole primitivních datových typů ve své „instanci“ **přímo obsahuje hodnoty jednotlivých prvků**