JAVA - 람다와 스트림(2)

DevSeoRex·2022년 11월 3일
0
post-thumbnail

자주 쓰이는 함수형 인터페이스

java.util.function 패키지에는 여러가지 함수형 인터페이스들이 정의되어 있다.
그중에서 가장 기본적인 함수형 인터페이스는 다음과 같다.

매개변수와 반환값의 유무에 따라 4개의 함수형 인터페이스가 정의되어 있다.

조건식의 표현에 사용되는 Predicate

Predicate는 Function의 변형으로, 반환타입이 boolean이라는 점이 다르다.
Predicate는 조건식을 람다식으로 표현하는데 사용된다.

// Predicate 사용예시
Predicate<String> isEmptyStr = s -> s.length() == 0;
String s = "";

if(isEmptyStr.test(s)) // if(s.length() == 0)
	System.out.println("This is an empty String.");

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

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

두 개 이상의 매개변수를 갖는 함수형 인터페이스가 필요하다면, 직접 만들어야 한다.
3개의 매개변수를 갖는 함수형 인터페이스를 선언한다면 아래와 같을 것이다.

@FunctionalInterface
interface TriFunction<T,U,V,R> {
	R apply(T t, U u, V v);
}

UnaryOperator와 BinaryOperator

Function의 또 다른 변형으로 UnaryOperator와 BinaryOprerator가 있다.
매개변수의 타입과 반환타입의 타입이 모두 일치한다는 점 이외에는 Function과 같다.

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

컬렉션 프레임웍의 인터페이스에는 함수형 인터페이스를 사용하는 다수의 디폴트 메서드가
추가 되었다.

컬렉션 프레임웍의 함수형 인터페이스 사용 예제

  • List 선언 후, List의 모든 요소를 출력(forEach 사용)
// List 선언
ArrayList<Integer> list = new ArrayList<>();
for(int i=0; i<10; i++){
	list.add(i);
}

// list의 모든 요소를 출력
list.forEach(i -> System.out.print(i + ",") );
  • List에서 2 또는 3의 배수를 제거(removeIf 사용)
list.removeIf(x -> x%2==0 || x%3==0);
  • List의 각 요소에 10을 곱한다(replaceAll 사용)
list.replaceAll(i -> i*10);
  • Map을 선언하고 {k,v} 형태로 출력(forEach 사용)
Map<String, String> map = new HashMap<>();
map.put("1","1");
map.put("2","2");
map.put("3","3");
map.put("4","4");

map.forEach((k,v) -> System.out.print("{" + k + "," + v + "},"));

기본형을 사용하는 함수형 인터페이스

매개변수와 반환값이 지네릭 타입일 경우, 박싱(boxing)과 언박싱(unboxing)횟수가 증가하여 성능이
좋지 못하다. 기본형 대신 래퍼(wrapper)클래스를 사용하지 않고도 처리할 수 있는 함수형 인터페이스가 제공된다.

Function의 합성과 Predicate의 결합

함수형 인터페이스인 FunctionPredicate에 정의된 메서드는 아래와 같다.

Function의 합성 - andThen( )


Function의 합성은 어떤 함수를 먼저 적용하는지에 따라 달라진다. 함수 x와 z가 있다고 가정하였을때,
x.andthen(z)는 함수 x를 먼저 적용하고, 그 다음에 함수 z를 적용하는 것이다.

// andThen() 사용예시
Function<String, String> f = (s) -> Integer.parseInt(s, 16);
Function<Integer, String> g = (i) -> Integer.toBinaryString(i);
Function<String, String> h = f.andThen(g);

위 함수에 문자열 "FF"를 입력하면, 결과로 "11111111"을 얻는다.

"FF"문자열이 먼저 숫자 255로 변환되고, 255는 문자열 "11111111"로 변환되기 때문에
"FF"문자열을 입력으로 주었을때, "11111111"이 반환되는 것이다.

Function의 합성 - compose( )


compose( )는 andThen( )과 반대로, 함수 x와 z가 있다고 가정하였을때, x.compose(z)는 함수 z를 먼저 적용하고, 그 다음에 함수 x를 적용하는 것이다.

// compose() 사용예시
Function<Integer, String> g = (i) -> Integer.toBinaryString(i);
Function<String, Integer> f = (s) -> Integer.parseInt(s, 16);
Function<Integer, Integer> h = f.compose(g);

위 함수에 숫자 10을 입력하면 결과로 16을 얻는다.

숫자 2를 입력으로 주면, 2진 문자열인 "10"으로 변환되고, 2진 문자열 "10"은 숫자 16으로 변환되어,
숫자 2를 입력으로 주었을때, 16을 반환받게 된다.

출처 : 자바의 정석 3rd (남궁성 저, 도우 출판)

0개의 댓글