728x90

다양한 함수형 인터페이스

java.util.function 패키지에 일반적으로 자주 쓰이는 형식의 메서드를 함수형 인터페이스로 미리 정의해 두었다. 일반적으로 많이쓰이는 이패키지의 인터페이스를 활용하면 재사용성이나 유지보수 측면에서도 좋을것이다.

 

목록

Supplier<T> : 메서드 T get() - 매개변수는 없고, 반환값만 있다. (공급자)

Consumer<T> : 메서드 void accept(T t) - Supplier와 반대로 매개변수만 있고, 반환값이 없다. (소비자)

Function<T, R> : 메서드 R apply(T t) - 일반적인 하나의 매개변수와 반환값이 있는 함수. 입력타입 T 반환타입 R (입출력 함수)

Predicate<T> : 메서드 boolean test(T t) - 조건식을 표현하는데 사용됨. 매개변수 하나, 반환타입은 boolean(조건식)

 

매개변수가 두개인 함수형 인터페이스

매개변수가 두개인 함수형 인터페이스의 이름에는 'Bi'가 붙는다.

 

BiConsumer<T, U> : 메서드 void accept(T t, U u) - 두개의 매개변수만 있고 반환값은 없는 소비자

BiPredicate<T, U> : 메서드 boolean test(T t, U u) - 조건식을 표현하고 수행하는데 사용된다. 매개변수는 두개이고 반환값은 boolean이다.

BiFunction<T,U,R> : 메서드 R apply(T t, U u) - 두개의 매개변수 t, u를 받아서 결과를 반환한다. 반환 타입은 R

 

3개이상의 매개변수를 사용하는 함수형 인터페이스를 사용하고싶다면 직접 만들어서 사용해야한다.

ex)

@FunctionalInterface

interface TriFunction<T, U, V, R>{

     R apply(T t, U u, V v);

}

 

켤렉션 프레임웍과 함수형 인터페이스

컬렉션 프레임워크의 인터페이스에 함수형인터페이스가 존재한다.

 

UnaryOperator<T> : T apply(T t) - Function의 자손, Function과 달리 매개변수와 결과의 타입이 같다.

BinaryOperator<T> : T apply(T t, T t) - BiFunction의 자손, BiFunction과 달리 매개변수와 결과의 타입이 같다.

 

메서드 목록

Collection

boolean removeIf(Predicate<E> filter) : Predicate 조건식에 일치하는 값들을 삭제

List

void replaceAll(UnaryOperator<E> operator)  : 모든 요소 UnaryOperator의 함수의 반환값으로 변환하여 대체

Iterator 

void forEach(Consumer<T> action) : 모든 요소에 작업 action을 수행

Map

V comput(K key, BiFunction<K,V> f) : 지정된 키의 값에 작업 f를 수행

V computeIfAbsent(K key, Function<K,V> f) : 키가 없으면, 작업 f를 수행 후 추가

V computeIfPresent(K key, BiFunction<K,V,V> f ) : key가 있을때, 작업 f를 수행

V merge(K key, V value, BiFunction<V,V,V> f) : 모든 요소에 병합작업 f를 수행

void forEach(BiConsumer<K, V> action) : 모든 요소에 작업 action을 수행

void replaceAll(BiFunction<K,V,V> f) : 모든요소에 치환작업 f를 수행

 

list.forEach를 사용하고 매개변수로 람다식을 주었다. list의 모든 요소를 출력한다.

2번째줄 출력은 list.removeIf()를 수행한 이후이다. x가 2의배수거나 3의배수라면 모두 삭제하는 연산이다.

3번째줄 출력은 replaceAll을 통해 모든 요소들을 10배하여 요소값을 바꾸는 것이다.

4번째줄은 forEach를 통해 맵의 모든 요소들을 출력한 것이다.

 

Function의 합성과 Predicate의 결합

Function과 Predicate에 정의된 메서드

 

Function

default <V>Function<T,V> andThen(Function<? super R, ? extends V> after)

default <V>Function<V,R> compose(Function<? super V, ? extends T> before)

static <T> Function<T,T> identity()

 

andThen의 사용예시 Function f, g가 있을 때, f.andThen(g)는 함수 f를 적용한 후 g함수를 적용한다는 의미이다.

compose는 반대로 f.compose(g)의 경우 g함수를 먼저 적용한후 f함수를 적용한다.

identity()는 항등함수로 x->x 를 나타낸다. 잘 사용하지않는다.

 

Predicate

default Predicate<T> and(Predicate<? super T> other)

default Predicate<T> or(Prerdicate<? super T> other)

default Predicate<T> negate()

static <T> Predicate<T> isEqual(Object targetRef)

 

and, or 메서드는 내부에 또다른 조건식을 필요로한다. and(조건식)의 경우 두 조건식의 and결합(&&)이고 or(조건식)의 경우 두 조건식의 or결합(||)이다.

negate()는 부정연산자(!)가 결합되는것이다.

isEqual()은 매개변수로 대상하나를 지정하고 또다른 비교대상은 test()의 매개변수로 지정하는 방식으로 사용하는데 각각의 대상이 같은지 비교한다.

 

메서드참조

람다식을 더욱 간결하게 표현하는 방법으로 람다식이 하나의 메서드만 호출하는 경우 '메서드 참조(method reference)'라는 방법으로 람다식을 간략히 할 수 있다.

 

Function<String, Integer> f = (String s) -> Integer.parseInt(s);

위같은 함수형인터페이스가 정의되었다고 가정할 때, 위식을 아래와 같이 간단하게 나타낼 수 있다.

Function<String, Integer> f = Integer::parseInt;

람다식의 일부가 생략되었다. 생략된정보들은 좌변의 함수형인터페이스 형식으로부터 얻거나 우변의 parseInt메서드호출로 알 수 있다. Function<String, Integer>는 String을 매개변수로 받고 반환값은 Integer로 반환한다는 의미이다.

해당 Function의 메서드로는 Integer클래스의 parseInt를 사용하는것을 알 수 있다.

 

3가지 경우의 메서드 참조

static메서드 참조

(x) -> ClassName.method(x) == ClassName::method

인스턴스메서드 참조

(obj, x) -> obj.method(x) == ClassName::method

특정 객체 인스턴스 메서드 참조

(x) -> obj.method(x) == obj::method

 

생성자 매서드 참조

생성자를 호출하는 람다식도 메서드 참조로 변환할 수 있는데 위와같이 하면된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90

'Programming > JAVA' 카테고리의 다른 글

스트림(Stream)의 중간연산  (0) 2021.08.25
스트림(Stream)  (0) 2021.08.24
람다식(Lambda expression)  (0) 2021.08.21
fork & join  (0) 2021.08.20
쓰레드의 동기화  (0) 2021.08.20

+ Recent posts