5/31/2020

Interfejsy funkcyjne Java

W poście tym przybliżam interfejsy funkcyjne wprowadzone w bibliotece  Java 8. Istnieje sześć głównych typów interfejsów funkcyjnych. Wszystkich interfejsów funkcyjnych jest 43.

Lista dostępnych intefejsów funkcyjnych:

Interface

Function Signature

Example

UnaryOperator<T>

T apply(T t)

String::toLowerCase

BinaryOperator<T>

T apply(T t1, T t2)

BigInteger::add

Predicate<T>

boolean test(T t)

Collection::isEmpty

Function<T,R>

R apply(T t)

Arrays::asList

Supplier<T>

T get()

Instant::now

Consumer<T>

void accept(T t)

System.out::println


1. Operator

Jest to interfejs reprezentujący funkcję gdzie typ wyniku i argumentu jest taki sam.


2. Predykat (Predicate)

Jest to interfejs reprezentujący funkcję, która przyjmuje argument i zwraca boolean.

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
    }
}


3. Funkcja (Function)

Jest to interfejs reprezentujący funkcję gdzie typ wyniku i argumentu jest różny.

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
    }
}



4. Konsument (Consumer)

Jest to interfejs reprezentujący funkcję, która przyjmuje argument i nie zwraca nic.

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);

    }

    }

}

5. Dostawca (Supplier)

Jest to interfejs reprezentujący funkcję, która nie przyjmuje argumentu i  zwraca wartość.

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.

src: https://devcave.pl/effective-java/interfejsy-funkcyjne-w-javie



    

Brak komentarzy:

Prześlij komentarz

Polecane notatki

Git przydatne komendy do codziennej pracy

Git jest to narzędzie do zarządzania repozytorium kodu, nad którym pracujemy. Powszechnie używany system kontroli wersji. Wiele osób na co d...