함수형 인터페이스(Functional Interface)
함수형 인터페이스(Funtional interface)는 추상메서드가 1개만 정의된 인터페이스를 의미합니다.
앞서 포스팅한 내용(Strema API - 1) 람다 표현식)에서 함수형 인터페이스를 통해 람다 표현식을 이용하여
함수형 프로그래밍 구현이 가능해집니다.
Java 8에서 제공하는 Functional 인터페이스
java8에서 제공하는 주요 Functional 인터페이스는 java.util.function 패키지에 아래와 같이 있습니다.
각 인터페이스는 매개 변수와 리턴되는 값에 따라 람다 표현식으로 표현이 가능합니다.
Supplier 인터페이스
@FunctionalInterface
public interface Supplier<T> {
T get();
}
람다 표현식
() -> expression
() -> { statement }
주요 특징
T get()
: 인수를 받지 않고,T
의 객체를 반환합니다.
// 기본 사용법
Supplier<String> stringSupplier = () -> "Hello World!";
System.out.println(stringsSpplier.get()); // "Hello World!" 출력
// 메서드 참조
Supplier<Double> randomSupplier = Math::random;
System.out.println(randomSupplier.get()); // 0.4471631248628112 출력
Consumer 인터페이스
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
람다 표현식
( parameter ) -> expression
( parameter ) -> { statement }
주요 특징
- 단일 인수를 받아 아무것도 반환하지 않는 동작을 정의합니다.
void accpet(T t)
: 주어진 인수를 소비하고 반환값이 없습니다.default Consumer andThen(Consumer after)
:Consumer
를 실행 후에 다른Consumer
를 실행할 수 있도록 합니다.after
매개변수 뒤로 전달된Consumer
가 현재Consumer
다음에 실행됩니다.
// ex
Consumer<String> consumer = (str) -> System.out.println(str.split(" ")[0]);
consumer.andThen(System.out::println).accept("Hello World!");
// 출력
// > Hello
// > Hello World!
// ex2
List<String> strings = Arrays.asList("apple", "banana", "cherry");
Consumer<String> printConsumer = System.out::println;
strings.forEach(printConsumer);
// 출력
// > apple
// > banana
// > cherry
Function 인터페이스
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
람다 표현식
( parameter ) -> expression
( parameter ) -> { statement }
주요 특징
T
타입의 입력을 받아R
타입을 반환합니다.default Function compose(Function before)
: 현재Function
을 다른Function(before)
의 입력으로 사용하여 그Function
을 실행한 결과를 현재Function
의 입력으로 하여 최종 결과를 반환합니다.default Function andThen(Function after)
: 현재Function
의 결과를 다른Function(after)
의 입력으로 사용하여Function
을 실행한 결과를 반환합니다.static Function identity()
: 동일한 입력을 받아 그대로 반환하는Function
을 생성하여 반환합니다.
// ex
Function<String, Integer> function = str -> str.length();
System.out.println(function.apply("Hello World!")); // 12 출력
// ex
// 두 함수를 정의합니다.
Function<Integer, Integer> addOne = x -> x + 1;
Function<Integer, Integer> multiplyByTwo = x -> x * 2;
// compose() 메서드를 사용하여 두 함수를 조합합니다.
Function<Integer, Integer> composedFunction = addOne.compose(multiplyByTwo);
// andThen() 메서드를 사용하여 두 함수를 조합합니다.
Function<Integer, Integer> andThenFunction = addOne.andThen(multiplyByTwo);
// 조합된 함수를 사용하여 결과를 계산합니다.
int result1 = composedFunction.apply(5); // (5 * 2) + 1 = 11
int result2 = andThenFunction.apply(5); // (5 + 1) * 2 = 12
System.out.println("Composed Function Result: " + result1); // "Composed Function Result: 11" 출력
System.out.println("AndThen Function Result: " + result2); // "AndThen Function Result: 12" 출력
Predicate 인터페이스
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
람다 표현식
( parameter ) -> expression
( parameter ) -> { statement }
주요 특징
boolean test(T t)
:T
를 매개변수로 받아boolean
타입을 반환합니다.default Predicate and(Predicate other)
: 두 개의Predicate
를 조합하여 논리적 "AND"연산을 수행하며, 현재의Predicate
가false
일 때 다른Predicate
를 판단하지 않습니다.default Predicate negate()
:Predicate
의 결과를 반전시켜 새로운Predicate
를 생성합니다.default Predicate or(Predicate other)
: 두 개의Predicate
를 조합하여 "OR"연산을 수행하며, 현재의Predicate
가true
일 때 다른Predicate
는 판단하지 않고 바로true
를 반환합니다.static Predicate isEqual(Object targetRef)
: 두 인수가 동일한지를 판별합니다.static Predicate not(Predicate target)
:negate()
를 호출하여 결과를 반전시킵니다. 정적 메서드로 기존의 객체는 변하지 않고 반전된 객체를 새롭게 생성합니다.
// ex
Predicate<String> predicate = (str) -> str.equals("Hello World!");
System.out.println(predicate.test("Hello World!")); // true 출력
Predicate<Integer> isEven = number -> number % 2 == 0;
// ex2
// 짝수 여부를 판별할 숫자
int number1 = 5;
int number2 = 10;
// Predicate를 사용하여 숫자가 짝수인지를 판별합니다.
boolean result1 = isEven.test(number1); // false
boolean result2 = isEven.test(number2); // true
// 결과 출력
System.out.println(number1 + " is even? " + result1); // "5 is even? false" 출력
System.out.println(number2 + " is even? " + result2); // "10 is even? true" 출력
UnaryOperator 인터페이스 : A unary operator from T -> T
apply()
라는 하나의 매개 변수를 갖는 메서드가 있으며, 리턴값도 존재합니다. 단, 한 가지 타입에 대하여 결과도 같은 타입일 경우 사용합니다.
람다 표현식
( parameter ) -> expression
( parameter ) -> { statement }
BinaryOperator 인터페이스 : A binary operator from (T, T) -> T
apply()
라는 두 개의 매개 변수를 갖는 메서드가 있으며, 리턴값도 존재합니다. 단, 한 가지 타입에 대하여 결과도 같은 타입일 경우 사용합니다.
람다 표현식
( parameter1, parameter2 ) -> expression
( parameter1, parameter2 ) -> { statement }
내용 참고 : 자바의 神 (로드북)
내용 참고 : Inpa Dev(티스토리)
내용 참고 : 망나니 개발자(티스토리)
'자바 탐구' 카테고리의 다른 글
자바) Java 21의 주요 특징 (0) | 2024.07.28 |
---|---|
자바) Stream API - 3) 스트림(Stream) (0) | 2024.06.09 |
자바) Stream API - 1) 람다 표현식(Lambda Expression) (0) | 2024.06.09 |
스프링) 스프링이란? (0) | 2024.05.14 |
JPA) N + 1 문제 (0) | 2023.08.01 |