Java8에서 미리 정의해 놓은 함수형 인터페이스들을 알아보자. 다음 인터페이스들은 java.util.function에 정의되어있다.
Predicate<T>
Predicate<T> 인터페이스 내에는 boolean test(T t) 라는 추상 메서드가 존재한다. boolean test(T t)는 전달된 인자를 판단해 true 또는 false를 반환해야 하는 상황에서 사용한다.
public static int sum(Predicate<Integer> p, List<Integer> lst) {
int s = 0;
for(int n : lst) {
if(p.test(n))
s += n;
}
return s;
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 5, 7, 9, 11, 12);
int s;
s = sum(n -> n%2 == 0, list);
System.out.println("짝수 합: " + s);
s = sum(n -> n%2 != 0, list);
System.out.println("홀수 합: " + s);
}
위의 코드에서 sum 메서드는 Predicate<Integer> p를 인자로 받아 p.test()를 사용한다. 따라서 sum 메서드의 인자 p에는 추상메서드 test()를 구체화 할 람다가 들어가야 한다. 예제 에서는 짝수와 홀수를 판단하는 람다식을 사용했다.
Predicate<T>를 구체화 한 IntPredicate, LongPredicate, DoublePredicate 도 존재한다. 또 두 개의 인자를 받아 참 거짓을 정하는 BiPredicate<T, U> 도 존재한다.
Supplier<T>
Supplier<T> 인터페이스 내에는 T get() 이라는 추상 메서드가 존재한다. T get() 은 단순히 무엇인가를 반환할 때 사용한다.
public static List<Integer> makeIntList(Supplier<Integer> s, int n) {
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(s.get());
return list;
}
public static void main(String[] args) {
Supplier<Integer> spr = () -> {
Random rand = new Random();
return rand.nextInt(50);
};
List<Integer> list = makeIntList(spr, 5);
System.out.println(list);
list = makeIntList(spr, 10);
System.out.println(list);
}
위의 코드에서는 makeIntList 메서드가 Supplier<Integer> s를 인자로 받아 s.get()을 사용한다. 따라서 makeList 메서드의 인자 s에 get()을 구체화 해 메서드 내에서 활용할 값을 반환하는 람다식이 들어가야한다. 예제에서는 랜덤 값을 반환하는 식을 사용했다.
Supplier<T>를 구체화 한 IntSupplier, LongSupplier, DoubleSupplier, BooleanSupplier 도 존재한다.
Consumer<T>
Consumer<T> 인터페이스 내에는 void accept(T t) 라는 추상 메서드가 존재한다. void accept(T t)는 인자를 받아 사용하지만 반환은 하지 않는 상황에서 사용한다.
public static void main(String[] args) {
Consumer<String> c = s -> System.out.println(s);
c.accept("Mint");
}
위의 코드에서는 람다식을 사용해 Consumer<String> c 인스턴스를 선언했다. c.accept()를 사용하여 c 인스턴스에 구현한 기능을 사용할 수 있다.
Consumer<T>를 구체화 한 IntConsumer, LongConsumer, DoubleConsumer, 매개변수를 추가로 선언한 ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T> 가 존재한다. 또 두개의 인자를 받는 BiConsumer<T, U>도 존재한다.
Function<T, R>
Function<T, R> 인터페이스 내에는 R apply(T t) 라는 추상 메서드가 존재한다. R apply(T t) 는 인자를 받아 반환하는 상황에서 사용하며 가장 흔히 사용할 수 있는 인터페이스이다.
public static void main(String[] args) {
Function<String, Integer> f = s -> s.length();
System.out.println(f.apply("Robot"));
}
위의 코드에서는 람다식을 사용해 Function<String, Integer> f 인스턴스를 선언했다. f.apply()를 사용하여 f 인스턴스에 구현한 값을 반환할 수 있다.
매개변수와 반환형에 따라 Function<T, R>을 구체화한 여러 인터페이스들이 있다. 그중 BiFunction<T, U, R>은 인자 두개를 받아 반환하는 인터페이스이다. 또, 매개변수 자료형과 반환 자료형이 모두 같을 때 UnaryOperator<T>와 BinaryOperator<T>를 사용한다.
참조
윤성우의 열혈 JAVA 프로그래밍
'JAVA > Java' 카테고리의 다른 글
[Java] Optional 클래스 (0) | 2022.09.15 |
---|---|
[Java] 메서드 참조(Method Reference) (0) | 2022.09.15 |
[Java] 익명 클래스(Anonymous Class)와 람다식(Lambda Expression) (0) | 2022.09.13 |
[Java] 어노테이션(Annotation) (0) | 2022.09.13 |
[JAVA] 매개변수의 가변 인자(Variable Argument) 선언 (0) | 2022.09.12 |
댓글