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



    

Komentarze

Popularne posty