함수형 인터페이스란?
- 추상 메서드를 하나만 갖는 인터페이스
- @FuncationInterface 어노테이션을 갖는 인터페이스
- Single Abstract Method(SAM) 인터페이스
예시
1
2
3
|
public interface FunctionalInterface {
public abstract void doSomething();
}
|
cs |
함수형 인터페이스를 사용하는 이유
자바의 람다식을 사용할 때 함수형 인터페이스로만 접근이 가능하기 때문이다.
@FuncationInterface 어노테이션을 붙여주면 함수형 인터페이스의 규칙을 위반했을 때 에러를 발생시킨다.
기존 방식
1
2
3
4
5
6
7
8
|
FunctionalInterface func = new FunctionalInterface() {
@Override
public void doSomething() {
System.out.println(text);
}
};
func.doSomething("do something");
|
cs |
람다식을 사용한 경우
1
2
3
4
5
|
public interface FunctionalInterface {
public abstract void doSomething();
}
FunctionalInterface func = () -> System.out.println("do something");
func.doSomething(); |
cs |
기본 함수형 인터페이스
자바에서 기본적으로 제공하는 함수형 인터페이스이다. 기본적으로 제공되는 것만 사용해도 웬만한 람다식은 다 만들 수 있다.
따라서 개발자는 직접 함수형 인터페이스를 만드는 경우가 거의 없다.
- Runnable
- Supplier
- Consumer
- Function<T,R>
- Predicate
Runnable
인자를 받지 않고 리턴값도 없는 인터페이스이다. run 메소드를 사용한다.
1
2
3
4
5
6
|
public interface Runnable {
public abstract void run();
}
-----------------------------------------------------
Runnable runnable = () -> System.out.println("run~"); runnable.run(); //결과: run~
|
cs |
Supplier
인자를 받지 않고 T 타입의 객체를 리턴한다. get 메소드를 사용한다.
1
2
3
4
5
6
7
|
public interface Supplier<T> {
T get();
}
----------------------------------------------------- Supplier<String> getString = () -> "supplier test!";
String str = getString.get();
System.out.println(str); //결과: supplier test!
|
cs |
Consumer
T 타입의 객체를 인자로 받고 리턴 값은 없다. appept 메소드를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
|
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
----------------------------------------------------- Consumer<String> printString = text -> System.out.println("Consumrer is " + text );
printString.accept("you"); //결과: Consumer is you
|
cs |
andThen 메소드를 사용하면 두개 이상의 Consumer를 연속 실행할 수 있다.
1
2
3
4
|
Consumer<String> printString = text -> System.out.println("By hello" + text );
Consumer<String> printString2 = text -> System.out.println("!!");
printString.andThen(printString2).accept("world"); //결과: By hello world !!
|
cs |
Function
T 타입의 인자를 받고, R 타입의 객체를 리턴한다. apply 메소드를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public interface Function<T, R> {
R apply(T, t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
-----------------------------------------------------
Function<Integer, Integer> multiply = (value) -> value *2;
Integer result = nultiply.apply(3);
System.out.println(result); //결과: 6
|
cs |
compose 메소드를 사용하면 Function을 조합하여 사용할 수 있다.
단, andThen 메소드와 실행 순서가 반대이다. compose()에 인자로 전달되는 Function이 먼저 실행되고 이후에 호출하는 객체의 Function이 실행된다.
1
2
3
4
5
6
7
|
Function<Integer, Integer> multiply = (value) -> value * 2;
Function<Integer, Integer> add = (value) -> value + 5;
Function<Integer, Integer> addThenMultiply = multiply.compose(add);
Integer result1 = addThenMultiply.apply(3);
System.out.println(result1); // 결과: 16
|
cs |
add함수가 먼저 실행되고 multiply 함수가 실행된다.
Predicate
T 타입 인자를 받고 결과로 boolean을 리턴한다. test 메소드를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
-----------------------------------------------------
Predicate<Integer> equalThanTen = num -> num == 10;
System.out.println(equalThenTen.test(10)); //결과: true
|
cs |
and 메소드와 or 메소드를 함께 사용할 수 있다.
and 메소듣는 두개의 Predicate가 true 일 때 참, or 메소드는 두개 중 하나만 true이면 참이다.
isEquals 메소드는 인자로 전달되는 객체와 같은지 체크해준다.
1
2
3
4
5
6
7
|
Predicate<Integer> biggerThanTen = num -> num > 10;
Predicate<Integer> lowerThanTen = num -> num < 10;
Predicate<Integer> equals = Predicate.isEqual(10);
System.out.println(biggerThanTen.and(lowerThanTen.test(5)); //결과: false
System.out.println(lowerThanThen.or(lowerThanTen.test(5)); //결과: true
isEquals.test(10); //결과: true
|
cs |
'BackEnd > Java' 카테고리의 다른 글
[Java] 싱글톤(Singleton)이란? (0) | 2022.10.10 |
---|---|
[Java] 메소드 레퍼런스란? (0) | 2022.10.09 |
[JAVA] LinkedList의 개념 및 사용법 (1) | 2022.09.07 |
[JAVA] for문 리팩토링하기(List) (0) | 2022.09.04 |
[JAVA] 생성자 정리 (0) | 2022.09.04 |
댓글