Lekce 11 - Pole v Javě
V předešlém cvičení, Řešené úlohy k 9.-10. lekci Javy, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním Java tutoriálu si představíme datovou strukturu pole a vyzkoušíme si, co všechno umí.
Pole
Představte si, že si chcete uložit nějaké údaje o více prvcích.
Například chcete v paměti uchovávat 10 čísel, políčka šachovnice nebo
jména padesáti uživatelů. Asi vám dojde, že v programování bude nějaká
lepší cesta, než začít bušit proměnné uzivatel1
,
uzivatel2
, ... až uzivatel50
. Nehledě na to, že
jich může být třeba 1000! A jak by se v tom potom hledalo? Brrr, takhle ne
Pokud potřebujeme uchovávat větší množství proměnných
stejného typu, tento problém nám řeší pole.
Můžeme si ho představit jako řadu přihrádek, kde v každé máme uložený
jeden prvek. Přihrádky jsou očíslované tzv. indexy, první
má index 0
:
(Na obrázku je vidět pole osmi čísel.)
Programovací jazyky se velmi liší v tom, jak s polem pracují. V některých jazycích (zejména starších, kompilovaných) nebylo možné za běhu programu vytvořit pole s dynamickou velikostí (např. mu dát velikost dle nějaké proměnné). Pole se muselo deklarovat s konstantní velikostí přímo ve zdrojovém kódu. Toto se obcházelo tzv. pointery a vlastními datovými strukturami, což často vedlo k chybám při manuální správě paměti a nestabilitě programu (např. v C++). Naopak některé interpretované jazyky umožňují nejen deklarovat pole s libovolnou velikostí, ale dokonce tuto velikost na již existujícím poli měnit (např. PHP). My víme, že Java je virtuální stroj, tedy cosi mezi kompilerem a interpretem. Proto můžeme pole založit s velikostí, kterou dynamicky zadáme až za běhu programu, ale velikost existujícího pole modifikovat nemůžeme. Lze to samozřejmě obejít nebo použít jiné datové struktury, ale k tomu se dostaneme.
Výhody pole
Možná vás napadá, proč se tu zabýváme s polem, když má evidentně mnoho omezení a existují lepší datové struktury. Odpověď je prostá: pole je totiž jednoduché. Nemyslím pro nás na pochopení (to také), ale zejména pro Javu. Rychle se s ním pracuje, protože prvky jsou v paměti jednoduše uloženy za sebou, všechny prvky zabírají stejně místa a rychle se k nim přistupuje. Mnoho vnitřních funkčností v Javě proto nějak pracuje s polem nebo pole vrací. Je to klíčová struktura.
Pro hromadnou manipulaci s prvky pole se používají cykly.
Práce s polem
V několika dalších krocích si deklarujeme pole, následně ho založíme a na závěr naplníme vlastními daty.
Deklarace pole
Pole deklarujeme pomocí hranatých závorek:
int[] cisla;
Slovo cisla
je samozřejmě název naší proměnné. Nyní jsme
však pouze deklarovali, že v proměnné bude pole prvků typu
int
. Nyní ho musíme založit, abychom ho mohli používat. Pole
pojmenováváme vždy množným číslem podle toho, co pole
obsahuje.
Založení pole
K založení použijeme klíčové slovo new
, které zatím
nebudeme vysvětlovat. Spokojme se s tím, že je to kvůli tomu, že je pole
referenční datový typ (můžeme chápat jako složitější typ):
int[] cisla = new int[10];
Nyní máme v proměnné cisla
pole o velikosti deseti čísel
typu int
.
Přístup k prvkům pole
K prvkům pole potom přistupujeme přes hranatou závorku, pojďme na první
index (tedy index 0
) uložit číslo 1
:
int[] cisla = new int[10]; cisla[0] = 1;
Naplnění pole cyklem
Plnit pole ručně daty by bylo příliš pracné, použijeme
cyklus a naplníme si pole čísly od 1
do
10
. K naplnění použijeme cyklus for
:
int[] cisla = new int[10]; for (int i = 0; i < 10; i++) { cisla[i] = i + 1; }
Abychom pole vypsali, můžeme za předchozí kód připsat:
{JAVA_CONSOLE}
int[] cisla = new int[10];
for (int i = 0; i < 10; i++) {
cisla[i] = i + 1;
}
for (int i = 0; i < cisla.length; i++) {
System.out.print(cisla[i] + " ");
}
{/JAVA_CONSOLE}
Všimněte si, že pole má konstantu length
, kde
je uložena jeho délka, tedy počet prvků.
Výstup programu:
Konzolová aplikace
1 2 3 4 5 6 7 8 9 10
Cyklus foreach
Můžeme použít zjednodušenou verzi cyklu pro práci s kolekcemi, známou jako tzv. foreach. Ten projede všechny prvky v poli a jeho délku si zjistí sám. Jeho syntaxe je následující:
for (datovytyp promenna : kolekce) { // příkazy }
Cyklus projede prvky v kolekci (to je obecný název pro struktury, které obsahují více prvků, u nás to bude pole) postupně od prvního do posledního. Prvek máme v každé iteraci cyklu uložený v dané proměnné.
Přepišme tedy náš dosavadní program pro cyklus foreach. Cyklus foreach nemá řídící proměnnou, není tedy vhodný pro vytvoření našeho pole a použijeme ho jen pro výpis:
{JAVA_CONSOLE}
int[] cisla = new int[10];
for (int i = 0; i < 10; i++) {
cisla[i] = i + 1;
}
for (int cislo : cisla) {
System.out.print(cislo + " ");
}
{/JAVA_CONSOLE}
Výstup programu:
Konzolová aplikace
1 2 3 4 5 6 7 8 9 10
Naplnění pole ručně
Pole samozřejmě můžeme naplnit ručně a to i bez toho, abychom dosazovali postupně do každého indexu. Použijeme k tomu složených závorek a prvky oddělujeme čárkou:
String[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Pole často slouží k ukládání mezivýsledků, které se potom dále v programu používají. Když něco potřebujeme 10x, tak to nebudeme 10x počítat, ale spočítáme to jednou a uložíme do pole, odtud poté výsledek jen načteme.
Metody na třídě Arrays
Java nám poskytuje třídu Arrays
, která obsahuje pomocné
metody pro práci s poli.
K jejímu použití je třeba ji naimportovat:
import java.util.Arrays;
Pojďme se na metody podívat:
Metoda sort()
Jak již název napovídá, metoda sort()
nám pole seřadí.
Její jediný parametr je pole, které chceme seřadit. Metoda je dokonce tak
chytrá, že pracuje podle toho, co máme v poli uložené. Řetězce třídí
podle abecedy, čísla podle velikosti. Zkusme si seřadit a vypsat naši
rodinku Simpsonů:
package onlineapp;
import java.util.Arrays;
public class Program {
public static void main(String[] args) {
String[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
Arrays.sort(simpsonovi);
for (String simpson : simpsonovi) {
System.out.print(simpson + " ");
}
}
}
Výstup programu:
Konzolová aplikace
Bart Homer Lisa Maggie Marge
Zkuste si udělat pole čísel a vyzkoušejte si, že to opravdu funguje i pro ně.
Metoda binarySearch()
Když pole seřadíme, umožní nám v něm Java vyhledávat prvky. Metoda
binarySearch()
nám vrátí index prvního nalezeného prvku. V
případě nenalezení prvku vrátí metoda hodnotu -1
. Metoda bere
dva parametry, prvním je pole, druhým hledaný prvek. Umožníme uživateli
zadat jméno Simpsona a poté zkontrolujeme, zda je to opravdu Simpson:
package onlineapp;
import java.util.Arrays;
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] simpsonovi = {"Homer", "Marge", "Bart", "Lisa", "Maggie"};
System.out.println("Zadej Simpsona (z rodiny Simpsonů): ");
String simpson = scanner.nextLine();
Arrays.sort(simpsonovi);
int pozice = Arrays.binarySearch(simpsonovi, simpson);
if (pozice >= 0) {
System.out.println("Jo, to je Simpson!");
}
else {
System.out.println("Hele, tohle není Simpson!");
}
}
}
Pole musí být opravdu setříděné, než metodu zavoláme!
Výstup programu:
Konzolová aplikace
Zadej Simpsona (z rodiny Simpsonů):
Homer
Jo, to je Simpson!
Metoda copyOfRange()
Metoda copyOfRange()
již podle názvu zkopíruje část pole do
jiného pole. Prvním parametrem je zdrojové pole, druhým startovní pozice a
třetím konečná pozice. Metoda vrací nové pole, které je výsekem
původního pole.
Proměnná délka pole
Říkali jsme si, že délku pole můžeme definovat i za běhu programu, pojďme si to zkusit:
Scanner scanner = new Scanner(System.in); System.out.println("Ahoj, spočítám ti průměr známek. Kolik známek zadáš?"); int pocetZnamek = Integer.parseInt(scanner.nextLine()); int[] znamky = new int[pocetZnamek]; for (int i = 0; i < pocetZnamek; i++) { System.out.printf("Zadejte %d. číslo:%n", i + 1); znamky[i] = Integer.parseInt(scanner.nextLine()); } // spočítání průměru int soucet = 0; for (int znamka : znamky) { soucet += znamka; } double prumer = soucet / (double)znamky.length; System.out.printf("Průměr tvých známek je: %.1f", prumer);
Příkaz soucet += znamka
je pouze zkrácený
zápis pro soucet = soucet + znamka
.
Při výpisu jsme použili výraz %n
. Tento výraz
nám zajistí, ať máme nezávisle na platformě nový řádek. Na platformě
MacOS to například automaticky nahradí za znaky \r
.
Alternativně můžeme využít například znaky \n
, ale je
možné, že to na nějaké platformě nový řádek nevytvoří.
Výstup programu:
Konzolová aplikace
Ahoj, spočítám ti průměr známek. Kolik známek zadáš?
5
Zadejte 1. číslo: 1
Zadejte 2. číslo: 2
Zadejte 3. číslo: 2
Zadejte 4. číslo: 3
Zadejte 5. číslo: 5
Průměr tvých známek je: 2.6
Tento příklad by šel samozřejmě napsat i bez použití pole, ale co kdybychom chtěli spočítat např. medián? Nebo vypsat zadaná čísla pozpátku? To už by bez pole nešlo. Takhle máme k dispozici v poli původní hodnoty a můžeme s nimi neomezeně a jednoduše pracovat.
U výpočtu průměru si všimněte, že při dělení je před jedním
operandem napsáno (double)
, tím říkáme, že chceme dělit
neceločíselně. Při dělení 3 / 2
dostaneme výsledek
1
a při dělení 3 / 2.0F
dostaneme výsledek
1.5
. Druhé číslo musí být vždy reálné, aby Java dělila
taktéž reálně (na více desetinných míst).
To by pro dnešek stačilo, můžete si s polem hrát.
V následujícím kvízu, Kvíz - Podmínky, cykly a pole v Javě, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1347x (71.07 kB)
Aplikace je včetně zdrojových kódů v jazyce Java