4강에서 알아보았던 함수적 인터페이스들은 andThen()과 compose()라는 디폴트 메소드를 가지고 있다.
이 디폴트 메소드들은 첫번째 메소드의 처리결과를 두번째 메소드의 매개값으로 넘겨주지만,
인터페이스AB = 인터페이스A.andThen(인터페이스B);
or
인터페이스AB = 인터페이스B.andThen(인터페이스A);
최종결과 = 인터페이스AB.method();
위와같이 인터페이스 AB 의 method()를 호출하기 위해 매개값으로 인터페이스 A와 B의 연산값을 넘겨준다면
andThen은 인터페이스A 호출 -> 인터페이스B 호출
compose는 인터페이스B 호출 -> 인터페이스A 호출을 먼저 한다.
Consumer와 Function API를 사용한 코드를 통해 알아보자.
import java.util.function.Consumer;
import java.util.function.Function;
public class Address {
private String country;
private String city;
public Address(String country, String city){
this.country = country;
this.city = city;
}
public String getCountry() {
return this.country;
}
public String getCity(){
return this.city;
}
}
public class Member {
private String name;
private String id;
private Address address;
public Member(String name, String id, Address address){
this.name = name;
this.id =id;
this.address = address;
}
public String getName() { return this.name ;}
public String getId() { return this.id;}
public Address getAddress() { return this.address;}
}
public class ConsumerAndThenExample {
public static void main(String[] args){
System.out.println("=========consumer test=========");
Consumer<Member> consumerA = (m) -> {
// #1. 나는 Membertype이 들어오면 name을 리턴해주는 Consumer 표준 API이다.
System.out.println("consumerA: " + m.getName());
};
Consumer<Member> consumerB = (m) -> {
// #2. 나는 Membertype이 들어오면 id를 리턴해주는 Consumer 표준 API이다.
System.out.println("consumerB: " + m.getId());
};
Consumer<Member> consumerAB = consumerA.andThen(consumerB);
//#3. member의 name -> id 순서대로 리턴
consumerAB.accept(new Member("홍길동","hong", null));
System.out.println("=========function test=========");
Function<Member, Address> functionA;
Function<Address, String> functionB;
Function<Member, String> functionAB;
String city;
// #4. 나는 Member타입을 매개변수로, Address를 리턴해주는 API이다.
functionA = (m) -> m.getAddress();
// #5. 나는 Address타입을 매개변수로, String을 리턴해주는 API이다.
functionB = (a) -> a.getCity();
functionAB = functionA.andThen(functionB);
city = functionAB.apply(
// #6. Member변수를 매개로 -> address -> String 을 리턴받아 City에 저장
new Member("홍길동", "hong", new Address("한국","서울"))
);
System.out.println("거주도시 : " + city);
functionAB = functionB.compose(functionA);
city = functionAB.apply(
// #7. 위에랑 똑같지만, compose를 사용하여 순서를 조정함에 주목.
new Member("청길동", "chung", new Address("조선","한양"))
);
System.out.println("거주도시 : " + city);
}
}
실행 결과는 다음과 같다.
다음은 Predicate API의 and, or, negate, isEqual에 대해 알아보겠다. 코드로 알아보자.
import java.util.function.IntPredicate;
import java.util.function.Predicate;
public class ConsumerAndThenExample {
public static void main(String[] args){
System.out.println("*******and, or, negate test*********");
// #1. predicate API를 정의
IntPredicate predicateA = a-> a%2==0;
IntPredicate predicateB = b-> b%3==0;
IntPredicate predicateAB ;
boolean result;
// #2. A -> B의 순서로 predicateAB의 test 메소드에 인자로 넘겨준다.
predicateAB = predicateA.and(predicateB);
result = predicateAB.test(9);
System.out.println("9는 2와 3의 배수입니까? :" + result);
predicateAB = predicateA.or(predicateB);
result = predicateAB.test(9);
System.out.println("9는 2 또는 3의 배수입니까? : "+ result);
// #3. negate : 원래 결과값의 반대로 출력
predicateAB = predicateA.negate();
result = predicateAB.test(9);
System.out.println("9는 홀수입니까? " + result);
System.out.println("*******IsEqual method test*********");
Predicate<String> predicate;
// #4. targetObject를 null로 설정
predicate = Predicate.isEqual(null);
// #5. sourceObject도 null로 설정 후 test method 호출
System.out.println("null, null : " + predicate.test(null) );
predicate = Predicate.isEqual(null);
System.out.println("null, JAVA8 : " + predicate.test("JAVA8"));
predicate = Predicate.isEqual("JAVA8");
System.out.println("JAVA8, JAVA8 : " + predicate.test("JAVA8"));
}
}
출력 결과는 다음과 같다.
다음은 BinaryOperator 함수적인터페이스가 제공하는 minBy(), maxBy() 정적 메소드를 알아보자.
이 두 메소드는 매개값으로 제공되는 Comparator를 이용해서 최대 T와 최소 T를 얻는 BinaryOperator를 제공한다.
BinaryOperator<T>가 제공하는 정적메소드
- minBy(Comparator<? Super T> Comparator)
- maxBy(Comparator<? Super T> Comparator)
// #1. 함수적 인터페이스로 선언된 Comparator 방식
@FunctionalInterface
public interface Comparator<T>{
public int compare(T o1, T o2);
}
// #2. 람다식으로 선언된 Comparator 방식
(o1, o2) -> {...; return intVal;}
예시로 알아보자.
import java.util.function.*;
public class ConsumerAndThenExample {
public static void main(String[] args) {
BinaryOperator<Fruit> binaryOperator;
Fruit fruit;
Fruit 딸기 = new Fruit("딸기", 6000);
Fruit 수박 = new Fruit("수박" , 10000);
// #1. 두 객체의 price 값으로 작은 값을 리턴하는 BinaryOperator API 정의
binaryOperator = BinaryOperator.minBy((f1, f2)-> Integer.compare(f1.price, f2.price));
fruit = binaryOperator.apply(딸기, 수박);
System.out.println("minby Operation result : " + fruit.name);
// #2. 두 객체의 price 값으로 큰 값을 리턴하는 BinaryOperator API 정의
binaryOperator = BinaryOperator.maxBy((f1, f2) -> Integer.compare(f1.getPrice(), f2.getPrice()));
fruit = binaryOperator.apply(딸기, 수박);
System.out.println("maxby Operation result : " + fruit.getName());
}
}
'Study > Java' 카테고리의 다른 글
자바 기본서를 다시 읽다. 7 - 스트림의 개념과 파이프라인 (0) | 2022.04.05 |
---|---|
자바 기본서를 다시 읽다. 6 - 메소드 참조 (0) | 2022.03.29 |
자바 기본서를 다시 읽다. 4 - 표준 API의 함수적 인터페이스 (0) | 2022.03.16 |
자바 기본서를 다시 읽다. 3 - 로컬클래스와 익명객체, 그리고 람다식 (2) (0) | 2022.03.15 |
자바 기본서를 다시 읽다. 3 - 로컬클래스와 익명객체, 그리고 람다식 (1) (0) | 2022.03.15 |