본문 바로가기
개발/java

주요 함수형 인터페이스

by 가시죠 2024. 5. 19.
반응형

Java의 주요 함수형 인터페이스는 java.util.function 패키지에 정의되어 있으며, 

람다 표현식과 함께 사용하여 간결하고 가독성 높은 코드를 작성할 수 있습니다.

 

주요 함수형 인터페이스들

1. Predicate<T>

Predicate<T>는 입력을 받아 boolean 값을 반환하는 함수형 인터페이스입니다. 주로 조건을 테스트하는 데 사용됩니다.

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<String> isEmpty = s -> s.isEmpty();
        
        System.out.println(isEmpty.test(""));  // 출력: true
        System.out.println(isEmpty.test("Hello"));  // 출력: false
        
        // 다른 예시: 숫자가 짝수인지 확인
        Predicate<Integer> isEven = n -> n % 2 == 0;
        System.out.println(isEven.test(4));  // 출력: true
        System.out.println(isEven.test(5));  // 출력: false
    }
}
 

Predicate는 and, or, negate 메서드를 사용하여 조합할 수 있습니다.

Predicate<String> isNotEmpty = s -> !s.isEmpty();
Predicate<String> containsA = s -> s.contains("A");

Predicate<String> complexPredicate = isNotEmpty.and(containsA);

System.out.println(complexPredicate.test("Apple"));  // 출력: true
System.out.println(complexPredicate.test(""));  // 출력: false
System.out.println(complexPredicate.test("Banana"));  // 출력: false

 

2. Function<T, R>

Function<T, R>는 입력을 받아 다른 타입의 출력을 반환하는 함수형 인터페이스입니다. 주로 변환 작업에 사용됩니다.

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        Function<Integer, String> intToString = i -> "Number: " + i;
        
        System.out.println(intToString.apply(5));  // 출력: Number: 5
        
        // 다른 예시: 문자열의 길이 계산
        Function<String, Integer> stringLength = s -> s.length();
        System.out.println(stringLength.apply("Hello"));  // 출력: 5
    }
}

 

Function은 andThen, compose 메서드를 사용하여 조합할 수 있습니다.

Function<Integer, Integer> multiplyByTwo = x -> x * 2;
Function<Integer, Integer> addThree = x -> x + 3;

Function<Integer, Integer> combinedFunction = multiplyByTwo.andThen(addThree);

System.out.println(combinedFunction.apply(5));  // 출력: 13
 

 

3. Consumer<T>

Consumer<T>는 입력을 받아 소비하는 함수형 인터페이스로, 반환값이 없습니다. 주로 입력을 출력하거나 다른 작업을 수행하는 데 사용됩니다.

import java.util.function.Consumer;

public class ConsumerExample {
    public static void main(String[] args) {
        Consumer<String> print = s -> System.out.println(s);
        
        print.accept("Hello, World!");  // 출력: Hello, World!
        
        // 다른 예시: 숫자를 출력
        Consumer<Integer> printNumber = n -> System.out.println("Number: " + n);
        printNumber.accept(10);  // 출력: Number: 10
    }
}

 

Consumer는 andThen 메서드를 사용하여 조합할 수 있습니다.

Consumer<String> printUpperCase = s -> System.out.println(s.toUpperCase());
Consumer<String> printLowerCase = s -> System.out.println(s.toLowerCase());

Consumer<String> combinedConsumer = printUpperCase.andThen(printLowerCase);

combinedConsumer.accept("Java");  // 출력: JAVA, java

 

4. Supplier<T>

Supplier<T>는 입력을 받지 않고 출력을 반환하는 함수형 인터페이스입니다. 주로 값을 생성하거나 제공하는 데 사용됩니다.

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        Supplier<String> supplyString = () -> "Hello, Supplier!";
        
        System.out.println(supplyString.get());  // 출력: Hello, Supplier!
        
        // 다른 예시: 현재 시간 제공
        Supplier<Long> currentTime = () -> System.currentTimeMillis();
        System.out.println(currentTime.get());  // 출력: 현재 시간 밀리초
    }
}

 

5. BinaryOperator<T>

BinaryOperator<T>는 동일한 타입의 두 인수를 받아 동일한 타입의 출력을 반환하는 함수형 인터페이스입니다. BiFunction<T, U, R>의 특수한 경우로, 인수와 반환 타입이 동일한 경우입니다.

import java.util.function.BinaryOperator;

public class BinaryOperatorExample {
    public static void main(String[] args) {
        BinaryOperator<Integer> sum = (a, b) -> a + b;
        
        System.out.println(sum.apply(2, 3));  // 출력: 5
        
        // 다른 예시: 문자열 합치기
        BinaryOperator<String> concatenate = (s1, s2) -> s1 + s2;
        System.out.println(concatenate.apply("Hello", " World"));  // 출력: Hello World
    }
}

 

6. UnaryOperator<T>

UnaryOperator<T>는 단일 인수를 받아 동일한 타입의 출력을 반환하는 함수형 인터페이스입니다. Function<T, R>의 특수한 경우로, 입력과 반환 타입이 동일한 경우입니다.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
    public static void main(String[] args) {
        UnaryOperator<Integer> square = x -> x * x;
        
        System.out.println(square.apply(4));  // 출력: 16
        
        // 다른 예시: 문자열 대문자로 변환
        UnaryOperator<String> toUpperCase = s -> s.toUpperCase();
        System.out.println(toUpperCase.apply("hello"));  // 출력: HELLO
    }
}

 

7. BiFunction<T, U, R>

BiFunction<T, U, R>는 두 개의 인수를 받아 다른 타입의 출력을 반환하는 함수형 인터페이스입니다.

import java.util.function.BiFunction;

public class BiFunctionExample {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, String> sumToString = (a, b) -> "Sum: " + (a + b);
        
        System.out.println(sumToString.apply(2, 3));  // 출력: Sum: 5
        
        // 다른 예시: 두 문자열을 합치고 길이 반환
        BiFunction<String, String, Integer> combineLength = (s1, s2) -> (s1 + s2).length();
        System.out.println(combineLength.apply("Hello", " World"));  // 출력: 11
    }
}

 

결론

Java의 주요 함수형 인터페이스는 코드의 재사용성과 가독성을 크게 향상시킬 수 있습니다. Predicate, Function, Consumer, Supplier, BinaryOperator, UnaryOperator, BiFunction 등의 함수형 인터페이스를 적절히 활용하면 더 간결하고 명확한 코드를 작성할 수 있습니다. 이 인터페이스들은 람다 표현식과 함께 사용되며, Java 8에서 도입된 스트림 API와도 잘 어울립니다. 이를 통해 Java의 강력한 함수형 프로그래밍 기능을 최대한 활용할 수 있습니다.

반응형

댓글