[Java] 함수형 인터페이스
이 게시글은 남궁성의 정석코딩 - 자바의 정석 기초편(2020최신)을 보고 공부한 내용을 정리한 게시글입니다.
틀린 내용이 있을 수 있습니다.
함수형 인터페이스
단 하나의 추상메서드만 선언된 인터페이스이다.
@FunctionalInterface
interface MyInterface{
public abstract int max(int a, int b);
}
max() 추상 메서드를 하나를 가진 함수형 인터페이스 MyInterface를 구현했다.
@FunctionalInterface : 어노테이션으로 컴파일러가 함수형 인터페이스를 올바르게 작성했는지 체크해준다. 없어도 문제는 없지만 있는게 좋다.
함수형 인터페이스로 람다식 호출하기
1. 함수형 인터페이스 MyInterface 를 구현해서 익명객체를 만든다.
MyInterface m = new MyInterface(){
public int max(int a, int b){
return a>b ? a:b;
};
};
함수형 인터페이스 MyInterface를 구현해 익명객체를 생성했다.
추상 메서드를 구현하기 위해 동일한 제어자를 사용해서 public으로 max() 메서드를 구현했다.
2. 만들어진 익명객체를 람다식으로 바꿔 MyInterface 타입 참조변수 m에 대입한다.
MyInterface m = (a, b) -> a>b ? a:b;
3. a와 b에 값을 대입하여 호출한다.
System.out.println(m.max(1, 10)); //10
MyInterface 인터페이스에는 max() 메서드가 존재한다. 그래서 위에 Object 타입과는 달리 m.max()를 호출할 수 있다.
함수형 인터페이스 타입의 매개변수
매개변수에 함수형 인터페이스를 타입으로 넣을 수 있다.
예제를 통해 알아보자.
// 함수형 인터페이스 MyInterface 생성
@FunctionalInterface
interface MyInterface {
public abstract int max(int a, int b);
}
public class Test {
// MyInterface를 매개변수로 갖는 메서드 생성
static int method(MyInterface m, int a, int b) {
return m.max(a, b);
};
// 호출할 main 메서드
public static void main(String[] args) {
MyInterface myinterface = (a, b) -> a > b ? a : b;
System.out.println(method(myinterface, 10, 50)); // 50
}
}
코드 설명
static int method(MyInterface m, int a, int b){}
함수형 인터페이스 MyInterface 를 타입으로 갖는 변수 m을 매개변수로 넣었다.
MyInterface myinterface = (a, b) -> a > b ? a : b
변수 myinterface에 MyInterface의 람다식을 넣어준다.
method(myinterface, 10, 50)
MyInterface 타입을 갖는 변수 myinterface를 첫번째 매개변수에 대입한다.
함수형 인터페이스 반환타입
메서드의 반환타입으로 함수형 인터페이스를 사용할 수 있다.
예제로 알아보자.
// 함수형 인터페이스 MyInterface
@FunctionalInterface
interface MyInterface {
public abstract int max(int a, int b);
}
public class Test {
// 반환타입이 함수형 인터페이스인 메서드
static MyInterface returnLambda() {
MyInterface m = (a, b) -> a > b ? a : b;
return m;
}
public static void main(String[] args) {
MyInterface myinterface = returnLambda();
System.out.println(myinterface.max(5, 25)); //25
}
}
코드 설명
static MyInterface returnLambda(){}
변수 m에 MyInterface의 람다식을 대입한 후 반환한다. (= 함수형 인터페이스 반환)
MyInterface myinterface = returnLambda()
MyInterface 타입의 변수 myinterface에 함수형 인터페이스를 반환하는 메서드를 대입한다.
myinterface.max(5, 25)
myinterface에는 MyInterface의 람다식이 대입되어 있으므로 MyInterface의 메서드 max()를 호출한다.
java.util.function 패키지
자주 사용되는 다양한 함수형 인터페이스를 제공한다.
매개변수가 1개인 함수형 인터페이스 |
java.lang.Runnable | 매개변수 X, 반환값 X |
Supplier<T> | 매개변수 X, 반환값 O | |
Consumer<T> | 매개변수 O, 반환값 X | |
Function<T, R> | 하나의 매개변수(T타입)를 받아서 결과(R타입)를 반환 | |
Predicate<T> | 조건식, 매개변수 O, 반환타입은 boolean(true, false) | |
매개변수가 2개인 함수형 인터페이스 |
BiConsumer<T,U> | 2개의 매개변수, 반환값 X |
BiPredicate<T,U> | 2개의 매개변수, 반환타입은 boolean | |
BiFunction<T,U,R> | 2개의 매개변수(T, U타입), 하나의 반환값(R타입) | |
매개변수와 반환타입 일치하는 함수형 인터페이스 |
UnaryOperator<T> | Function의 자손, 매개변수와 반환타입이 같음 |
BinaryOperator<T> | BiFunction의 자손, 매개변수 2개, 매개변수와 결과의 타입이 같음 |
Supplier<T>
매개변수 X, 반환값 O
함수형 인터페이스 Supplier<T>와 람다식을 이용해 랜덤값을 list로 뽑는 예제이다.
import java.util.*;
import java.util.function.*;
public class Test{
public static void main(String[] args){
Supplier<Integer> s = () -> (int)(Math.random()*100)+1; // 매개변수X, 반환값O
List<Integer> list = new ArrayList<>();
for(int i=0; i<5; i++) {
list.add(s.get());
}
System.out.println(list); //[89, 10, 4, 96, 2]
}
}
코드 설명
Supplier<Integer> s = () -> (int)(Math.random()*100)+1
함수형 인터페이스 Supplier를 이용해서 1~100 사이의 랜덤값을 반환하는 람다식을 생성했다.
s.get()
public T get(){(int)(Math.random()*100)+1}
Supplier 인터페이스에 있는 추상 메서드로, 매개변수를 받지 않고 T 타입의 객체를 반환한다.
Consumer<T>
매개변수 O, 반환값 X
위의 코드에서 나온 list에서 짝수 값들만 출력하는 예제이다.
import java.util.*;
import java.util.function.*;
public class Test{
public static void main(String[] args){
Supplier<Integer> s = () -> (int)(Math.random()*100)+1; // 매개변수X, 반환값O
Consumer<Integer> c = i -> System.out.print(i + ", "); // 매개변수O, 반환값X
List<Integer> list = new ArrayList<>();
for(int i=0; i<5; i++) {
list.add(s.get());
}
System.out.println(list); //[33, 4, 92, 72, 74]
printNum(c, list); //4, 92, 72, 74,
}
// 짝수값만 뽑는 메서드
static <T extends Integer> void printNum(Consumer<T> c, List<T> list){
for(T i : list) {
if(i % 2 == 0) c.accept(i);
}
}
}
코드 설명
Consumer<Integer> c = i -> System.out.print(i + ", ")
Consumer 함수형 인터페이스를 사용해서 i를 매개변수로 받으면 반환값 없이 그대로 출력하는 변수 c를 선언했다.
printNum()
메서드
함수형 인터페이스 Consumer와 List를 매개변수로 받는다.
매개변수로 들어온 list를 하나씩 돌면서 짝수인지 체크한다.
i가 짝수라면 Consumer에 대입된 람다식을 이용해 i를 출력한다.
c.accept(i)
public T accept(i){System.out.print(i + ", ")}
Consumer 인터페이스에 있는 추상 메서드로 매개변수로 받은 값을 이용하여 특정한 작업을 수행하는 메서드이다.
Predicate<T>
조건식, 매개변수 O, 반환타입은 boolean(true, false)
위에 Supplier 예제에서 나온 리스트에서 짝수면 true, 홀수면 false를 반환하는 예제이다.
import java.util.*;
import java.util.function.*;
public class Test{
public static void main(String[] args){
Supplier<Integer> s = () -> (int)(Math.random()*100)+1; // 매개변수X, 반환값O
Predicate<Integer> p = i -> i%2 == 0; // true, false를 반환
List<Integer> list = new ArrayList<>();
for(int i=0; i<5; i++) {
list.add(s.get());
}
System.out.println(list); //[65, 6, 63, 4, 100]
printNum(p, list); //false, true, false, true, true,
}
// true를 반환하면 짝수, false를 반환하면 홀수
static <T> void printNum(Predicate<T> p, List<T> list){
for(T i : list) {
System.out.print(p.test(i) + ", ");
}
}
}
코드 설명
Predicate<Integer> p = i -> i%2 == 0
짝수면 true, 홀수면 false를 반환한다.
printNum()
메서드
함수형 인터페이스 Predicate와 List를 매개변수로 받는 메서드이다.
list를 돌면서 i가 짝수이면 true를, 홀수이면 false를 반환한다.
p.test(i)
public boolean test(i){return i%2 == 0;}
Predicate 인터페이스에 있는 추상 메서드로 매개변수로 받은 값을 이용하여 람다식을 평가하고 결과값으로 true나 false를 반환하는 메서드이다.
Function<T, R>
하나의 매개변수(T타입)를 받아서 결과(R타입)를 반환
Supplier의 예제를 이용하여 list 있는 값들의 1의 자리 숫자만 반환하는 예제이다.
import java.util.*;
import java.util.function.*;
public class Test{
public static void main(String[] args){
Supplier<Integer> s = () -> (int)(Math.random()*100)+1; // 매개변수X, 반환값O
Function<Integer, Integer> f = i -> i%10; // 매개변수O, 반환값O
List<Integer> list = new ArrayList<>();
for(int i=0; i<5; i++) {
list.add(s.get());
}
System.out.println(list);
printNum(f, list);
}
// 1의 자리 숫자만 반환하는 메서드
static <T> void printNum(Function<T,T> f, List<T> list){
for(T i : list) {
System.out.print(f.apply(i) + ", ");
}
}
}
코드 설명
Function<Integer, Integer> f = i -> i%10
Integer 타입의 매개변수를 받아서 1의 자리 숫자만 반환한다. 반환타입은 Integer다.
printNum()
메서드
매개변수로 함수형 인터페이스 Function과 List를 받는다.
list를 돌면서 i의 1의 자리 숫자만 반환한다.
f.apply(i)
public R apply(i){return i%10}
Function 인터페이스의 추상 메서드로, 매개변수로 전달된 값을 받아서 결과값으로 반환하는 역할을 하는 메서드이다.