본문 바로가기
Programing/Java & Spring

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

by 슈퍼와이비 2023. 9. 22.
반응형

Java에서는 함수형 인터페이스가 도입되어 함수형 프로그래밍을 지원하고, 람다 표현식과 함께 사용함으로써 코드의 간결성과 확장성을 개선하고자 했습니다. 함수형 인터페이스는 Java 8부터 등장하여 Java 프로그래밍에서 중요한 역할을 하고 있습니다.

 

  1. 람다 표현식 지원: Java 8에서는 람다 표현식이 도입되었습니다. 이를 통해 익명 함수를 간결하게 정의하고 전달할 수 있게 되었습니다. 람다 표현식은 함수형 인터페이스와 함께 사용됩니다. 따라서 함수형 인터페이스의 필요성이 부각되었습니다.
  2. 함수형 프로그래밍 패러다임: 함수형 프로그래밍은 코드의 간결성, 가독성, 테스트 용이성, 병렬 처리 등 여러 이점을 제공합니다. 이러한 함수형 프로그래밍 패러다임을 Java에 도입하고자 했으며, 함수형 인터페이스는 이를 가능하게 합니다.
  3. 병렬 및 비동기 프로그래밍: 병렬 및 비동기 프로그래밍은 멀티코어 프로세서와 함께 사용되며, 함수형 프로그래밍 원칙을 따르는 코드는 병렬화 및 비동기 작업을 더 쉽게 다룰 수 있습니다. 함수형 인터페이스는 비동기 작업을 위한 콜백 함수를 정의하는 데 사용됩니다.
  4. 컬렉션 및 데이터 처리 개선: Java의 컬렉션 프레임워크와 데이터 처리 라이브러리(Stream API)는 함수형 프로그래밍 원칙을 적용하여 데이터 처리를 개선하였습니다. 함수형 인터페이스는 이러한 라이브러리와 연동하여 사용됩니다.
  5. 가독성 및 유지 보수성 향상: 함수형 인터페이스와 람다 표현식을 사용하면 코드가 간결해지고 가독성이 향상됩니다. 또한 함수형 프로그래밍은 상태 변경을 줄이고 예측 가능한 동작을 촉진하여 유지 보수성을 향상시킵니다.

 

함수형 인터페이스에서 제네릭 타입 매개변수는 일반적으로 함수의 입력과 출력 타입을 정의하는 데 사용됩니다. 일반적으로 첫 번째 제네릭 타입 매개변수는 함수의 입력 타입을 나타내고, 두 번째 제네릭 타입 매개변수는 함수의 출력 타입을 나타냅니다.
@FunctionalInterface
interface MyFunction<T, R> {
    R apply(T t);
}

 


위의 MyFunction 인터페이스는 하나의 입력(T)을 받아서 출력(R)을 반환하는 함수를 표현합니다. T는 입력 타입을, R은 출력 타입을 나타냅니다.

함수형 인터페이스를 사용할 때 이러한 제네릭 타입을 적절하게 구체화하여 람다 표현식 또는 메서드 참조를 정의할 수 있습니다. 예를 들어, MyFunction 인터페이스를 사용하는 람다 표현식은 다음과 같을 수 있습니다

MyFunction<String, Integer> stringLength = (s) -> s.length();

 


 

java.util.function 패키지에는 많은 종류의 함수형 인터페이스가 포함되어 있으며, 주로 다음과 같이 사용됩니다

 

Consumer
Consumer<T> 는 하나의 인자를 받아서 결과를 반환하지 않는 함수를 나타냅니다. 주로 어떤 동작을 수행할 때 사용됩니다.
Consumer<String> printer = (s) -> System.out.println(s);
printer.accept("Hello, World!"); // 출력: "Hello, World!"

 

Supplier
Supplier<T>는 인자를 받지 않고 결과를 반환하는 함수를 나타냅니다. 주로 데이터를 생성할 때 사용됩니다.
Supplier<Integer> randomNumber = () -> (int) (Math.random() * 100);
int number = randomNumber.get();

 

Function
Function<T, R>는 하나의 인자를 받아서 다른 타입의 결과를 반환하는 함수를 나타냅니다
Function<Integer, String> intToString = (n) -> Integer.toString(n);
String result = intToString.apply(42); // "42"

 

Predicate
Predicate<T>는 하나의 인자를 받아서 boolean 값을 반환하는 함수를 나타냅니다.
Predicate<Integer> isEven = (n) -> n % 2 == 0;
boolean result = isEven.test(4); // true

 


 

Java의 Stream API에서도 다양한 함수형 인터페이스가 사용됩니다. Stream API는 데이터 컬렉션을 다루고 변환할 때 함수형 인터페이스를 활용합니다. 아래는 일부 Stream API에서 주로 사용되는 함수형 인터페이스 예제입니다

 

 

  • Function<T, R> 함수형 인터페이스는 map 메서드에서 주로 사용됩니다. 스트림의 각 요소를 다른 타입으로 변환하거나 매핑할 때 사용됩니다.
  • Predicate<T> 함수형 인터페이스는 filter 메서드에서 주로 사용됩니다. 스트림의 요소를 조건에 따라 필터링할 때 사용됩니다.
  • Consumer<T> 함수형 인터페이스는 forEach 메서드에서 주로 사용됩니다. 스트림의 각 요소를 소비하거나 출력할 때 사용됩니다.
  • Comparator<T> 함수형 인터페이스는 정렬을 위한 메서드들에서 사용됩니다. 예를 들어, sorted 메서드에서 사용하여 스트림의 요소를 정렬할 수 있습니다.

 

List<String> names = List.of("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream()
    .map((name) -> name.length()) // Function 사용
    .collect(Collectors.toList());
    
    
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
    .filter((n) -> n % 2 == 0) // Predicate 사용
    .collect(Collectors.toList());


List<String> fruits = List.of("Apple", "Banana", "Cherry");
fruits.stream()
    .forEach((fruit) -> System.out.println("I like " + fruit)); // Consumer 사용


List<String> names = List.of("Alice", "Bob", "Charlie");
List<String> sortedNames = names.stream()
    .sorted((name1, name2) -> name1.compareTo(name2)) // Comparator 사용
    .collect(Collectors.toList());

 

함수형 인터페이스는 Java 8 이상에서 소개된 중요한 개념 중 하나이며, Java의 함수형 프로그래밍 및 람다 표현식을 활용하는 데 필수적인 개념입니다. 다양한 예시를 통해 익숙해 지셨으면 좋겠습니다.

 

 

반응형