자바에서 표준으로 정의하고 있는 함수형 인터페이스들에 대해 알아보자.
기본 함수형 인터페이스
함수형 인터페이스 | 추상 메소드 | 설명 |
Predicate<T> | boolean test(T t) | 전달 인자를 근거로 참/거짓 반환 |
Supplier<T> | T get() | 메소드 호출시 무언가를 반환 |
Consumer<T> | void accept(T t) | 인자를 받아들이기만 함 |
Funtion<T, R> | R apply(T t) | 입력/출력이 있음 (수학적으론 함수) |
* java.util.funtion 패키지에 정의되어 있음
Predicate
- 전달된 인자를 판단하여 true 또는 false를 반환해야 하는 상황에 사용할 수 있다.
@FuntionalInterface
public interface Predicate<T> {
boolean test(T t);
}
더보기
public class FunctionalInterface_Predicate {
public static int sum(Predicate<Integer> p, List<Integer> li) {
int s = 0;
for (int n : li) {
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);
}
}
짝수 합: 12
홀수 합: 33
public class FunctionalInterface_Predicate2 {
public static <T> void show(Predicate<T> p, List<T> li) {
for (T n : li) {
if (p.test(n))
System.out.println(n);
}
}
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 3, 8, 10, 11);
show(n -> n % 2 != 0, list1); // 홀수만 출력
List<Double> list2 = Arrays.asList(-1.2, 3.5, -2.4, 9.5);
show(n -> n > 0.0, list2); // 0.0보다 큰 수만 출력
}
}
1
3
11
3.5
9.5
💡 Predicate<T>를 다양화한 인터페이스
인터페이스 | 추상 메소드 | 설명 |
IntPredicate | boolean test(int value) | • 기본자료형을 대상으로 따로 정의 해놓은 인터페이스 • 오토박싱, 오토 언박싱 과정이 필요 없어짐 |
LongPredicate | boolean test(long value) | |
DoublePredicate | boolean test(double value) | |
BiPredicate<T, U> | boolean test(T t, U u) | • 매개 인자를 두 개를 받아 true/false을 해야할 경우 사용 |
- Predicate<T>의 T를 기본자료형으로 결정하여 정의한 인터페이스들도 존재한다. (함수형 인터페이스이지만 제네릭은 아님)
- 제네릭의 타입인자로 기본자료형은 올 수 없어 래퍼클래스를 사용해줘야 한다.
- 다음과 같이 기본자료형을 대상으로 따로 정의해놓은 인터페이스를 사용하면 박싱, 언박싱 과정을 줄일 수 있다.
Supplier
- 단순히 무언가를 반환해야 할 때 사용할 수 있다.
@FuntionalInterface
public interface Supplier<T> {
T get();
}
더보기
class FunctionalInterface_Supplier {
public static List<Integer> makeList(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 = makeList(spr, 5);
System.out.println(list);
list = makeList(spr, 10);
System.out.println(list);
}
}
// 매 실행마다 다른 난수가 담긴다.
[25, 39, 11, 48, 26]
[40, 13, 42, 17, 10, 36, 19, 20, 46, 42]
💡 Supplier<T>를 다양화한 인터페이스
인터페이스 | 추상 메소드 |
IntSupplier | int getAsInt() |
LongSupplier | long getAsLong() |
DoubleSupplier | double getAsDouble() |
BooleanSupplier | Boolean getAsBoolean() |
- supplier<T>의 T를 기본자료형으로 결정하여 정의 (함수형 인터페이스이지만 제네릭은 아님)
Consumer
- 전달된 인자를 소비하는 형태이다. 즉, 인자는 전달받지만 반환은 하지않는다.
- 전달된 인자를 가지고 어떠한 결과를 보여야 할때 사용할 수 있다.
@FuntionalInterface
public interface Consumer<T> {
void accept(T t);
}
더보기
public class FunctionalInterface_Consumer {
public static void main(String[] args) {
Consumer<String> c = s -> System.out.println(s);
c.accept("Black"); // 출력이라는 결과를 보임
c.accept("Red");
}
}
Black
Red
💡 Consumer<T>를 다양화한 인터페이스
인터페이스 | 추상 메소드 |
IntConsumer | void accept(int value) |
ObjIntConsumer | void accept(T t, int value) |
LongConsumer | void accept(long value) |
ObjLongConsumer | void accept(T t, long value) |
DouLongConsumer | void accept(double value) |
ObjDoubleConsumer | void accept(T t, double value) |
BiConsumer<T t, U u> | void accept(T t, U u) |
- Consumer<T>의 T를 기본자료형으로 결정하여 정의 (함수형 인터페이스이지만 제네릭은 아님)
더보기
class FunctionalInterface_ObjIntConsumer {
public static void main(String[] args) {
ObjIntConsumer<String> c = (s, i) -> System.out.println(i + ". " + s);
int n = 1;
c.accept("Red", n++);
c.accept("Black", n++);
c.accept("Pink", n++);
}
}
1. Red
2. Black
3. Pink
Function<T, R>
- 전달 인자와 반환 값이 있는 형태이다.
@FuntionalInterface
public interface Function<T> {
R apply(T t);
}
더보기
public class FunctionalInterface_Function {
public static void main(String[] args) {
Function<String, Integer> f = s -> s.length();
System.out.println(f.apply("Red"));
System.out.println(f.apply("Black"));
}
}
3
5
class FunctionalInterface_Function2 {
public static void main(String[] args) {
Function<Double, Double> cti = d -> d * 0.393701;
Function<Double, Double> itc = d -> d * 2.54;
System.out.println("1cm = " + cti.apply(1.0) + "inch"); // cm를 inch로
System.out.println("1inch = " + cti.apply(1.0) + "cm"); // inch를 cm로
}
}
1cm = 0.393701inch
1inch = 0.393701cm
💡 Function<T, R>를 다양화한 인터페이스
- Function<T, R>의 T와 R을 모두 기본자료형으로 결정하여 정의 (함수형 인터페이스이지만 제네릭은 아님)
인터페이스 | 추상 메소드 |
IntToDoubleFuntion DoubleToIntFuntion |
double applyAsDouble(int value) int applyAsInt(double value) |
IntUnaryOperator DoubleUnaryOperator |
int applyAsInt(int operand) double applyAsDouble(double operand) |
BiFunction<T, U, R> | R apply(T t, U u) |
UnaryOperation<T> BiOperation<T> |
T apply(T t) T apply(T t1, T t2) |
ToIntBiFuntion<T, U> ToDoubleBiFuntion<T, U> |
int applyAsInt(T t, U u) double applyAsDouble(T t, U u) |
ToIntFuntion<T> ToDoubleFuntion<T> |
int applyAsInt(T value) double applyAsInt(T value) |
IntFuntion<R> DoubleFuntion<R> |
R apply(int value) R apply(double value) |
* Operator : 반환형과 매개변수형이 동일
* Unary : 반환형과 매개변수형이 동일하면서 매개변수가 하나
* To ~ : 반환형
* ~ To : 매개변수형
더보기
public class FunctionalInterface_DoubleUnaryOperator {
public static void main(String[] args) {
DoubleUnaryOperator cti = d -> d * 0.393701;
DoubleUnaryOperator itc = d -> d * 2.54;
System.out.println("1cm = " + cti.applyAsDouble(1.0) + "inch"); // cm를 inch로
System.out.println("1inch = " + cti.applyAsDouble(1.0) + "cm"); // inch를 cm로
}
}
1cm = 0.393701inch
1inch = 0.393701cm
removeIf 메소드
- Collection<E> 인터페이스에 정의되어 있는 디폴트 메소드이다.
- 컬렉션 인스턴스에 저장된 요소 중 해당 조건에 부합하는 요소를 지우는 메소드이다.
- 참조변수를 대상으로 람다식을 작성해 메소드의 인자로 전달할 수 있다.
public interface Collection<E> {
default boolean removeIf(Predicate<? super E> filter) {...}
}
더보기
class CollectionInterface_RemoveIf {
public static void main(String[] args) {
List<Integer> li = Arrays.asList(1, -2, 3, -4, 5);
li = new ArrayList<>(li);
List<Double> ld = Arrays.asList(-1.1, 2.2, 3.3, -4.4, 5.5);
ld = new ArrayList<>(ld);
Predicate<Number> p = n -> n.doubleValue() < 0.0; // 삭제의 조건
li.removeIf(p); // List<Integer> 인스턴스에 전달
ld.removeIf(p); // List<Double> 인스턴스에 전달
System.out.println(li);
System.out.println(ld);
}
}
[1, 3, 5]
[2.2, 3.3, 5.5]
'☕ Java > 이론' 카테고리의 다른 글
[Java] 추상 클래스 (0) | 2022.08.30 |
---|---|
[Java] 스트림 (Stream) (0) | 2022.02.08 |
[Java] Optional 클래스 (0) | 2022.02.07 |
[Java] 메소드 참조 (Method References) (0) | 2022.02.04 |
[Java] 람다 (0) | 2022.01.28 |
[Java] 네스티드 클래스, 이너 클래스 (0) | 2022.01.27 |
[Java] 가변인자, 어노테이션 (0) | 2022.01.26 |
[Java] 열거형 (enum) (0) | 2022.01.26 |