FAV-ZCU/KIV PPA1/8. Pole.md

217 lines
14 KiB
Markdown
Raw Permalink Normal View History

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