프로그래밍 언어/JAVA(자바)

[자바/java] 람다식(Lambda) 정리하기 (3. 람다식의 다양한 형태)

냠냠:) 2021. 5. 7. 21:04

 

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

람다식은 매개변수와 반환 값이 제네릭 타입뿐만 아니라 기본형을 사용할 수 있는 함수형 인터페이스들을 제공한다.

 

함수형 인터페이스 형식 메서드 설 명
DoubleToIntFunction
DoubleToLongFunction
IntToDoubleFunction
IntToLongFunction
LongToDoubleFunction
LongToIntFunction
AToBFunction double -> applyAsInt(double b) -> int

(A)       -> applyAsB(A)            -> B
입력 : A타입
출력 : B타입
ToIntFunction<T>
ToDoubleFunction<T>
ToLongFunction<T>
ToBFuntion T   ->   applyAsInt(T t)     -> int

T   ->   applyAsB(T t)       -> B
입력 : 제네릭
출력 : B 타입
IntFunction<R>
BooleanFunction<R>
LongFunction<R>
AFunction int  ->   apply(int i)       ->  R

A    ->   apply(A a)       ->  R
입력 : A
출력 : 제네릭
ObjIntConsumer<T>
ObjDoubleConsumer<T>
ObjLongConsumer<T>
ObjAFunction T, int  ->  accept(T t, int i)    -> 출력 x

T, A   ->  accept(T t, A a)   -> 출력 x
입력 : T, A

(Java 11버전을 기준으로 있는 다양한 함수형 인터페이스 형식 - java.util.function에 존재하는 것을 기준으로 정리)

 

[예제]

(책의 내용을 토대로 함수형 인터페이스 정리)

public static void main(String[] args) {
	IntSupplier s = () -> (int)(Math.random() * 100) + 1;
	IntConsumer c = i -> System.out.print(i + " ");
	IntPredicate p = i -> i % 2 == 0;
	IntUnaryOperator op = i -> i*10;
	
	int[] arr = new int[10];
	
	makeRandomList(s, arr);
	IntStream.of(arr).forEach(c);
	
	System.out.println();
	printEvenNum(p, c, arr);
	System.out.println();
	
	int[] test = doSomething(op, arr);
	IntStream.of(test).forEach(c);
}

static void makeRandomList(IntSupplier s, int[] arr) {
	for(int i = 0; i < arr.length; i++) {
		arr[i] = s.getAsInt();
	}
}

static void printEvenNum(IntPredicate p, IntConsumer c, int[] arr) {
	for(int i : arr) {
		if(p.test(i)) {
			c.accept(i);
		}
	}
}

static int[] doSomething(IntUnaryOperator op, int[] arr) {
	int[] newArr = new int[arr.length];
	
	for(int i = 0; i < newArr.length; i++) {
		newArr[i] = op.applyAsInt(arr[i]);
	}
	
	return newArr;
}

 

//위 예제에서 IntUnaryOperator 대신 Function을 사용하면 a 타입을 알 수 없기 때문에 에러가 난다.
Function f = (a) -> 2*a;


//a와 반환 값의 타입을 추정할 수 없기 때문에 아래와 같이 타입을 지정해줘야한다.
Function<Integer, Integer> f = (a) -> 2*a;


//IntUnaryOperator가 Function이나 IntFunction보다 오토박싱&언박싱 횟수가 줄어들어 성능이 더 좋다.
//매개변수 int, 반환타입 Integer
IntFunction<Integer> f = (a) -> 2 * a;

 

 

Function의 합성과 Predicate의 결합

java.util.function 패키지에 있는 함수형 인터페이스는 하나의 추상 메서드 외에도 디폴트 메서드와 static메서드가 정의되어 있다.

 

Predicate.class 내부

1. Function의 합성

수학에서 두 함수를 합성해서 하나의 함수를 만들 수 있는 것처럼, 람다식도 새로운 람다식을 만들 수 있다.

함수 f, g가 있을 때, f.andThen(g)는 함수 f를 먼저 적용하고 함수 g를 적용한다. 

함수 f, g가 있을 때, f.compose(g)는 함수 g를 먼저 적용하고 함수 f를 적용한다.

 

[예제 1] - 16진수(10)를 10진수(16)로 변환 후 2진수(10000)로 변환하는 케이스

public static void main(String[] args) {
	Function<String, Integer> f = str -> Integer.parseInt(str, 16);
	Function<Integer, String> g = num -> Integer.toBinaryString(num);
	Function<String, String> h = f.andThen(g);
	
	System.out.println(h.apply("10"));
}

//10000

[예제 2] - 10진수(2)를 2진수(10)로 변환 후 16진수(16)로 변환하는 케이스

public static void main(String[] args) {
	Function<Integer, String> f2 = num -> Integer.toBinaryString(num);
	Function<String, Integer> g2 = str -> Integer.parseInt(str, 16);
	Function<Integer, Integer> h2 = g2.compose(f2);
	
	System.out.println(h2.apply(2));
}

//16

 

2. Predicate의 결합

여러 조건식을 논리연산자 and(&&), or(||), not(!)으로 연결해서 하나의 식을 구성할 수 있는 것처럼, 여러 Predicate를 and(), or(), negate()로 연결해서 하나의 Predicate로 결합할 수 있다.

 

[예제] - Predicate 결합

public static void main(String[] args) {
	Predicate<Integer> p = i -> i < 100;
	Predicate<Integer> q = i -> i < 200;
	Predicate<Integer> r = i -> i % 2 == 0;
	Predicate<Integer> notP = p.negate();		//not연산
	
	//100 <= i %% (i < 200 || i % 2 == 0)
	Predicate<Integer> all = notP.and(q.or(r));
	System.out.println(all.test(150));
	
    //위의 코드 대신 이렇게 사용할 수 있다.
	Predicate<Integer> all2 = notP.and(i -> i < 200).or(i -> i % 2 == 0);
	System.out.println(all2.test(150));
	
}

//true
//true

Predicate 끝에 negate()를 붙이면 조건식 전체가 부정이 된다.

 

[예제] - isEqual()

public static void main(String[] args) {
	Predicate<String> equal = Predicate.isEqual("테스트 문자열");
	System.out.println(equal.test("테스트 문자열"));
	
    //위의 문법을 아래와 같이 사용할 수 있다.
	System.out.println(Predicate.isEqual("테스트 문자열").test("테스트 문자열"));
}

//true
//true

 

 

 

 

-> [자바/java] 람다식(Lambda) 정리하기 (4. 메서드 참조) 바로가기 : tosuccess.tistory.com/196


 

[개인 공부를 위한 정리입니다. 참고용으로만 활용하세요]

Reference

Java의 정석 (남궁 성 지음)

 

반응형