ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 람다와 스트림 - java.util.function - part1
    백엔드/자바 2021. 8. 24. 16:16

    이전 람다 파트에선 람다란 무엇인지, 람다의 사용법, 함수형 인터페이스 등에 대해서 배웠다.

     

    다시 한번 간단하게 복습하면 다음과 같다.

     

    - 람다식은 익명 객체를 간략하게 만든 표현식이다.

     

    - 익명 객체를 사용하려면 함수형 인터페이스가 필요하다.

     

    - 함수형 인터페이스를 통해 익명 객체를 사용 할 수 있고, 이때 익명 객체를 람다로 표현이 가능하다.

     

    이제 예제를 보며 함수형 인터페이스와 람다 사용하는 방법을 복습해보자.

     

     

     

    만약 두 숫자를 비교하는 기능을 하는 익명 객체를 만들어 사용해보고 싶다면?

     

    - 우선 함수형 인터페이스를 작성한다.

     

    - 형식에 맞게 람다식을 작성하고 함수형 인터페이스의 참조 변수에 람다식을 저장한다.

     

    - 참조 변수이용해서 숫자를 대입한 뒤 실행하여 결과값을 확인한다.

     

    사실 예제가 간단해서 이 정도 수준이라면 크게 어렵지 않고 코드도 길지 않다.

     

    하지만 조금 더 복잡한 연산 필요하고 이러한 인터페이스가 여러개가 필요하다고 상상해보자.

     

    그렇다면 매번 인터페이스를 만들어주는 식으로 코드를 짜야하고 당연히 가독성이 떨어질 것이다.

     

    그래서 만들어진 것이 바로 java.util.function 패키지다.

     

    java.util.function 패키지

    기존에 함수형 인터페이스를 이용하려면 단 한번을 이용해도 매번 직접 만들어야 했다.

     

    그래서 등장한 것이 바로 java.util.function 패키지다.

     

    이 패키지는 자바 사용자들이 이용할만한 기능이 담긴 인터페이스, 메서드를 미리 만들어 제공한다.

     

    즉 사칙연산, 조건문 등의 자주 쓰는 기능을 가진 인터페이스를 미리 만들어 놓고 제공하는 것이다.

     

    그래서 이 패키지를 사용하면 시간도 절약되고, 코드도 절약되고, 유지보수 측면에서도 유리하다.

     

    다만 인터페이스는 그 숫자가 많아서 주로 쓰이는 것 몇 가지만 익히면 쉽게 사용이 가능하다.

     


    함수형 인터페이스


    메서드


    설명


    Runnable


    void run( )


    매개변수, 반환값 모두 없을 때 사용


    Supplier<T>


    T get( )


    매개변수는 없고, 반환값만 있을 때 사용


    Consumer<T>


    void accept(T t)


    매개 변수는 있고, 반환값은 없을 때 사용


    Function<T,R>


    R apply (T t)


    매개 변수 하나에 반환값이 있을 때 사용


    Predicate<T>


    boolean test(T t)


    조건을 표현하는데 씀.

    매개변수 하나에, 반환값은 boolean 타입

     

    간단히 설명하면 본인이 만들고 싶은 메서드의 형태에 맞는 인터페이스를 리스트에서 선택하는 것이다.

     

    그 다음 선택한 인터페이스로 만든 참조 변수에 람다식을 저장한다.

     

    그 다음 참조변수로 리스트에 있는 메서드를 불러서 실행하면 된다.

     

    별도로 인터페이스를 만들 필요가 없어 빠르고 편리하게 사용이 가능하다.

     

    실제 사용 예시를 보면 더 이해하기 쉬울 것이다.

     

    참고로 아래 내용은 패키지에 있는 인터페이스에서 가장 많이 쓰는 것 5개만 추린 것으로

     

    파트2에서 추가로 더 다룰 예정이다.

     

    함수형 인터페이스 - Runnable

     

    Runnable 인터페이스는 매개 변수가 없고 반환값도 없는 메서드를 만들 때 사용하면 된다.

     

    매개 변수도 없고 리턴 값도 없어서 사용법이 매우 간단하다.

     

    Runnable의 참조 변수에 람다식을 저장하고 그 뒤에 참조변수의 run() 메서드를 실행하면 된다.

     

     

     

    이미 위에서 이야기했지만 패키지에서 제공되는 인터페이스들은 함수형 인터페이스에 이미 만들어졌다.

     

    그래서 그냥 static 메서드를 쓰듯이 그냥 가져다가 쓰면 된다.

     

     

     

    혹시나 run1 참조 변수에 저장된 람다가 이해가 안된다면 위의 코드를 보자.

     

    Runnable은 함수형 인터페이스고 Runnable 참조변수엔 Runnable을 구현한 익명 객체만 저장 가능하다.

     

    그리고 Runnable을 구현한 익명 객체는 Runnable이 가진 run() 메서드도 오버라이딩으로 구현해야 한다.

     

    그렇게 만들어진 것이 run2에 저장된 익명 객체고, run1은 이 익명객체를 람다로 간단히 표현한 것이다.

     

    함수형 인터페이스 - Supplier<T>

     

    매개변수는 없고 반환값만 존재할 때 Supplier 인터페이스를 사용한다. 사용법은 Runnable과 동일하다.

     

    차이점이라면 반환값이 있다는 점이다.

     

    그리고 Supplier는 매개변수가 없을 때 쓰는 인터페이스라 매개변수를 넣으면 컴파일 에러를 볼 수 있다.

     

    이때 주목할 점은 위와 같이 반환 타입이 여러 종류가 될 수 있다는 것이다.

     

    잘 보면 Supplier의 지네릭스 부분에 어떤 타입을 넣느냐에 따라 반환 타입이 변경되는 것을 알 수 있다.

     

     

     

    이는 Supplier 인터페이스의 get( ) 메서드의 반환값이 지네릭스에 따라 달라지기 때문이다.

     

    즉 Supplier<T> 에서 T에 넣는 자료 타입이 get( )의 반환 타입이 되는 것이다.

     

    인터페이스 - Consumer<T>

     

    Consumer<T> 인터페이스도 이전의 Supplier와 사용법은 같다.

     

    다만 람다식 부분에서 볼 수 있듯이 Consumer는 반드시 매개변수가 존재해야 한다는 것이다.

     

    매개 변수 없으면 Consumer는 컴파일 에러를 발생시킨다.

     

    그 외에는 Supplier<T>와 마찬가지로 Consumer<T>도 지네릭스에 들어가는 자료 타입에 따라서

     

    매개변수를 통해 전달 받을 수 있는 자료 타입이 달라진다.

     

     

     

    이러한 점은 다른 인터페이스와 마찬가지로 인터페이스가 가진 메서드때문이다.

     

    위 그림의 accept( T t)을 보면 지네릭스<T>에 따라 매개변수 타입도 바뀌는 것을 알 수 있다.

     

    함수형 인터페이스 - Function<T, R>

     

    우리가 자주 사용하는 매개 변수와 반환값이 모두 존재하는 메서드를 사용하고 싶다면

     

    Function<T, R> 인터페이스를 사용하면 된다.

     

    위 그림을 보면 알겠지만 참조변수를 선언할 때 지네릭스 <T,R>에 자료 타입을 입력해주면 된다.

     

    T 부분은 매개변수의 자료 타입이 되고, R 부분은 반환값의 자료타입이 된다.

     

    예를 들면 Function<String, Integer>로 설정해두면 매개변수의 타입은 String, 반환값은 Integer가 된다.

     

     

     

    이러한 특징은 Function 인터페이스의 apply() 메서드 때문이라고 보면 된다.

     

    함수형 인터페이스 - Predicate<T>

     

    매개변수를 통해 전달된 데이터가 조건에 맞는지 틀린지 판단할 때 사용하는 인터페이스다.

     

    우리가 흔히 if문을 이용해서 조건을 처리하던 것을 구현한 인터페이스라 생각하면 된다.

     

    사용법은 다른 인터페이스랑 비슷하다.

     

    우선 참조변수를 선언할 때 <T> 지네릭스에 매개변수로 전달될 자료타입을 지정한다.

     

    그리고 매개변수를 통해 전달된 데이터를 어떻게 검증할지 람다식으로 만들어주면 된다.

     

    주의할 점은 반환 타입은 무조건 boolean이라는 것이다.

     

    함수형 인터페이스 활용

    이전 단락들에선 간단하게 함수형 인터페이스 사용법을 익혔다.

     

    이번에는 이 인터페이스들을 조합해서 어떤식으로 활용할 수 있는지 예시를 보도록 하자.

     

     

     

    위 코드는 랜덤 정수 5개를 뽑아서 리스트에 저장한 다음 짝수를 판별하여 출력하도록 한 코드다.

     

    내용이 길긴한데 하나씩 잘라서 살펴보도록 하자.

     

     

     

    이미 위에서 설명했듯 랜덤 정수를 뽑아서 짝수를 판별하는 것이 이 코드의 목적이다.

     

    우선 매개변수 없이 랜덤 정수를 뽑아서 전달할 수 있는 람다식은 Supplier 타입의 참조변수에 저장했다.

     

    그 다음 짝수를 판별할 수 있는 람다식은 매개변수를 받아 true, false를 판단 가능한 predicate에 저장했다.

     

    마지막으로 짝수로 판별된 정수를 반환없이 출력하는 람다식을 Consumer에 저장했다.

     

    이러면 우선 기본적인 준비는 끝났고 이제 메서드를 만들어줄 차례다.

     

     

     

    이 메서드는 제목 그대로 리스트를 만드는 메서드다.

     

    for문이 5번 돌아가는 동안 매개변수로 받은 Supplier의 참조변수 s가 랜덤 정수를 5개를 반환한다.

     

    그러면 이 반환된 정수가 리스트에 저장되는 기능을 한다.

     

     

     

    마지막으로 makeList()메서드를 통해 만들어진 리스트를 매개변수로 제공하고

     

    for문을 통해 각 요소가 짝수인지 홀수인지 매개변수로 받은 Predicate를 이용해 판별한다.

     

    만약 true가 나올 경우 매개변수를 통해 받은 Consumer는 해당 요소를 받아서 출력하는 역할을 한다.

     

     

     

    이제 직접 실행을 해보도록 하자.

     

    실행은 메인 함수 안에서 메서드를 선언하여 참조형 인터페이스 타입의 참조변수들을 매개변수로 전달하면 된다.

     

     

     

    그리고나서 결과를 확인하면 위와 같이 랜덤하게 출력된 함수 중 짝수만 뽑아서 출력된 것을 볼 수 있다.

     

    함수형 인터페이스는 단독사용도 가능하지만, 이처럼 매개변수 또는 반환값으로도 사용할 수 있으므로

     

    잘 이용하면 더 빠른 작업과 코드를 깔끔하게 만들 수 있는 효과를 가져온다.

Designed by Tistory.