본문 바로가기

Java 길찾기/이것이 자바다

[Java] 표준 API의 함수적 인터페이스 - Suplier, Function

Supplier 함수적 인터페이스

Supplier 함수적 인터페이스의 특징은 매개 변수가 없고 리턴값이 있는 getXXX() 메소드를 가지고 있다. 이 메소드들은 실행 후 호출한 곳으로 데이터를 리턴하는 역할을 한다.

리턴 타입에 따라서 아래와 같은 Supplier 함수적 인터페이스들이 있다.

인터페이스명 추상 메소드 설명
Supplier<T> T get() T 객체를 리턴
BooleanSupplier boolean getAsBoolean() boolean 값을 리턴
DoubleSupplier double getAsDouble() double 값을 리턴
IntSupplier int getAsInt() int 값을 리턴
LongSupplier long getAsLong() long 값을 리턴

 

Supplier<T> 인터페이스를 타겟 타입으로 하는 람다식은 다음과 같이 작성할 수 있다. get() 메소드가 매개값을 가지지 않으므로 람다식도 ( )를 사용한다. 람다식의 중괄호 { }는 반드시 한 개의 T 객체를 리턴하도록 해야 한다. T가 String 타입이므로 람다식의 중괄호 { }는 문자열을 리턴하도록 해야 한다.

Supplier<String> supplier = () -> { ...; return "문자열"; }

 

IntSupplier 인터페이스를 타겟 타입으로 하는 람다식은 다음과 같이 작성할 수 있다. getAsInt() 메소드가 매개값을 가지지 않으므로 람다식도 ( )를 사용한다. 람다식의 중괄호 { }는 반드시 int 값을 리턴하도록 해야 한다.

IntSupplier supplier = () -> { ...; return int값; }

 

 다음 예제는 주사위의 숫자를 랜덤하게 공급하는 IntSupplier 인터페이스를 타겟 타입으로 하는 람다식이다.

// SupplierExample.java -- Supplier 함수적 인터페이스
import java.util.function.IntSupplier;

public class SupplierExample {
    public static void main(String[] args) {
        IntSupplier intSupplier = () -> {
            int num = (int) (Math.random() * 6) + 1;
            return num;
        };
        int num = IntSupplier.getAsInt();
        System.out.println("눈의 수: " + num);
    }
}

 

Function 함수적 인터페이스

Function 함수적 인터페이스의 특징은 매개값과 리턴값이 있는 applyXXX() 메소드를 가지고 있다. 이 메소드들은 매개값을 리턴값으로 매핑(타입 변환)하는 역할을 한다.

매개 변수 타입과 리턴 타입에 따라서 아래와 같은 Function 함수적 인터페이스들이 있다.

인터페이스명 추상 메소드 설명
Function<T, R> R apply(T t) 객체 T를 객체 R로 매핑
BiFunction<T, U R> R apply(T t, U u) 객체 T와 U를 객체 R로 매핑
DoubleFunction<R> R apply(double value) double 을 객체 R로 매핑
IntFunction<R> R apply(int value) int를 객체 R로 매핑
IntToDoubleFunction double applyAsDouble(int value) int를 double로 매핑
IntToLongFunction long applyAsLong(int value) int를 long으로 매핑
LongToDoubleFucntion double applyAsDouble(long value) long을 double로 매핑
LongToIntFunction int applyAsInt(long value) long을 int로 매핑
ToDoubleFunction<T, U> double applyAsDouble(T t, U u) 객체 T와 U를 double로 매핑
ToDoubleFunction<T> double applyAsDouble(T t) 객체 T를 double로 매핑
ToIntBiFunction<T, U> int applyAsInt(T t, U t) 객체 T와 U를 int로 매핑
ToIntFunction<T> int applyAsInt(T t) 객체 T를 int로 매핑
ToLongBiFunction<T, U> long applyAsLong(T t, U u) 객체 T와 U를 long으로 매핑
ToLongFunction<T> long aplyAsLong(T t) 객체 T를 long으로 매핑

 

