람다와 java.util.function패키지는 무슨 관련이 있는 가?
람다식을 다루기 위한 인터페이스를 함수형 인터페이스라고 한다. java.util.function패키지에 일반적으로 자주 쓰이는 형식의 메서드를 함수형 인터페이스로 미리 정의해 놓았다.
사용 이유는?
-매번 새로운 함수형 인터페이스를 정의하지 않아도 된다.
-대부분의 메서드는 타입이 비슷하다. 매개변수가 없거나 한 개 또는 두 개, 반환 값은 없거나 한 개. 또한 지네릭 메서드로 정의하면 매개변수나 반환 타입이 달라도 문제가 되지 않는다.
-함수형 인터페이스에 정의된 메서드 이름이 통일되고, 재사용성이나 유지보수 측면에도 좋다.
사용 방법은?
기본적인 함수형 인터페이스
java.lang.Runnable
매개변수도 없고, 반환값도 없음.
Supplier<T>
매개변수는 없고, 반환값만 있음.
Consumer<T>
Supplier와 반대로 매개변수만 있고, 반환값이 없음.
Function<T,R>
일반적인 함수. 하나의 매개변수를 받아서 결과를 반환한다.
Predicate<T>
조건식을 표현하는데 사용됨. 매개변수는 하나. 반환 타입은 boolean.
반환값이 boolean이라는 것만 제외하면 Function과 동일하다.
매개변수가 두 개인 함수형 인터페이스
매개변수의 개수가 2개인 함수형 인터페이스는 이름 앞에 접두사 'Bi'가 붙는다. 두 개 이상의 매개변수를 갖는 함수형 인터페이스를 선언한다면 다음과 같을 것이다.
BiConsumer<T,U>
두개의 매개변수만 있고, 반환값이 없음.
BiPredicate<T,U>
조건식을 표현하는데 사용됨. 매개변수는 둘, 반환값은 boolean
BiFunction<T,U,R>
두 개의 매개변수를 받아서 하나의 결과를 반환
UnaryOperator & BinaryOperator
Funtion의 변형이다. 매개변수의 타입과 반환타입이 모두 일치한다는 점만 제외하고는 Function과 같다.
UnaryOperator<T>
Function의 자손. Function과 달리 매개변수와 결과의 타입이 같다.
BinaryOperator<T>
BiFunction의 자손. BiFunction과 달리 매개변수와 결과의 타입이 같다.
컬렉션 프레임워크와 함수형 인터페이스
컬렉션 프레임워크의 인터페이스에 다수의 디폴트 메서드가 추가되었는데, 그 중의 일부는 함수형 인터페이스를 사용한다.
Collection
boolean removeif(Predicate<? super E> filter)
조건의 맞는 요소를 삭제
List
void replaceAll(UnaryOperator<E> operator)
모든 요소를 변환하여 대체
Iterable
void forEach(Consumer<T> action)
모든 요소에 작업 action을 수행
Map
V compute(K key, BiFunction<? super K, super V, ? extends V,? extends V> remappingFunction)
지정된 키의 값에 remappingFunction을 수행
V computeIfAbsent(K key, Function(? super K, ? extends V) mappingFunction)
-키가 없으면, mappingFunction 수행 후 추가
V computeIfPresent(K key, BiFunction(? super K, ? super V,? extends V) remappingFunction)
지정된 키가 있을 때, remappingFunction을 수행
V merge(K key, V value, BiFunction(? super V, ? super V, ? extends V) remappingFunction)
모든 요소에 병합작업 remappingFunction을 수행
void forEach(BiConsumer(? super K, ? super V) action)
모든 요소에 작업 action을 수행
void replaceAll(BiFunction<? super K, ? super V, ? extends V>function)
모든 요소에 치환작업 function을 수행
기본형을 사용하는 함수형 인터페이스
오토박싱&언방식으로 인해 기본형 대신 래퍼클래스를 사용하는 것이 비효율적이기 때문에 제공되는 인터페이스이다.
DoubleToIntFunction
AToBFunction은 입력은 A타입 출력이 B타입이다
ToIntFunction<T>
ToBFunction은 입력은 지네릭 타입 출력이 B타입이다.
IntFunction<R>
AFunction은 입력이 A타입이고 출력은 지네릭 타입이다.
ObjectConsumer<T>
ObjAFunction은 입력이 T, A타입이고 출력은 없다.
Function의 합성 Predicate의 결합
java.util.function패키지의 함수형 인터페이스에는 추상메서드 외에도 디폴트 메서드와 static메서드가 정의되어 있다.
Function의 합성
수학에서 두 함수를 합성해서 하나의 새로운 함수를 만들어낼 수 있다는 것처럼, 두 람다식을 합성해서 새로운 람다식을 만들 수 있다.
두 함수의 합성은 어느 함수를 먼저 적용하느냐에 따라 달라진다. 함수 f, g가 있을 떄, f.andThen(g)는 함수 f를 먼저 적용하고, 그 다음에 함수 g를 적용한다. 그리고 f.compose(g)는 반대로 g를 먼저 적용하고 f를 적용한다.
//문자열을 숫자로 변환하는 함수 f와 숫자를 2진 문자열로 변환하는 함수 g를
//andThen()으로 합성하여 만들어낸 새로운 함수 h. 함수 f를 먼저 적용하고, 그 다음 g를 적용한다.
Function<String, Integer> f = (s) -> Integer.parseInt(s,16);
Functin<Integer, String> g = (i) ->Integer.toBinaryString(i);
Function<String, String> h = f.andThen(g);
//<-> 반대
//숫자를 2진 문자열로 변환하는 함수g와 문자열을 숫자로 변환하는 함수 f
//compose()으로 합성하여 만들어낸 새로운 함수 h. 함수 g를 먼저 적용하고, 그 다음 f를 적용한다.
Function<Integer, String> g = (i) -> Integer.toBinaryString(i);
Function<String, Integer> f = (s) -> Integer.parseInt(s,16);
Function<Integer> h = f.compose(g);
Predicate의 결합
여러 조건식을 논리 연산자인 &&, ||, !으로 연결해서 하나의 식을 구성할 수 있는 것처럼, 여러 Predicate를 and(), or(), negate()로 연결해서 하나의 새로운 Predicate로 결합할 수 있다.
Predicate<Integer> p = i -> i < 100;
Predicate<Integer> q = i -> i < 200;
Predicate<Integer> r = i -> i%2 == 0;
Predicate<Integer> notP = p.negate(); //i>=100
//100 <= i && (i < 200 || i%2 ==0)
Predicate<Integer> all = notP.and(q.or(r));
System.out.println(all.test(100)); //true
조건식에 람다식을 직접 넣을 수 있다.
Predicate<Integer> all = notP.and(i -> i < 200).or(i -> i%2 == 0);
Predicate 인터페이스의 static메서드인 isEqual()은 두 대상을 비교하는 Predicate를 만들 때 사용한다.
먼저, isEqual()의 매개변수로 비교대상을 하나 지정하고, 또 다른 비교대상은 test()의 매개변수로 지정한다.
Predicate<String> p = Predicate.isEqual(str1);
boolean result = p.test(str2);
//아래 한 문장과 위 두 문장의 결과는 같다.
boolean result = Predicate.isEqual(str1).test(str2);
참조
자바의 정석
https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
https://docs.oracle.com/javase/8/docs/api/java/util/List.html
https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html
https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
'자바' 카테고리의 다른 글
[Java] 자바의 제어문2, 조건문 (2) | 2020.12.12 |
---|---|
[Java] 자바의 제어문1, 반복문 (0) | 2020.12.12 |
[Java] 람다(Lambda) (0) | 2020.04.14 |
[Java] super - 조상클래스 참조하기 (0) | 2020.04.06 |
[Java] Java의 탄생 (0) | 2019.03.28 |
댓글