220 lines
14 KiB
Markdown
220 lines
14 KiB
Markdown
# 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é“
|
||
- Příklady přístupu k prvkům pole a k „vnitřním“ polím kvůli jejich délce je na
|
||
- Deklarace a vytvoření pole ```jednotkovaMatice```
|
||
- Kompletní příklad na použití dvojrozměrných polí k násobení matic (v kombinaci s objekty)
|
||
- Použitá třída ```Matice```
|
||
|
||
### 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ů**
|
||
|