본문 바로가기
자바

[Java] 람다(Lambda)와 java.util.function패키지

by 책 읽는 개발자_테드 2020. 4. 17.
반응형

람다와 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

댓글