Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Novinky jazyka Java 8 Programovací jazyk Java. Funkční rozhraní (Function interfaces) Rozhraní deklarující právě jednu abstraktní metodu (tj. vyžadující.

Podobné prezentace


Prezentace na téma: "Novinky jazyka Java 8 Programovací jazyk Java. Funkční rozhraní (Function interfaces) Rozhraní deklarující právě jednu abstraktní metodu (tj. vyžadující."— Transkript prezentace:

1 Novinky jazyka Java 8 Programovací jazyk Java

2 Funkční rozhraní (Function interfaces) Rozhraní deklarující právě jednu abstraktní metodu (tj. vyžadující implementaci právě jedné metody). Rozhraní deklarující právě jednu abstraktní metodu (tj. vyžadující implementaci právě jedné metody). Ve standardní knihovně taková rozhraní již byla, ale doposud byla především jednoúčelová ( Comparable, Runnable ) Ve standardní knihovně taková rozhraní již byla, ale doposud byla především jednoúčelová ( Comparable, Runnable ) Knihovna Javy 8 přináší balíček java.util.function, definující celou řadu obecných funkčních rozhraní. Knihovna Javy 8 přináší balíček java.util.function, definující celou řadu obecných funkčních rozhraní.

3 Funkční rozhraní v balíčku java.util.function Metody rozhraní ze skupiny Consumer jsou čistí konzumenti. Zpracují své parametry, ale nic nevrací. Consumer void accept(T value) Consumer void accept(T value) DoubleConsumer void accept(double value) DoubleConsumer void accept(double value) IntConsumer void accept(int value) IntConsumer void accept(int value) LongConsumer void accept(long value) LongConsumer void accept(long value) BiConsumer void accept(T t, U value) BiConsumer void accept(T t, U value) ObjDoubleConsumer void accept(T t, double value) ObjDoubleConsumer void accept(T t, double value) ObjIntConsumer void accept(T t, int value) ObjIntConsumer void accept(T t, int value) ObjLongConsumer void accept(T t, long value) ObjLongConsumer void accept(T t, long value)

4 Funkční rozhraní v balíčku java.util.function Metody rozhraní ze skupiny Supplier jsou naopak čistí producenti. Nemají parametry a vracejí hodnotu zadaného typu. Supplier T get() Supplier T get() BooleanSupplier boolean getAsBoolean() BooleanSupplier boolean getAsBoolean() DoubleSupplier double getAsDouble() DoubleSupplier double getAsDouble() IntSupplier int getAsInt() IntSupplier int getAsInt() LongSupplier long getAsLong() LongSupplier long getAsLong() Metody rozhraní ze skupiny Function jsou klasické funkce: zpracují svůj parametr a vrátí funkční hodnotu. Function R apply(T value) Function R apply(T value) DoubleFunction R apply(double value) DoubleFunction R apply(double value) IntFunction R apply(int value) IntFunction R apply(int value) LongFunction R apply(long value) LongFunction R apply(long value)

5 Funkční rozhraní v balíčku java.util.function Další rozhraní ze skupiny Function: ToIntFunction int applyAsInt (T value) ToIntFunction int applyAsInt (T value) ToDoubleFunction double applyAsDouble(T value) ToDoubleFunction double applyAsDouble(T value) ToLongFunction long applyAsLong (T value) ToLongFunction long applyAsLong (T value) DoubleToIntFunction int applyAsInt (double value) DoubleToIntFunction int applyAsInt (double value) DoubleToLongFunction long applyAsLong (double value) DoubleToLongFunction long applyAsLong (double value) IntToDoubleFunction double applyAsDouble(int value) IntToDoubleFunction double applyAsDouble(int value) IntToLongFunction long applyAsLong (int value) IntToLongFunction long applyAsLong (int value) LongToDoubleFunction double applyAsDouble(long value) LongToDoubleFunction double applyAsDouble(long value) LongToIntFunction int applyAsInt (long value) LongToIntFunction int applyAsInt (long value) BiFunction R apply (T t, U u) BiFunction R apply (T t, U u) ToDoubleBiFunction double applyAsDouble(T t,U u) ToDoubleBiFunction double applyAsDouble(T t,U u) ToIntBiFunction int applyAsInt (T t, U u) ToIntBiFunction int applyAsInt (T t, U u) ToLongBiFunction long applyAsLong (T t, U u) ToLongBiFunction long applyAsLong (T t, U u)

6 Funkční rozhraní v balíčku java.util.function Metody rozhraní ze skupiny UnaryOperator představují unární operátory. Jejich návratová hodnota je stejného typu jako jejich parametr. UnaryOperator T apply (T operand) UnaryOperator T apply (T operand) DoubleUnaryOperator double applyAsDouble(double operand) DoubleUnaryOperator double applyAsDouble(double operand) IntUnaryOperator int applyAsInt (int operand) IntUnaryOperator int applyAsInt (int operand) LongUnaryOperator long applyAsLong (long operand) LongUnaryOperator long applyAsLong (long operand) Metody rozhraní ze skupiny BinaryOperator představují binární operátory. Mají dva parametry, přičemž typy obou parametrů i funkční hodnoty jsou shodné. BinaryOperator T apply (T left, T right) BinaryOperator T apply (T left, T right) DoubleBinaryOperator double applyAsDouble(double left, double right) DoubleBinaryOperator double applyAsDouble(double left, double right) IntBinaryOperator int applyAsInt (int left, int right) IntBinaryOperator int applyAsInt (int left, int right) LongBinaryOperator long applyAsLong (long left, long right) LongBinaryOperator long applyAsLong (long left, long right)

7 Funkční rozhraní v balíčku java.util.function Metody rozhraní ze skupiny Predicate slouží k získání logické hodnoty odvozené z hodnoty jejich parametru. Predicate boolean test(T value) Predicate boolean test(T value) DoublePredicate boolean test(double value) DoublePredicate boolean test(double value) IntPredicate boolean test(int value) IntPredicate boolean test(int value) LongPredicate boolean test(long value) LongPredicate boolean test(long value) BiPredicate boolean test(T t, U u) BiPredicate boolean test(T t, U u)

8 Označíme-li rozhraní touto anotací, bude překladač kontrolovat, zda toto rozhraní obsahuje opravdu právě jednu abstraktní metodu. Označíme-li rozhraní touto anotací, bude překladač kontrolovat, zda toto rozhraní obsahuje opravdu právě jednu abstraktní metodu. Neabstraktních metod může mít libovolné množství. Neabstraktních metod může mít libovolné množství.

9 Lambda výrazy Představují způsob, jak definovat jako objekt nějakou část kódu, kterou bychom v jiné části programu rádi použili. Představují způsob, jak definovat jako objekt nějakou část kódu, kterou bychom v jiné části programu rádi použili. Lambda výraz můžeme uložit do proměnné funkčního typu a předávat metodám jako hodnotu parametru funkčního typu. Lambda výraz můžeme uložit do proměnné funkčního typu a předávat metodám jako hodnotu parametru funkčního typu. Překladač definuje lambda výraz jako instanci funkčního rozhraní, jehož metoda má odpovídající parametry a vrací hodnotu odpovídajícího typu (převod na příslušný typ zařídí překladač). Překladač definuje lambda výraz jako instanci funkčního rozhraní, jehož metoda má odpovídající parametry a vrací hodnotu odpovídajícího typu (převod na příslušný typ zařídí překladač).

10 Lambda výrazy Lambda výraz zapisujeme některým z následujících způsobů: Lambda výraz zapisujeme některým z následujících způsobů: (parametry) -> { příkazy } //Obecný tvar parametr -> { příkazy } //Jediný parametr (parametry) -> výraz //Tělo tvoří pouze vyhodnocovaný výraz parametr -> výraz //Jediný parametr + pouze 1 výraz Je-li vlevo jediný parametr, nemusí se dávat do kulatých závorek. Není-li žádný, nebo je-li jich více, závorky jsou potřeba. Je-li vlevo jediný parametr, nemusí se dávat do kulatých závorek. Není-li žádný, nebo je-li jich více, závorky jsou potřeba. Dokáže-li si překladač odvodit typ parametru, nemusí se uvádět. Dokáže-li si překladač odvodit typ parametru, nemusí se uvádět. Pokud se vpravo pouze vyhodnocuje nějaký výraz, nemusí se dávat do složených závorek. Pokud se vpravo pouze vyhodnocuje nějaký výraz, nemusí se dávat do složených závorek.

11 Lambda public interface MojeFunkce { public int počítej(int vstup); public interface MojeFunkce { public int počítej(int vstup); } Funkci implementující rozhraní MojeFunkce můžeme vytvořit několika způsoby: Funkci implementující rozhraní MojeFunkce můžeme vytvořit několika způsoby: MojeFunkce naDruhou = (int i) -> { return i * i; }; MojeFunkce naDruhou = (int i) -> { return i * i; }; MojeFunkce naDruhou = (i) -> i * i; MojeFunkce naDruhou = (i) -> i * i; MojeFunkce naDruhou = i -> i * i; MojeFunkce naDruhou = i -> i * i;

12 Lambda výrazy K vytvoření funkce z předchozího snímku můžeme použít i připravené funkční rozhraní IntFunction : K vytvoření funkce z předchozího snímku můžeme použít i připravené funkční rozhraní IntFunction : IntFunction naDruhou = i -> i * i; IntFunction naDruhou = i -> i * i; Další příklad: Další příklad: IntFunction odmocnina = i -> Math.sqrt(i); IntFunction odmocnina = i -> Math.sqrt(i); Příklady použití: Příklady použití: int mocnina = naDruhou.apply(5);// 25 int mocnina = naDruhou.apply(5);// 25 double o = odmocnina.apply(9);// 3 double o = odmocnina.apply(9);// 3

13 Odkazy na metody a konstruktory Pomocí dvou dvojteček (::) se můžeme odkazovat na metody nebo konstruktory a konvertovat je na funkce, resp. funkční rozhraní. Namísto Pomocí dvou dvojteček (::) se můžeme odkazovat na metody nebo konstruktory a konvertovat je na funkce, resp. funkční rozhraní. Namísto Supplier dodavatel = () -> System.currentTimeMillis(); napíšeme napíšeme Supplier dodavatel = System::currentTimeMillis; a v obou případech použijeme např. takto: a v obou případech použijeme např. takto: long čas = dodavatel.get();

14 Odkazy na metody a konstruktory Další příklady použití dvou dvojteček: Další příklady použití dvou dvojteček: Pro metody instance: Pro metody instance: Date datum = new Date(); Supplier dodavatel = datum::getTime; long čas = dodavatel.get(); Date datum = new Date(); Supplier dodavatel = datum::getTime; long čas = dodavatel.get(); Pro konstruktory: Pro konstruktory: Function generátorData = Date::new; Date datum = generátorData.apply(System.currentTimeMillis()); Function generátorData = Date::new; Date datum = generátorData.apply(System.currentTimeMillis()); Metoda nebo konstruktor musí mít samozřejmě vhodný počet a typ parametrů, které odpovídají požadovanému funkčnímu rozhraní. Výše byl zavolán konstruktor public Date(long date). Metoda nebo konstruktor musí mít samozřejmě vhodný počet a typ parametrů, které odpovídají požadovanému funkčnímu rozhraní. Výše byl zavolán konstruktor public Date(long date).

15 Výchozí metody rozhraní V Javě 8 můžou rozhraní obsahovat i neabstraktní metody, tedy metody, obsahující implementaci, ne jen hlavičku. Pro označení těchto metod se používá klíčové slovo default. V Javě 8 můžou rozhraní obsahovat i neabstraktní metody, tedy metody, obsahující implementaci, ne jen hlavičku. Pro označení těchto metod se používá klíčové slovo default. Třída, která implementuje toto rozhraní, tak získá i tuto funkcionalitu – jedná se tak v podstatě o vícenásobnou dědičnost. Třída, která implementuje toto rozhraní, tak získá i tuto funkcionalitu – jedná se tak v podstatě o vícenásobnou dědičnost. Užitečné je to mj. v souvislosti s funkčními rozhraními a lambdami. Pomocí lambda výrazu definujeme určitou funkcionalitu, ale koncový uživatel daného rozhraní může volat jinou metodu (výchozí, definovanou v rozhraní), která tu metodu z lambdy obaluje, případně dělá něco úplně jiného (např. skládá více funkčních rozhraní dohromady – viz dále). Užitečné je to mj. v souvislosti s funkčními rozhraními a lambdami. Pomocí lambda výrazu definujeme určitou funkcionalitu, ale koncový uživatel daného rozhraní může volat jinou metodu (výchozí, definovanou v rozhraní), která tu metodu z lambdy obaluje, případně dělá něco úplně jiného (např. skládá více funkčních rozhraní dohromady – viz dále).

16 Funkční rozhraní Function z balíčku java.util.function Přehled metod: Přehled metod: Modifikátor a typMetoda a popis default Function compose(Function before) Vrátí složenou funkci, která na svůj vstup nejprve aplikuje funkci before a pak aplikuje na výsledek funkci předanou jako argument. default Function andThen(Function after) Vrátí složenou funkci. Nejprve se provede funkce předaná jako argument, na výsledek se aplikuje funkce after. Oproti compose volá tedy funkce v opačném pořadí. Rapply(T t) Aplikuje funkci na zadaný argument.

17 Funkční rozhraní Function z balíčku java.util.function Ukázky výchozích metod: Ukázky výchozích metod: Function přičtiJedna = a -> a + 1; Function vynásobDvěma = a -> a * 2; int x = vynásobDvěma.compose(přičtiJedna).apply(5); // (5 + 1) × 2 = 12 int y = přičtiJedna.compose(vynásobDvěma).apply(5); // (5 × 2) + 1 = 11 int z = vynásobDvěma.andThen(přičtiJedna).apply(5); // (5 × 2) + 1 = 11

18 Predikáty Predikát je zde funkce, jejímž oborem hodnot je boolean. Definiční obor je daný generickým typem a může to být cokoli. Pomocí metody Predicate.test(T t) vyhodnocujeme pravdivost predikátu nad zadanou hodnotu. Predikát je zde funkce, jejímž oborem hodnot je boolean. Definiční obor je daný generickým typem a může to být cokoli. Pomocí metody Predicate.test(T t) vyhodnocujeme pravdivost predikátu nad zadanou hodnotu. Vytvoření predikátů: Vytvoření predikátů: Predicate neníNull = Objects::nonNull; Predicate správnáDélka = s -> s.matches(".{8,32}"); Predicate obsahujeČíslici = s -> s.matches(".*[0-9].*"); Predicate obsahujeVelkéPísmeno = s -> s.matches(".*[A-Z].*");

19 Predikáty Stejně jako funkce – i predikáty můžeme díky výchozím metodám skládat: Stejně jako funkce – i predikáty můžeme díky výchozím metodám skládat: Predicate složenýPredikát = neníNull.and(správnáDélka).and(obsahujeČíslici.or (obsahujeVelkéPísmeno)); a složený predikát vyhodnotit: a složený predikát vyhodnotit: boolean a = složenýPredikát.test("Abcd123"); // = false boolean b = složenýPredikát.test("abcdefgh"); // = false boolean c = složenýPredikát.test("abcdefgh123"); // = true boolean d = složenýPredikát.test("Abcdefgh"); // = true

20 Datové proudy Při práci s klasickými poli a kolekcemi se používají především externí (sekvenční) iterátory Při práci s klasickými poli a kolekcemi se používají především externí (sekvenční) iterátory Program požádá kolekci o iterátor, který pak v cyklu žádá o další instanci, s níž provede požadovanou operaci. Program požádá kolekci o iterátor, který pak v cyklu žádá o další instanci, s níž provede požadovanou operaci. Proud se chová jako objekt využívající interní (dávkové) iterátory provádějící s iterovanými objekty operace definované lambda-výrazy. Proud se chová jako objekt využívající interní (dávkové) iterátory provádějící s iterovanými objekty operace definované lambda-výrazy. Program definuje, jaká data se do proudu zařadí, resp. jak proud ona data získá. Program definuje, jaká data se do proudu zařadí, resp. jak proud ona data získá. Nezávisle na tom se definuje, jak se těmito daty bude pracovat. Nezávisle na tom se definuje, jak se těmito daty bude pracovat.

21 Analogie: výrobní linka Na počátku je vstup Na počátku je vstup V případě výrobního pásu je to sklad dílů, v případě proudu to bude zdroj dat – většinou nějaký zdrojový kontejner. V případě výrobního pásu je to sklad dílů, v případě proudu to bude zdroj dat – většinou nějaký zdrojový kontejner. Zdrojem ale může být i generátor, který vytváří data na požádání Zdrojem ale může být i generátor, který vytváří data na požádání Pracoviště Pracoviště Podél výrobního pásu jsou připravená pracoviště, na nichž zaškolení dělníci provádějí jednotlivé operace. Podél výrobního pásu jsou připravená pracoviště, na nichž zaškolení dělníci provádějí jednotlivé operace. V případě proudu nahradíme dělníky metodami (přesněji lambda výrazy), které s příchozím objektem provedou požadovanou operaci V případě proudu nahradíme dělníky metodami (přesněji lambda výrazy), které s příchozím objektem provedou požadovanou operaci Zpracovaný objekt pokračuje po proudu k dalšímu pracovišti Zpracovaný objekt pokračuje po proudu k dalšímu pracovišti Výsledky Výsledky Na konci výrobního pásu „vypadne“ hotový výrobek. Na konci výrobního pásu „vypadne“ hotový výrobek. Na konci proudu obdržíme požadovaný výsledek. Na konci proudu obdržíme požadovaný výsledek.

22 Odchylky od kolekcí a polí Neblokují si žádnou paměť pro zpracovávaná data; data od někud „přitékají“, „pracoviště“ je zpracuje a pošle dál. Neblokují si žádnou paměť pro zpracovávaná data; data od někud „přitékají“, „pracoviště“ je zpracuje a pošle dál. Ve většině případů neovlivňují zdrojová data. Ve většině případů neovlivňují zdrojová data. Naplánované operace se chovají obdobně jako dělníci u pásu: nehrnou se do skladu (kontejneru), aby v něm data zpracovaly, ale počkají si, až k nim zpracovávaný objekt po proudu „přiteče“ a pak se o něj postarají. Naplánované operace se chovají obdobně jako dělníci u pásu: nehrnou se do skladu (kontejneru), aby v něm data zpracovaly, ale počkají si, až k nim zpracovávaný objekt po proudu „přiteče“ a pak se o něj postarají. Nezajímají se o to, zda je vstup dat konečný (klasický kontejner), nebo nekonečný. Nezajímají se o to, zda je vstup dat konečný (klasický kontejner), nebo nekonečný.

23 Datové proudy Výhody datových proudů: Z programu zmizí pomocný kód, který měl na starosti řízení iterací, a zpřehlední se tak popis akcí, které se mají se zpracovávanými objekty udělat. Z programu zmizí pomocný kód, který měl na starosti řízení iterací, a zpřehlední se tak popis akcí, které se mají se zpracovávanými objekty udělat. Objeví-li se v budoucnu nějaké propracovanější techniky paralelizace prováděných činností, není třeba upravovat část programu řešící aplikační logiku, ale stačí pouze vylepšit knihovnu proudů a tím se automaticky zefektivní zpracování programů, které tyto proudy využívají. Objeví-li se v budoucnu nějaké propracovanější techniky paralelizace prováděných činností, není třeba upravovat část programu řešící aplikační logiku, ale stačí pouze vylepšit knihovnu proudů a tím se automaticky zefektivní zpracování programů, které tyto proudy využívají.

24 Ukázka zpracování datového proudu List cislaSlovne = Arrays.asList("100", "200", "300", "400"); Integer[] cisla = cislaSlovne.stream().stream().map(Integer::parseInt).map(Integer::parseInt).filter(num -> num num < 300).toArray(Integer[]::new);.toArray(Integer[]::new); for (int i: cisla) { System.out.print(i + ", "); } Vypíše: 100, 200,

25 Práce s obsahem proudu Obsah proudu můžeme během práce filtrovat použitím metody Stream filter(Predicate predicate) Obsah proudu můžeme během práce filtrovat použitím metody Stream filter(Predicate predicate) Proudy můžeme také řadit: Proudy můžeme také řadit: Stream sorted() Stream sorted(Comparator comparator) Prvky proudu můžeme konvertovat na jiný typ: Prvky proudu můžeme konvertovat na jiný typ: Stream map(Function mapper) Stream map(Function mapper) DoubleStream mapToDouble(ToDoubleFunction mapper) IntStream mapToInt (ToIntFunction mapper) LongStream mapToLong (ToLongFunction mapper)

26 Možnosti získání proudu Z kolekcí prostřednictvím metod stream() a parallelStream() Z kolekcí prostřednictvím metod stream() a parallelStream() Z polí prostřednictvím metody Arrays.stream(Object[]) Z polí prostřednictvím metody Arrays.stream(Object[]) Z továrních metod třídy Stream, např.: Z továrních metod třídy Stream, např.: Stream of(Object[]) IntStream range(int, int) Stream iterate(Object, UnaryOperator) Řádky souboru lze získat metodou BufferedReader.lines() Řádky souboru lze získat metodou BufferedReader.lines() Proud náhodných čísel lze získat metodou Random.ints() Proud náhodných čísel lze získat metodou Random.ints() Proud položek v ZIP-souboru lze získat metodou JarFile.stream() Proud položek v ZIP-souboru lze získat metodou JarFile.stream()

27 Další novinky Nové API pro datum a čas (balíček java.time ) – umožňuje např. práci s časovými zónami (lokální datum a čas, internacionalizace aplikace), poskytuje vláknově bezpečné (thread- safe) objekty. Nové API pro datum a čas (balíček java.time ) – umožňuje např. práci s časovými zónami (lokální datum a čas, internacionalizace aplikace), poskytuje vláknově bezpečné (thread- safe) objekty. Paralelní řazení polí – využití víceprocesorových počítačů a vícejádrových procesorů. Paralelní řazení polí – využití víceprocesorových počítačů a vícejádrových procesorů. Zabezpečení – nativní podpora TLS (Transport Layer Security neboli TLS jsou protokoly, které umožňují zabezpečenou komunikaci na internetu), nativní podpora NSA Suite B Cryptographic Algorithms. (Balíček šifrovacích algoritmů, které pomáhají uchránit data při transportu přes nezabezpečený internet. Tyto algoritmy jsou velmi silné a jejich prolomení je v podstatě nemožné.) Zabezpečení – nativní podpora TLS (Transport Layer Security neboli TLS jsou protokoly, které umožňují zabezpečenou komunikaci na internetu), nativní podpora NSA Suite B Cryptographic Algorithms. (Balíček šifrovacích algoritmů, které pomáhají uchránit data při transportu přes nezabezpečený internet. Tyto algoritmy jsou velmi silné a jejich prolomení je v podstatě nemožné.) Nástroj pro zpracování (engine, interpreter) jazyka JavaScript s názvem Nashorn. Nástroj pro zpracování (engine, interpreter) jazyka JavaScript s názvem Nashorn.

28 What's New in JDK html html html html


Stáhnout ppt "Novinky jazyka Java 8 Programovací jazyk Java. Funkční rozhraní (Function interfaces) Rozhraní deklarující právě jednu abstraktní metodu (tj. vyžadující."

Podobné prezentace


Reklamy Google