Miesiąc: Maj 2020

Dwu argumentowy predykat, funkcja, konsument. Opis i porównanie

W poście tym przybliżam ciekawą funkcję wprowadzoną w Java8 jaką jest umożliwienie wprowadzania dwóch argumentów do Predykatu, Funkcji, Konsumenta i Dostawcy.

1. Predykat (Predicate)

Jest to funkcja, która przyjmuje jakiś argument i odpowiada: „tak” lub „nie”, w zależności od podanego jej elementu. Przykład predykatu jedno argumentowego gdzie sprawdzamy czy zmienna jest parzysta lub nie:
Predicate<Integer> p = i-> i%2==0;
W przypadku gdy predykat zwróci „tak”, to metoda umieści ten element w kolekcji wynikowej. W przeciwnym razie, ten element się tam nie znajdzie.

BiPredicate daje nam możliwość sprawdzenia warunków dla 2 argumentów. Poniżej przykład użycia:

import java.util.function.*
class Test {
public static void main(String [] args){
        BiPredicate<Integer, Integer> p = (a,b)  ->  (a+b) % 2  == 0;
        log.debug(p.test(10,20); // true
        log.debug(p.test(15); // false
    }
}

2. Funkcja

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:

import java.util.function.*
class Test {
public static void main(String [] args){
        BiFunction<Integer, Integer, Integer> f = (a,b) -> a*b
        log.debug(p.apply(10,20); // 200
        log.debug(p.apply(1, 10); // 10
    }
}

3 Konsument

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.

Przykład użycia BiFunction oraz BiConsumer:
import java.util.function.*;
import java.util.*
class Employee {
    String name;
    double salary;

Employee(String name, double salary){
    this.name = name;
    this.salary = salary;
}
class Test {
    public static void main(String[] args){
        ArrayList<Employee> list = new ArrayList<Employee>();
        BiFunction<String, double, Employee> f = (name,salary) -> new Employee(name, salary);

    list.add(f.accept(„Adam”, 1000000000));
    list.add(f.accept(„Ada”, 1000));
    list.add(f.accept(„Anna”, 1000));

BiConsumer<Employee, Double> c = (e,d) -> e.salary = e.salary + d;

for (Employee e: list){
    c.accept(e, 600);

}

    for (Employee e :l){
        log.debug(e.salary);
        log.debug(e.name);
    }
    }
}

4. Dostawca (Supplier)

Zwraca (dostarcza) wartość typu Date.

Supplier<Date> s = () -> new Date();

Porównanie jedno i dwu argumentowego predykatu i funkcji:

Jedno argumentowy interfejs funkcjonalny. 
interface Predicate<T> {
    public boolean test(T t);
    default Predicate and(Predicate p);
    default Predicate or(Predicate p);
    default Predicate negate();
    static Predicate isEqual(Object o);
}

Zawiera jedna metodę abstrakcyjna (test) oraz 4 domyśle metody i jedna metodę statyczna.


Dwu argumentowy interfejs funkcjonalny:

interface BiPredicate<T, U> {
    public boolean test(T t, U u);
    default BiPredicate and(BiPredicate p);
    default BiPredicate or(BiPredicate p);
    default BiPredicate negate();
}
Nie posiada metody statycznej. Przyjmuje 2 argumenty w metodzie abstrakcyjnej.
Interfejs Funkcji:
interface Function<T,R> {
    public R apply(T t);
    default Function andThen(Function f);
    default Function compose(Function f);
          static Function identity();
}
Posiada jedne argument na wejściu (T) oraz zwraca jeden argument (R). Jedna metode abstrakcyjna oraz 2 domyślne i jedna statyczna.
Interfejs BiFunkcji:
interface BiFunction<T, U, R> {
    public R apply(T t, U u);
    default BiFunction andThen(Function f);
}
Posiada 2 argumenty na wejściu (T,U) oraz zwraca jeden argument (R). Warto zauważyć że domyślna metoda andThen przyjmuje na wejściu Funkcję f a nie BiFunckję.
Jednoargumentowy interfejs Konsument:
interface Consumer<T> {
    public void accept(T t);
    default Consumer andThen(Consumer c);
}
Przyjmuje jeden argument i nic nie zwraca. 
Dwuargumentowy interfejs Konsument:
interface Consumer<T> {
    public void accept(T t);
    default BiConsumer andThen(Consumer c);
}
Przyjmuje dwa argumenty ale nic nie zwraca. Metoda andThen używamy do łaczenia większej ilości Konsumentów.
    

Reactive streams i projekt Reactor ogólne informacje

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:

  1. Publisher
  2. Subscriber
  3. Subscription
  4. Processor

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


Projekt reactor

Aby nie tracić czasu podaje poniżej przydatne dla mnie informacje, które od razu pokazują jak stosować najbardziej używane elementy projektu Reactor:

  1. Flux
  2. Mono

Są to implementacje, interfejsu Publisher. Powyższe elementy muszą zostać zasubskrybowane. Można na nich operować za pomocą metod np:

  • map
  • flatMap
W źródłach poniżej znajdują się bardzo przydatne informacje na temat praktycznego użycia Reactor. W linku 1 kiedy używać jakiego operatora np. kiedy używać Mono.just a w którym przypadku jest lepszy Optional. Są też podane informacje jak transformować uzyskane dane.
W linku 2 są natomiast podane najlepsze praktyki. Są tam odpowiedzi na pytania np: Jak odebrać i obsłużyć żądanie synchroniczne.
Praktyczne ćwiczenia znajdują się natomiast w Linku 3 . Jest to projekt na GitHubie utworzony przez twórców projektu Reactor. Musimy w nim ukończyć rozpoczęty kod. Jest to wspaniałe ćwiczenie 🙂

src:

  1. https://projectreactor.io/docs/core/release/reference/#which-operator
  2. https://projectreactor.io/docs/core/release/reference/#faq
  3. https://github.com/reactor/lite-rx-api-hands-on