O programování 09 - Pokročilé využití streamů a funkcionálního přístupu v Java 8
Protože se jedná se o poslední díl o funkcionálních rysech Javy 8, uvedu zde pár spíše spolu nesouvisejících poznámek.
Při zkoumání funkcionální rysů Java 8 jsem pročetl dost blogů a asi nejvíce mi dal tento.
V dosavadních úvahách jsem používal pouze metody, nedostal jsem se k vyzkoušení predikátů, konzumerů ani producentů, což jsou speciální varianty metod (bez vstupních nebo výstupních parametrů). Ono na úrovni spíše teoretických úvah je arita metod irelevantní.
Pravá síla funkcionálního přístupu vynikne na složitějších konstrukcích, na těch jednoduchých je to často kontraproduktivně matoucí. V tom mi zase pomohl tento článek, kde mě zaujal zápis typu:
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
To je opravdu celkem čitelný deklarativní zápis toho, co se má s daty dělat a intuitivně chápu, co zápis znamená (až na to nešťastné stream na začátku - opravdu by to bez něj nešlo?).
Ovšem na to, abych takto dokázal psát (a hlavně myslet), bych potřeboval trochu cviku a praxe, protože jsem zvyklý psát kód spíše ve formě sekvenčního algoritmu, tedy "procedurálně" a ne "funkcionálně". Sice jsem programoval 10 let v SQL a PL/SQL ale přesto (nebo právě proto) mi nepřijde, že je funkcionální přístup podobný SQL, což tvrdí někteří mí kolegové. Uznávám, že funkcionální i databázový přístup je podobný v tom, že deklarativně říkám CO a ne JAK, ale tím veškerá podobnost podle mě končí. SQL je založeno na relační algebře kdežto funkcionální programování na lambda kalkulu, což jsou pokud vím dosti odlišná paradigmata.
I když ... v poslední přednášce Algebry II představil docent Polák způsob, jak algebraicky reprezentovat termy i způsob, jak je vyhodnocovat čistě algebraickými prostředky. Tím představil alternativu nebo spíše jiný pohled na predikátovou logiku, resp. z ní odvozené systémy vyhodnocování termů používané jako (teoretický) základ (nejen) funkcionálního programování - pokud si to po cca dvaceti letech vybavuji správně, oprašovat letité poznámky kvůli tomu nebudu. A ze stejného důvod po mě nechtějte formálně přesnou a správnou formulaci toho, co mám vlastně na mysli.
Každopádně jsem byl tehdy celkem překvapen, jak se zdánlivě totálně nesouvisející oblasti (algebra, logika a překladače) potkaly celkem elegantním a pochopitelným způsobem. Takže možná není zas tak velký rozdíl mezi koncepty SQL a funkcionálního programování.
Ale to jsme poněkud odbočili, vraťme se zpět k Java 8, kde mě ještě zaujala existence tříd IntStream, LongStream a DoubleStream. Jejich metoda range() může úplně nahradit použití cyklu, viz následující příklad:
IntStream.range(1, 4).forEach(System.out::println);
Tímto končím s funkcionálními rysy Java 8, ještě si nechávám v zásobě paralelní streamy. A příště už bude čas na něco úplně jiného.
Ale Python to nebude :)
- O programování 01 - Úvod
- O programování 02 - Efektivita funkcionálního přístupu v Java 8
- O programování 03 - Přehlednost funkcionálního zápisu v Java 8
- O programování 04 - Java Microbenchmark Harness
- O programování 05 - Další varianty Javovské implementace foreach
- O programování 06 - Návrhové vzory - síla i slabina Javy
- O programování 07 - Funkce jako argument aneb od factory k lambdě v Javě
- O programování 08 - Jak v Javě předat metodu, která bude mít různé parametry
- O programování 10 - Java a inspirace v Ruby
- O programování 11 - Minimalistické programy a Java
- O programování 12 - Paralelní implementace násobení matic v Java - úvod