개발

[Java] 공급자 Supplier<T>

오렌지색 귤 2022. 1. 25. 00:53
반응형

공급자

내부 코드

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

Supplier는 매개변수를 받지 않고 단순히 반환하는 추상 메서드가 존재한다

 

활용 방식

 

1. 문자열 return

public class SupplierStringReturn {
    public static void main(String[] args) {

        Supplier<String> helloSupplier = () -> "Hi";

        System.out.println(helloSupplier.get());
    }
}

// 결과
// Hi

 

2. 객체 return

public class SupplierObjectReturn {

    static class Point { }

    public static void main(String[] args) {

        Supplier<Point> pointSupplier = () -> new Point();

        System.out.println(pointSupplier.get());

        System.out.println(pointSupplier.getClass());
    }
}

// 결과
// doodle.item03.SupplierObjectReturn$Point@4eec7777
// class doodle.item03.SupplierObjectReturn$$Lambda$1/1283928880

 

3. 메서드 참조 방식

public class SupplierMethodReference {

    public static void main(String[] args) {

        Supplier<String> supplier = SupplierMethodReference::getFire;

        System.out.println(supplier.get());
    }

    private static String getFire() {
        return "BOOM!";
    }
}

// 결과
// BOOM!

 

4. 원시 타입 값 return

public class SupplierPrimitive {

    public static void main(String[] args) {

        BooleanSupplier booleanSupplier = () -> "a".equalsIgnoreCase("A");
        DoubleSupplier doubleSupplier = () -> 5 / 3.0;
        IntSupplier intSupplier = () -> 6 * 10;
        LongSupplier longSupplier = () -> 5l + 10l;

        System.out.println(booleanSupplier.getAsBoolean());
        System.out.println(doubleSupplier.getAsDouble());
        System.out.println(intSupplier.getAsInt());
        System.out.println(longSupplier.getAsLong());
    }
}

// 결과
// true
// 1.6666666666666667
// 60
// 15

 

5. 무한 Stream 생성

public class SupplierStreamGenerate {

    public static void main(String[] args) {

        Supplier<Double> supplier = () -> new Random().nextGaussian();

        List<Double> list = Stream.generate(supplier)
            .limit(6)
            .collect(Collectors.toList());

        System.out.println(list);
    }
}

// 결과
// [0.4606804564124732, -1.13455907127883, -1.3330230626143407, 1.2478219314557397, -1.6212342383093146, -0.32124419611072896]

 

 

공급자를 활용하면 추상메서드 get()을 통해 Lazy Evaluation이 가능

 

Lazy Evaluation 정의

  • 불필요한 연산을 피하기 위해 연산을 지연시키는 행위
  • JPA에서의 지연 로딩과 유사한 뜻으로 생각됩니다

 

일반 상황

 

아래의 코드에서 printIfValidIndex 메서드가 호출되기 전에 getValue() 메서드가 호출되면서 스레드를 1초간 sleep 시키므로 결국 2초가 지연되게 됩니다.

public class LazyEvaluation {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        printIfValidIndex(10, getValue());
        printIfValidIndex(-10, getValue());
        System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " Second");
    }

    private static String getValue() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Valid";
    }

    private static void printIfValidIndex(int number, String value) {
        if (number > 0) {
            System.out.println(value);
        } else {
            System.out.println("Invalid");
        }
    }
}

// 결과
// Valid
// Invalid
// It took 2 Second

 

Supplier를 활용한 Lazy Evaluation

 

아래의 코드에서는 람다식인 () -> getValue()가 호출되면 이를 Supplier로 받아서 사용합니다.


따라서 실제로 전달된 number가 0보다 큰 경우에 한해서 get() 메서드가 호출되면 getValue()가 실제로 호출되어 1초간 지연이 됩니다.

public class LazyEvaluation2 {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        printIfValidIndex(10, () -> getValue());
        printIfValidIndex(-10, () -> getValue());
        System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " Second");
    }

    private static String getValue() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Valid";
    }

    private static void printIfValidIndex(int number, Supplier<String> valueSupplier) {
        if (number > 0) {
            System.out.println(valueSupplier.get());
        } else {
            System.out.println("Invalid");
        }
    }
}

// 결과
// Valid
// Invalid
// It took 1 Second

 

 

참고

아래 사이트에서 예제 코드 및 형식을 빌려와 직접 작성한 포스팅입니다.

주현님의 블로그
CodeChaCha

반응형