기본형을 사용하는 함수형 인터페이스
람다식은 매개변수와 반환 값이 제네릭 타입뿐만 아니라 기본형을 사용할 수 있는 함수형 인터페이스들을 제공한다.
(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메서드가 정의되어 있다.
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의 정석 (남궁 성 지음)
'프로그래밍 언어 > JAVA(자바)' 카테고리의 다른 글
[자바/java] 자바 문자열 배열을 문자열로 변환하기/바꾸기 (반대 과정 포함) (0) | 2021.05.15 |
---|---|
[자바/java] 람다식(Lambda) 정리하기 (4. 메서드 참조) (1) | 2021.05.10 |
[자바/java] 람다식(Lambda) 정리하기 (2. 함수형 인터페이스(Functional Interface) : 응용) (0) | 2021.04.15 |
[자바/java] 람다식(Lambda) 정리하기 (2. 함수형 인터페이스(Functional Interface) : 기본) (0) | 2021.04.12 |
[자바/java] 람다식(Lambda) 정리하기 (1. 개념) (0) | 2021.04.11 |