# 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ů**

