Nowe wydanie Javy JDK 15 z 15 września 2020 zawiera wiele nowych ciekawych i poprawionych funkcji.
JEP 339: Edwards-Curve Digital Signature Algorithm (EdDSA)
Nowe wydanie Javy JDK 15 z 15 września 2020 zawiera wiele nowych ciekawych i poprawionych funkcji.
JEP 339: Edwards-Curve Digital Signature Algorithm (EdDSA)
Typy wyjątków
BiPredicate daje nam możliwość sprawdzenia warunków dla 2 argumentów. Poniżej przykład użycia:
Przykład użycia funkcji gdzie na wejściu podajemy jeden argument typu Integer. W wyniku wykonania funkcji zwracamy mnożenie arguemntu prez samego siebie. Czyli jest to
function <Integer, Integer> f = i -> i*i
BiFunkcja w odróżnieniu od funkcji przedstawionej powyżej może na wejściu przyjąć 2 wartości i je przetworzyć. Poniżej przykład użycia:
Przykład użycia konsumenta gdzie na wejściu przyjmujemy argument typu String. Następnie przekazujmy go do funkcji sopen.
Consumer<String> c = a -> sopen(a)
BiKonsument może przetworzyć na wejściu 2 argumenty.
Zwraca (dostarcza) wartość typu Date.
Supplier<Date> s = () -> new Date();
W tym spisie zebrałem krótkie informacje na temat Reactive streams i project Reactor. Są również bardzo ciekawe linki, które w szybki sposób pomogą Ci wskoczyć na poziom umożliwiający programowanie z użyciem wspomnianych bibliotek.
Elementy występujące w Reactive streams możemy podzielić na:
Kiedy Subscriber zaczyna subskrybować Publisher zostaje utworzona Subskrybcja. Subskrybcja jest następnie przesyłana do metody onSubscribe.
Subscriber wysyła rządanie o elementy za pomocą onSubscribe i Publisher wysyła je. W przypadku gdy Publisher nie ma już więcej elementów do wysłania wywołana zostaje metoda onComplete.
W momencie gdy wystąpi błąd, subsrkypcja zostaje przerwana i zostaje wywołana metoda onError.
src: https://github.com/reactive-streams/reactive-streams-jvm
Są to implementacje, interfejsu Publisher. Powyższe elementy muszą zostać zasubskrybowane. Można na nich operować za pomocą metod np:
src:
package functional.staticMethods;
import java.util.function.Predicate;
przykład implementacji interfejsu funkcjonalnego Predicate przyjmującego parametr generyczny typu Integer
public class PredicateSampleInt {
public static void main(String[] args) {
Predicate<Integer> p = i -> i>10;
System.out.println(p.test(100));
System.out.println(p.test(9));
inny przykład implementacji Predicate przyjmującego parametr generyczny typu String
Poniżej przedstawiam listę różnic pomiędzy interfejsem z metodą domyślną a klasą abstrakcyjną w Java 1.8
Interfejs z metodą domyślną:
1. Wewnątrz interfejsu każda zmienna jest zawsze public static final nie można zadeklarować instancji zmiennej.
2. Interfejs nie przechowuje stanu obiektu
3. Wewnątrz interfejsu nie można deklarować konstruktora
4. Wewnątrz interfejsu nie można deklarować instancji oraz bloków statycznych (static blocks)
5. Interfejs funkcjonalny z metodą domyślną może zawierać wyrażenia lambda
6. Wewnątrz interfejsu nie można nadpisywać metod klasy obiektowej (object class methods)
Klasa abstrakcyjna:
1. Wewnątrz klasy abstrakcyjnej można deklarować instancje zmiennych, które są wymagane w klasach dziedziczących.
2. Klasa abstrakcyjna może przechowywać stan obiektu
3. W klasie abstrakcyjnej można deklarować konstruktory
4. W klasie abstrakcyjnej można deklarować instancje obiektu oraz bloki statyczne
5. Klasa abstrakcyjna nie może zawierać wyrażeń lambda
6. Wewnątrz klasy abstrakcyjnej możesz nadpisywać metody klasy obiektowej
Wersja 8 została wydana 18 marca 2014 roku. Wersja do pobrania JDK8.
Zasadnicze zmiany, które weszły wraz z Java 8:
W Java jest to popularna nazwa dla funkcji anonimowej (Anonymous function) czyli takiej, która nie posiada nazwy, modyfikatora dostępu. Jest definiowana w klasie, która posiada dokładnie jedną instancję.
Kolejnym krokiem jest przypisania nowo utworzonego predykatu do zmiennej np:
W momencie dodania predykatu do zmiennej, która jest wewnątrz metody będzie ona tworzona za każdym razem przy wywołaniu metody. Jeżeli chcemy to zoptymalizować i wywoływać predykat jeden raz przy ładowaniu klasy w pamięci. Możemy zadeklarować zmienną jako static i przenieść ją poza metodę.
Na koniec możemy użyć zmienną isEven w ten sposób:
Doszliśmy więc do tytułu pierwszego działu. Teraz przedstawię składnię wyrażenia lambda:
Następnie powyższe wyrażenie lambda możemy uprościć pozbywając się niepotrzebnych elementów.
I tak w przypadku gdy jest po lewej stronie tylko jeden argument możemy nie pisać nawiasów:
W przypadku używania wyrażenia lambda nie musimy jawnie definiować typów argumentów funkcji. Możliwe jest to dzięki temu, że wyrażenia lambda można używać tylko w miejscach gdzie oczekiwania jest implementacja interfejsu funkcjonalnego. Na tej podstawie Java może wnioskować typy przyjmowane przez interfejs oraz wartości jakie zwróci.
Funkcja anonimowa (integer) -> isEven.test(integer) jest równoznacza ze składnią isEven::test, gdzie isEven jest nazwą zmiennej, do której przypisana została metoda, którą chcemy wywołać.
Na koniec można jeszcze zrezygnować z nazwy metody. Nasza nowo utworzona metoda jest w anonimowa:
List<Integer> data = new LinkedList<>(Arrays.asList(3, 1, 6, 2, 9, 0, 5, 4, 8, 7));
System.out.println(Iterables.filter(data, integer -> integer % 2 == 0));
forEach() method in Iterable interface default and static methods in Interfaces Functional Interfaces and Lambda Expressions Java Stream API for Bulk Data Operations on Collections Java Time API Collection API improvements Concurrency API improvements Java IO improvements Miscellaneous Core API improvements
Deklaracja interfejsu „SampleInterf” z zaimplementowaną metodą domyślną:
interface SampleInterf {
default void main() {
log.debug(„default method”);
}
}
implementacja interfejsu:
class Test implements SampleInterf {
public static void main(String[] args) {
Test t = new Test();
t.main();
}
}
Deklaracja interfejsu SampleInterfWithStaticMethod z metodą statyczną. Metodę tego typu możesz używać w praktyce jako klasę narzędziową w pakiecie (utility class). Takiej metody statycznej nie możesz również nadpisywać.
public interface SampleInterfWithStaticMethod {
public static void m() {
System.out.println(„interface with static method”);
}
}
Stream jest interfejsem z pakietu java.util.stream. Może przetwarzać każdy obiekt kolekcji (ArrayList, LinkedList, Vector, Stack, PriorityQueue, ArrayDeque, HashSet, LinkedHashSet, TreeSet). Tworzenie streamu wygląda następująco:
Stream s = c.stream();
Jeżeli mamy utworzony Stream możemy nad nim pracować w 2 krokach:
src: