Seminář 11
Obsah
- Lokální a anonymní třídy
- Funkční rozhraní
- Lambda výrazy
- Stream API
Lokální a anonymní třídy
- Již známe vnitřní třídy (třída deklarovaná uvnitř jiné třídy).
- Existují i tzv. lokální třídy, definované uvnitř nějakého bloku pro lokální použití.
- Nadto máme i jejich anonymní verze pro jednorázové použití - rovnou vytváříme jedinou instanci.
- Tedy:
- Vntřní (třída ve třídě)
- vs lokální (třída v libovolném bloku)
- vs anonymní (nepojmenovaná lokální, rovnou instanciovaná).
Funkční rozhraní
- Za chvíli uvidíme lambda výrazy v javě.
- Na ty lze pohlížet jako na zkratky za tzv “funkční rozhraní”.
- Funkční rozhraní ≈ rozhraní s jedinou abstratkní metodou - hlavičkou funkce, kterou reprezentuje.
- Nejprve funkční rozhraní pro nejběžnější typy anonymních funkcí.
- Co si z toho odnést? (A, B, C jsou nějaké objektové typy, () je prázdný typ)
- Supplier<A>: () → A
- Consumer<A>: A → ()
- Callable<A>: () → A throws Exception
- Function<A,B>: A → B
- BiFunction<A,B,C>: A, B → C
- Predicate<A>: A → boolean
- UnaryOperator<A>: A → A
- BinaryOperator<A>: A, A → A
- Dále existují specifické verze pro nejčastější typy argumentů.
- Navíc Runnable:
- Runnable: () → ()
Vlastní funčkní rozhraní
- Lze vytvářet vlastní funkční rozhraní:
- Jediná abstraktní metoda (to je deklarace funkce, kterou budeme dodávat),
- Případný statický obsah,
- Je vhodné rozhraní označit anotací
@FunctionalInterface
.
Lambda výrazy
- Obvyklý tutoriál.
- Anonymní funkce.
- Tzv. first class citizen (≈ lze s nimi pracovat jako s daty):
- lze je vracet z funkcí,
- lze je předávat jako argumenty,
- lze je ukládat do proměnných a datových struktur.
- Typ anonymní funkce:
- Typ každé anonymní funkce je nějaké funkční rozhraní.
- Každé funkční rozhraní reprezentuje typ pro anonymní funkce (signatura oné jediné abstraktní metody).
- Anonymní funkce lze používat jen v kontextu, kde jejich typ lze odvodit (více např. zde).
- Tedy chcete-li anonymní funkci předat jako parametr nebo uložit do proměnné, použijte jako typ právě odpovídající funkční rozhraní.
Jak to spolu všechno souvisí
- Lambda výraz
- Anonymní implementace funknčího rozhraní
- Obecná anonymní třída
- Rozdíly?
- Co je k čemu?
Stream API
- Práce s “kolekcemi” ve funkcionálním stylu:
- líné vyhodnocování (nic se nevyhodnotí, dokud to není nutné)
- imutabilita (jen strukturální !),
- implicitní paralelismus (stream není kolekce, má jiná pravidla),
- pipeline (operace na streamu lze řetězit - mocné v kombinaci s předchozími vlastnostmi),
- agregační operace vs iterator (stream není Iterable).
- Dokumentace stream API.
- Tutoriál ke stream API.
Ukázka
Zpětná vazba
- Jaké byly semináře?
- Máte-li další podněty, napište mi je mailem nebo využijte pravidelnou evaluaci.
- Díky.
Úkol
- Upravte svou RPN kalkulačku tak, aby vhodně využívala funkčních rozhraní, lambda výrazů a anonymních tříd.
- Upravte svou RPN kalkulačku tak, aby vše bylo řádně zdokumentováno a otestováno.
- Napište následující metody, které za použití třídy Files nejprve načtou textový soubor z cesty
p
do streamu a poté vypočítají uvedenou transformaci/agregaci tohoto streamu:Optional<Double> average(Path p)
pro průměr čísel z jednotlivých řádků souboru;Optional<Double> evensAverage(Path p)
pro průměr sudých čísel z jednotlivých řádků souboru (tj. lichá čísla do výsledku nepočítáme);Optional<Double> evenMultsOfThreeAverage(Path p)
pro průměr sudých násobků 3 z jednotlivých řádků souboru (tj. jiná čísla než sudé násobky 3 do výsledku nepočítáme);String linesString(Path p, String delimeterWord)
pro všechny řádky spojené do jednohoStringu
oddělené pomocídelimeterWord
;Stream<String> palindroms(Path p)
pro Stream obsahující palindormy vytvořené z původních řádků zřetězením s jejich kopií pozpátku (např. řádekahoj
transformuje na řádekahojjoha
).
double
. - Výsledek odevzdejte emailem s předmětem jj1-11 na tomas.urbanec@upol.cz do 30.12.2023, 23:59 CEST. Odevzdávejte pouze zdrojové kódy, nikoliv celé projekty vygenerované IDE.