java

함수형 인터페이스

curiousKidd 2023. 4. 6. 15:09
반응형

1. 함수형 인터페이스란?

함수형 인터페이스는 하나의 추상 메서드만을 가지고 있는 인터페이스입니다. 즉, 함수형 인터페이스를 구현하는 클래스는 하나의 메서드만을 반드시 구현해야 합니다.

 

예를 들어, 아래와 같은 함수형 인터페이스를 정의할 수 있습니다.

 

@FunctionalInterface
public interface Calculator {
	int calculate(int x, int y);
}

 

위 인터페이스는 calculate라는 하나의 메서드만을 가지고 있습니다.
이 인터페이스를 구현하는 클래스는 calculate 메서드를 반드시 구현해야 합니다.

2. 함수형 인터페이스의 활용

Java 함수형 인터페이스는 함수형 프로그래밍을 지원하기 위해 도입되었습니다. 함수형 프로그래밍은 상태를 변경하는 대신 입력과 출력 간의 관계를 정의하는 방식으로 프로그래밍을 하는 패러다임입니다.

함수형 인터페이스를 사용하면 람다식을 이용한 함수형 프로그래밍을 쉽게 구현할 수 있습니다. 예를 들어, 위에서 정의한 Calculator인터페이스를 이용하여 다음과 같은 람다식을 정의할 수 있습니다.

 

Calculator add = (x, y) -> x + y;

 

위 람다식은 Calculator 인터페이스를 구현한 객체를 생성하는 코드입니다. 이 객체는 add라는 이름으로 참조됩니다. 이제 add 객체를 사용하여 다음과 같이 계산할 수 있습니다.

int result = add.calculate(3, 4);
System.out.println(result); // 출력 결과: 7

 

3. 자주 사용되는 함수형 인터페이스

Java에서는 이미 많은 함수형 인터페이스가 미리 정의되어 있습니다. 이러한 인터페이스들을 사용하여 함수형 프로그래밍을 쉽게 구현할 수 있습니다. 자주 사용되는 함수형 인터페이스에는 다음과 같은 것들이 있습니다.

 

3.1. Consumer<T>
Consumer<T> 인터페이스는 하나의 인자를 받아서 처리하는 함수형 인터페이스입니다.

 

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

 

예를 들어, 아래와 같은 코드는 Consumer<T> 인터페이스를 이용하여 문자열을 출력하는 예제입니다.

 

Consumer<String> printer = System.out::println;
printer.accept("Hello, world!");

 

위 코드에서는 System.out.println() 메서드를 참조하는 람다식을 정의하고, 이를 Consumer<String> 타입의 객체인 printer에 할당합니다. 그리고 printer 객체의 accept 메서드를 호출하여 문자열을 출력합니다.

 

3.2. Predicate<T>
Predicate<T> 인터페이스는 하나의 인자를 받아서 true 또는 false 값을 반환하는 함수형 인터페이스입니다.

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

 

예를 들어, 아래와 같은 코드는 Predicate<T> 인터페이스를 이용하여 문자열의 길이가 5 이상인지를 검사하는 예제입니다.

 

Predicate<String> checkLength = s -> s.length() >= 5;
System.out.println(checkLength.test("Hello")); // 출력 결과: true
System.out.println(checkLength.test("Java")); // 출력 결과: false

 

위 코드에서는 s.length() >= 5 람다식을 정의하고, 이를 Predicate<String> 타입의 객체인 checkLength에 할당합니다. 그리고 checkLength 객체의 test 메서드를 호출하여 문자열의 길이가 5 이상인지를 검사합니다.

 

3.3. Function<T, R>
Function<T, R> 인터페이스는 하나의 인자를 받아서 결과를 반환하는 함수형 인터페이스입니다.

 

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

 

예를 들어, 아래와 같은 코드는 Function<T, R> 인터페이스를 이용하여 문자열을 대문자로 변환하는 예제입니다.

 

    Function<String, String> toUpperCase = String::toUpperCase;
    System.out.println(toUpperCase.apply("hello")); // 출력 결과: HELLO

 

위 코드에서는 String::toUpperCase 메서드 참조를 이용하여 문자열을 대문자로 변환하는 람다식을 정의하고, 이를 Function<String, String> 타입의 객체인 toUpperCase에 할당합니다. 그리고 toUpperCase 객체의 apply 메서드를 호출하여 문자열을 대문자로 변환합니다.

 

4. 함수형 인터페이스의 활용 예제

함수형 인터페이스는 다양한 분야에서 활용될 수 있습니다. 예를 들어, 아래는 리스트에서 특정 조건을 만족하는 원소만 추출하는 예제입니다.

List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve");

// Predicate를 이용하여 "J"로 시작하는 이름만 추출
List<String> result = names.stream()
.filter(name -> name.startsWith("J"))
.collect(Collectors.toList());
System.out.println(result); // 출력 결과: [John, Jane]

 

위 코드에서는 List<String> 타입의 names 리스트의 각 원소를 검사하여 "J"로 시작하는 원소만 추출하는 예제입니다. 이를 위해 Stream 인터페이스의 filter 메서드를 이용합니다.

 

filter 메서드는 Predicate<T> 타입의 객체를 인자로 받아서, 이 객체의 test 메서드를 호출하여 각 원소를 검사합니다. test 메서드가 true 값을 반환하는 원소만 필터링하여 새로운 스트림을 반환합니다.

 

따라서 위 코드에서는 name -> name.startsWith("J") 람다식을 정의하고, 이를 Predicate<String> 타입의 객체로 사용합니다. filter 메서드는 name.startsWith("J")를 만족하는 name 원소만 추출하여 새로운 스트림을 생성합니다. 이후 collect 메서드를 이용하여 추출된 원소들을 List 컬렉션으로 변환합니다.

 

함수형 인터페이스는 또한 메서드 참조와 함께 사용하여 코드를 더 간결하고 가독성 좋게 만들 수 있습니다. 예를 들어, 아래는 리스트의 각 원소에 대해 문자열을 대문자로 변환한 후, 길이가 5 이상인 원소만 추출하는 예제입니다.

 

List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve");

// Function과 Predicate를 이용하여 문자열을 대문자로 변환하고 길이가 5 이상인 원소만 추출
List<String> result = names.stream()
.map(String::toUpperCase)
.filter(name -> name.length() >= 5)
.collect(Collectors.toList());
System.out.println(result); // 출력 결과: [JOHN, JANE]

 

위 코드에서는 Stream 인터페이스의 map 메서드를 이용하여 각 원소를 대문자로 변환합니다. map 메서드는 Function<T, R> 타입의 객체를 인자로 받아서, 이 객체의 apply 메서드를 호출하여 각 원소를 변환한 새로운 스트림을 반환합니다. 따라서 위 코드에서는 String::toUpperCase 메서드 참조를 이용하여 각 원소를 대문자로 변환하는 람다식을 정의합니다.

 

이후 filter 메서드를 이용하여 변환된 문자열의 길이가 5 이상인 원소만 추출합니다.

이 과정에서 Predicate<String> 타입의 객체를 사용합니다.

마지막으로 collect 메서드를 이용하여 추출된 원소들을 List 컬렉션으로 변환합니다.

반응형

'java' 카테고리의 다른 글

Java8 VS Java11  (0) 2023.12.07
자바 메모리 구조  (0) 2023.08.16
Java Stream  (0) 2023.03.28
블로킹(Blocking)? 논블로킹(Non-Blocking)?  (1) 2023.03.07
어노테이션(Annotation) 이란?  (0) 2022.07.11