본문 바로가기
Programming/JAVA

[java] 함수형 인터페이스

by 코딩의성지 2021. 11. 4.

예쩐에 포스팅에서 람다식에 대한 포스팅을 했었다.

https://devkingdom.tistory.com/272?category=941391 

 

[Java] 람다식 (Lambda Expression)

오늘은 람다식에 대해 간단하게 정리해두려고 한다. 람다식은 Java 8 부터 지원하는 객체지향 프로그래밍과는 다른 함수형 프로그래밍 방식이다. 람다식은 익명객체를 더 간단하게 줄여서 사용

devkingdom.tistory.com

위의 방식을 통해 람다식 표현이 가능하나, 기본적으로 java 같은 경우는 객체지향이라 순수함수와 일반함수를 다르게 보고 있다. 그러므로 이를 구분하기 위한 방법이 바로 함수형 인터페이스 이다.

 

Java 에서는 기본적으로 4가지의 함수형 인터페이스를 제공한다.

 

1. Supplier<T>

Supplier 는 매개변수는 따로 없고 반환값만 존재하는 함수형 인터페이스이다. Supplier는 T get() 이라는 추상메서드가 있다.

기본적인 사용방식은 아래와 같다.

@FunctionalInterface
public interface Supplier<T> {
	
    T get();
}
Supplier<String> supplier = ()->"Supplier use"
System.out.println(supplier.get()); // Supplier user 출력

 

2. Consumer <T>

Consumer는 객체 T를 매개변수를 받아서 상용하고 반환값은 없는 함수형 인터페이스 이다. Consumer 는 void accept(T t) 라는 추상메서드가 있다. 그리고 Consumer 는 andThen 이라는 함수를 제공하고 있는데, 이 함수를 이용하면 하나의 함수가 끝났을때 다음 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);
                         };
    }
}
Consumer<String> string1 = s -> System.out.println("Hi, " + s);
Consumer<String> string2 = s -> System.out.println("Nice to meet you!");
string1.andThen(string2).accept("babo");

//Hi, babo
//Nice to meet you!

만약에 Consumer에다 split 같은 연산 메서드가 들어갈수도 있는데, 이때 split 가 데이터를 변경했다고 해도 원본데이터는 유지된다.

Consumer<String> string1 = s -> System.out.println(s.split(" ")[0]);
string1.andThen(System.out::println).accept("Hi, babo");

//Hi,
//Hi, babo

 

3. Function<T,R>

Function 은 객체 T를 매개변수로 받고, 로직을 처리하고 R  로 반환하는 함수형 인터페이스이다. Function 은 R apply(T t) 라는 추상메서드를 가진다. Function 은 andThen 뿐만 아니라 compose 도 제공한다.

andThen 이 첫번째 함수가 실행되고 나서 다음 함수를 연결해주는 반면,

compose 는 첫번째 함수 실행 전에 먼저 함수를 실행하여 연결해주는 차이가 있다.

그리고 identity 라는 함수는 자기 자신을 반환해주는 static 함수 이다.

@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(t));
    }
    
    static <T> Function<T, T> identity() {
    	return t->t;
    }
}
Function<String, Integer> function = s -> s.length();
function.apply("Hi, babo")

 

4. Predicate <T>

Predicate 는 객체 T를 파라미터로 받아서 처리하고 Boolean 을 반환하는 함수형 인터페이스이다.

Predicate 는 boolean test(T t) 를 추상 메서드로 가지고 있다.

그리고 and, or, not ,equal 등의 연산을 할수 있는 함수가 있다.

@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);
    }
}

 

Predicate<String> predicate = s -> s.equals("Hi, babo");
predicate.test("Hi, chunjae"); // false

 

끝.

반응형

댓글