Today
-
Yesterday
-
Total
-
  • 함수형 인터페이스
    Language/Java 2023. 12. 1. 00:01

    Functional Interface

    java 8에서 도입된 개념으로 정확히 하나의 추상 메서드를 가진 인터페이스를 말한다.

    이 함수형 인터페이스는 람다 표현식으로 잘 활용된다.


    자바에는 여러가지 내장된 함수형 인터페이스가 있지만,

    특히 자바 공부할 때

    기능 설명 부분에서 자주 볼 수 있었던

    몇 가지 인터페이스에 대해서 정리 ✏️



    Function<T, R>

    매개변수     : T Return 타입 : R 추상 메서드 : apply()           기능 : T 타입의 인자를 받으며, R 타입의 결과를 반환한다.

    사용 예시

    기본 표현 방식 사용

    public static void getLastIndex(String text) {
    
        Function<String, Integer> getBasicLastIndex = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length() - 1;
            }
        };
    
        System.out.println(
                getBasicLastIndex.apply(text)
        );
    }

    람다 표현 방식 사용

    public static void getLastIndex(String text) {
    
        Function<String, Integer> getLambdaLastIndex = s -> s.length() - 1;
    
        System.out.println(
                getLambdaLastIndex.apply(text)
        );
    }

    Function 에서 사용할 수 있는 Default 메서드

    🤓✏️ Default 메서드

    자바 8에서 추가된 기능으로 
    
    인터페이스에서 선언과 구현을 동시에 하는 방법이다.
    
    인터페이스를 정의할 때 default 키워드를 사용하여 메서드를 작성하면 된다.
    
    디폴트 메서드를 사용하면,
    
    인터페이스에 새로운 메서드(default)를 추가하더라도 
    기존에 사용중이던 클래스를 수정하지 않고도 인터페이스에 추가된 메서드를 사용할 수 있다.
    
    주의 할 부분은
    여러 인터페이스에서 동일한 디폴트 메서드를 제공하는 경우 
    충돌이 발생할 수 있으므로 유의해서 사용해야 한다.
    

    * andThen()

    주어진 함수를 첫 번째 함수의 결과에 적용하여 새로운 자료형의 반환값을 반환한다.

    f.andThen(g) 형태로 사용하며, 수학적으로 표현하면 g(f(x))와 같다.

    Function<Integer, Integer> f1 = num -> num * 2;
    Function<Integer, Integer> f2 = num -> num * num;
    
    Function<Integer, Integer> f = f1.andThen(f2);
    System.out.println(f.apply(3));

    위에 작성한 코드를 보면 마지막 sout 문장 안에 있는 andThen 결과인 f에 3을 주었다.

    3f1에서 f1의 구현 내용으로 가공된 후 , 반환값이f2에 들어가서 f2의 구현 내용에 따라 2차 가공되어 최종 반환된다.

    이 경우 3 -> 3*2 -> 6*6 -> 36 순서로 값의 변화가 일어난다.

    * compose()

    compose()는 반대로 첫 번째 함수의 결과를 두 번째 함수에 적용한다.

    f.andThen(g) 형태로 사용하며, 수학적으로 표현하면 f(g(x))와 같다.



    아래 부터 소개하는 인터페이스의 디폴트 메서드는 나중에 정리 😵‍💫

    Predicate<T>

    매개변수     : T Return 타입 : boolean 추상 메서드 : test()           기능 : T 타입의 인자를 받으며 boolean을 반환한다.

    사용 예시

    기본 표현 방식 사용

    public static void isEvenOdd() {
    
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer % 2 == 0;
            }
        };
        
        System.out.println(
                predicate.test(2)
                        ? "짝수 입니다."
                        : "홀수 입니다."
        ); 
    }

    람다 표현 방식 사용

    public static void isEvenOdd() {
        
        Predicate<Integer> predicate2 = i -> i % 2 == 0;
    
        System.out.println(
                predicate2.test(3)
                        ? "짝수 입니다."
                        : "홀수 입니다."
        );
    }



    Consumer<T>

    매개변수     : T Return 타입 : void 추상 메서드 : accept()           기능 : T 타입의 인자를 받으며, 아무런 결과도 반환하지 않는다.

    결과를 반환하지 않고 값을 사용하기만 해서 소비자인가 🙊

    사용 예시

    기본 표현 방식 사용

    public static void print() {
    
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.printf("\"%s\" 입력 받았슴다 🤓\n", s);
            }
        };
        consumer.accept("가나다라");
    
    }

    람다 표현 방식 사용

    public static void print() {
    
        Consumer<String> consumer2 = s -> System.out.printf("\"%s\" 입력 받았슴다 🤓\n", s);
        consumer2.accept("아자차카타파하하하하하");
        
    }

    메서드 참조 표현식 사용

    메서드 참조 🤓✏️ > 지금은 간단히 적어두고 나중에 추가 공부 계획

    자바 8에서 도입

    이미 정의된 메서드를 람다 표현식 대신에 직접 참조할 수 있게 해준다.

    4가지 유형의 사용 방법이 있음!

    1. 정적(static) 메서드 참조 : 클래스::정적메서드 ex : Integer::parseInt

    2. 인스턴스 메서드 참조 : 인스턴스::메서드 ex : System.out::println

    3. 비한정적 인스턴스 메서드 참조 : 클래스::메서드 ex : String::length

    4. 생성자 참조 : 클래스::new ex : ArrayList::new

    public static void print() {
    
        Consumer<String> consumer3 = System.out::println;
        consumer3.accept("하하 🙈");
    
    }

    이렇게 사용하면 Consumer.accept(T t) = System.out.println(t) 이런식으로 적용 된다.



    Supplier<T>

    매개변수     : void Return 타입 : T 추상 메서드 : get()           기능 : 인자를 받지 않고, T 타입의 결과를 반환한다.

    오, Getter()랑 같은 기능! 그러면 반대로 동작하는 Consumer.accept() 는 Setter() !! 🙊

    공급자는 get() == getter() 소비자는 accept() == setter() 🙊

    주로 특정 값을 생성하거나, 계산하는데 사용된다고 한다.

    사용 예시

    기본 표현 방식 사용

    public static void getNowTime() {
    
        Supplier<LocalDateTime> supplier = new Supplier<LocalDateTime>() {
            @Override
            public LocalDateTime get() {
                return LocalDateTime.now();
            }
        };
        System.out.println(
                supplier.get()
        );
    
    }

    람다 표현식 사용

    public static void getNowTime() {
        
        Supplier<LocalDateTime> supplier2 = () -> LocalDateTime.now();
        System.out.println(
                supplier2.get()
        );
    
    }

    메서드 참조 방식 사용

    public static void getNowTime() {
        
        Supplier<LocalDateTime> supplier3 = LocalDateTime::now;
        System.out.println(
                supplier3.get()
        );
        
    }



    UnaryOperator<T>

    매개변수     : T Return 타입 : T 추상 메서드 : T apply(T t)           기능 : 인자로 T를 받고, T를 반환한다.

    Function<T, T> 를 확장한 인터페이스 이다. Function의 apply() 메서드를 그대로 사용한다. Function과 UnaryOperator의 차이점으로는 Function은 매개변수와 결과값의 자료형이 달라질 수 있고 UnaryOperator는 매개변수와 결과값의 자료형이 같아야 한다.

    사용 예시

    기본 표현 방식 사용

    public static void getPow() {
    
        UnaryOperator<Integer> uo = new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer num) {
                return num * num;
            }
        };
        System.out.println( uo.get() );
    
    }

    람다 표현 방식 사용

    public static void getPow() {
    
        UnaryOperator<Integer> uo = num -> num * num;
        System.out.println( uo.get() );
    
    }



    BinaryOperator<T>

    매개변수     : T Return 타입 : T 추상 메서드 : T apply(T t, T t)           기능 : T 타입의 인자를 2개 받고, T를 반환한다.

    사용 예시

    기본 표현 방식 사용

    public static void print(String str1, String str2) {
    
    	BinaryOperator<String> bo = new BinaryOperator<String>() {
    	    @Override
    	    public String apply(String s, String s2) {
    	        return s.length() >= s2.length() ? s : s2;
    	    }
    	};
    	System.out.println( bo.apply("monkey", "monday..") );
        
    }

    람다 표현 방식 사용

    public static void print2(String str1, String str2) {
    
    	BinaryOperator<String> bo = (s, s2) -> s.length() >= s2.length() ? s : s2;
    	System.out.println( bo.apply("monkey", "monday..") );
    
    }





    앞으로 강의 실습 계속 하면서 새롭고 낯선 함수형 인터페이스를 만나게 되면 추가할 계획!

    'Language > Java' 카테고리의 다른 글

    UUID.randomUUID()  (0) 2023.12.01
    Stream  (0) 2023.12.01
    enum 클래스  (0) 2023.11.30
    Optional  (0) 2023.11.30
    자바 메모리 모델 Java Memory Model  (0) 2023.11.30

Designed by Tistory / Custom by 얼거스