본문 바로가기
개발/자바

함수형 인터페이스 (Functional Interface)

by hamcheeseburger 2022. 3. 30.

 

함수형 인터페이스와 아무 관계 없는 사진입니다

함수형 인터페이스란?

오직 하나의 추상메서드만 갖는 인터페이스

디폴트 메소드가 있더라도 추상메서드가 오직 하나면 함수형 인터페이스이다.

 

(예시)

public interface CustomFuntionalInterface {
    int customFunction(int a, int b);
}

@FunctionalInterface

함수형 인터페이스임을 나타내는 어노테이션이다.

@FunctionalInterface로 인터페이스를 선언했지만 실제로 함수형 인터페이스가 아니면 컴파일러가 예외를 발생시킨다.

추상 메소드가 1개 이상이라면 컴파일 에러가 발생하는 것이다.

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

함수형 인터페이스의 종류

아래 코드에서는 추상 메소드만 나타내었으니 참고 바랍니다.

1. Predicate<T> (T → boolean)

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

T의 객체를 받아 boolean을 반환하는 추상메소드를 갖는다.

 

위의 Predicate<T> 인터페이스는 참조형(Byte, Integer, String 등) 파라미터만 전달할 수 있다.

다만 자바에서 기본형을 참조형으로 변환하는 오토박싱을 지원한다. 하지만 오토박싱은 메모리 비용이 추가적으로 발생한다.

아래 IntPredicate에서는 int를 Integer로 변환하는 오토박싱 없이 함수형 인터페이스를 구현할 수 있다.

 

* IntPredicate

@FunctionalInterface
public interface IntPredicate {
    boolean test(int value);
}

IntPredicate 이외에도 LongPredicate, DoublePredicate도 지원을 한다.

2. Consumer<T> (T -> void)

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

T의 객체를 받아 void를 반환하는 추상메소드를 갖는다. 특정 객체를 인수로 받아 어떠한 동작을 수행하고 싶을 때 주로 사용한다.

3. Supplier<T> (void -> T)

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

아무런 인자도 전달받지 않고 특정 객체를 반환하는 추상메소드를 갖는다.

4. Function<T, R> (T -> R)

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

제네릭 형식의 T를 전달 받아서 제네릭 형식의 R을 반환하는 추상메소드를 갖는다. 특정 값을 넣으면 무조건 어떠한 값을 반환하는 함수의 특징을 갖는다고 생각하면 된다.

5. UnaryOperator<T> (T → T)

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

}

Function을 상속받으며, 전달받은 인자의 타입과 반환의 타입이 동일하다.

6. BinaryOperator<T> ((T, T) → T)

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
   
}

BiFunction을 상속받으며, 인자를 2개 전달받는다. 전달받는 인자들의 타입과 반환의 타입이 동일하다.

7. BiPredicate<L, R> ((L, R) → boolean)

@FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
}

인자를 전달받아 boolean을 반환한다는 점에서 Predicate와 비슷하다. 하지만 BiPredicate는 인자를 2개 전달받는 점이 특징이다.

8. BiConsumer<T, U> ((T, U) → void)

@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
}

인자를 전달받아 void를 반환한다는 점에서 Consumer와 비슷하다. 하지만 BiConsumer는 인자를 2개 전달받는 점이 특징이다.

9. BiFunction<T, U, R> ((T, U) → R)

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

인자를 전달받아 특정 객체를 반환한다는 점에서 Function과 비슷하다. 하지만 BiFunction은 인자를 2개 전달받는 점이 특징이다.

 

람다로 구현하기

public static void consumerTest(List<Integer> numbers, Consumer<Integer> consumer) {
	for(Integer number: numbers) {
		if(consumer.test(number)) {
			// ..
		}
	}
}

public static void main(String[] args) {
	consumerTest(List.of(1, 2, 3), (number) -> number % 2 == 0);
}

 

'개발 > 자바' 카테고리의 다른 글

Java Closure  (0) 2022.12.03
기본형 특화 스트림(IntStream, LongStream, DoubleStream)  (3) 2022.10.09
추상화란?  (2) 2022.03.17
compareTo()가 0을 반환하면 어떤 순서로 정렬되나?  (0) 2022.02.19
Java Stream.max() 사용법  (0) 2022.02.14

이전 댓글