Function<T, R> 인터페이스를 타겟 타입으로 하는 람다식은 다음과 같이 작성할 수 있다. apply() 메소드는 매개값으로 T 객체 하나를 가지므로 람다식도 한 개의 매개 변수를 사용한다. 그리고 apply() 메소드의 리턴 타입이 R이므로 람다식의 중괄호 { }의 리턴값은 R 객체가 된다. T가 Student 타입이고 R이 String 타입이므로 t 매개 변수 타입은 Student가 되고, 람다식의 중괄호 { }는 String을 리턴해야 한다. t.getName()은 Student 객체의 getName() 메소드를 호출해서 학생 이름(String)을 얻는다. return 문만 있을 경우 중괄호 { }와 return 문은 생략할 수 있다는 것을 이미 배웠다. 다음 코드는 Student 객체를 학생 이름(String)으로 매핑하는 것이다.

Fucntion<Student, String> function = t -> { return t.getName(); }
또는
Function<Student, String> function = t -> t.getName();

 

ToIntFunction<T> 인터페이스를 타겟 타입으로 하는 람다식은 다음과 같이 작성할 수 있다. applyAsInt() 메소드는 메개값으로 T 객체 하나를 가지므로 람다식도 한 개의 매개 변수를 사용한다. 그리고 applyAsInt() 메소드의 리턴 타입이 int이므로 람다식 중괄호 { }의 리턴값은 int가 된다. T가 Student 타입이므로 t 매개 변수 타입은 Student가 된다. t.getScore()는 Student 객체의 getScore() 메소드를 호출해서 학생 점수(int)를 얻는다. 다음 코드는 Student 객체를 학생 점수(int)로 매핑하는 것이라고 볼 수 있다.

ToIntFunction<Student> function = t -> { return t.getScore(); }
또는
ToIntFunction<Student> function = t -> t.getScore();

 

다음 예제는 List에 저장된 학생 객체를 하나씩 꺼내서 이름과 점수를 출력한다. FunctionExample1의 printString() 메소드는 Function<Student, String> 매개 변수를 가지고 있고, printInt() 메소드는 ToIntFunction<Student> 매개 변수를 가지고 있으므로 이 메소드들을 호출할 때 매개값으로 람다식을 사용할 수 있다.

// FucntionExample.java -- Function 함수적 인터페이스
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.ToIntFunction;

public class FuntionExmaple1 {
    private static List<Student> list = Arrays.asList(
        new Student("홍길동", 90, 96),
        new Student("김자바", 95, 93)
    );
    
    public static void printString(Function<Student, String> function) {
        for(Student student : list) { // list에 저장된 항목 수만큼 루핑
            System.out.print(function.apply(student) + " ");
        }
        System.out.println();
    }
    
    public static void printlnt(ToIntFunction<Student> function) {
        for(Student student : List) {
            System.out.print(function.applyAsInt(student) + " ");
        }
        System.out.println();
    }
    
    public static void main(String[] args) {
        System.out.println("[학생 이름]");
        printString(t->t.getName());
        
        System.out.println("[영어 점수]");
        printInt(t->t.getEnglishScore());
        
        System.out.println("[수학 점수]");
        printInt(t->t.getMathScore());
    }
}
// Student.java -- Student 클래스
public class Student {
    private String name;
    private int englishScore;
    private int mathScore;
    
    public Student(String name, int englishScore, int mathScore) {
        this.name = name;
        this.englishScore = englishScore;
        this.mathScore = mathScore;
    }
    
    public String getName() { return name; }
    public int getEnglishScore() { return englishScore; }
    public int getMathScore() { return mathScore; }

 

다음 예제는 List에 저장된 학생 객체를 하나씩 꺼내서 영어 점수와 수학 점수의 평균값을 산출한다. FunctionExample2의 avg() 메소드는 ToIntFunction<Student> 매개 변수를 가지고 있다. 따라서 avg() 메소드를 호출할 때 매개값으로 람다식을 사용할 수 있다. 람다식은 getEnglishScore()와 getMathScore()를 호출해서 영어 점수와 수학 점수로 Student 객체를 매핑시킨다.

// FunctionExmaple2.java -- Function 함수적 인터페이스
import java.util.Arrays;
import java.util.List;
import java.util.function.ToIntFunction;

public class FunctionExample2 {
    private static List<Student> list = Array.asList(
        new Student("홍길동", 90, 96),
        new Student("김자바", 95, 93)
    );
    
    public static double avg( ToIntFunction<Student> function) {
        int sum = 0;
        for(Student student : List) {
            sum += function.applyAsInt(student);
        }
        double avg = (double) sum / list.size();
        return avg;
    }
    
    public static void main(String[] args) {
        double mathAvg = avg(s -> s.getMathScore());
        System.out.println("수학 평균 점수: " + mathAvg);
    }
}