๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
BackEnd๐ŸŒฑ/Java

Java์˜ ๊ธฐ๋ณธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

by ์•ˆ์ฃผํ˜• 2023. 3. 20.

์„œ๋ก 

์‚ฌ๋‚ด ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋‹ค๊ฐ€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค, ๊ทธ์ค‘์—์„œ๋„ BiFunction<T, U, R>์„ ์‚ฌ์šฉํ•œ ๋กœ์ง์„ ์ž์ฃผ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์‹ค์ œ๋กœ ๋ณด๋‹ˆ ์ƒ์†Œํ•˜๊ธฐ๋„ ํ•˜๊ณ , ์ €๋„ ๋กœ์ง์— ํ•œ๋ฒˆ ๋…น์—ฌ๋ณด๊ณ  ์‹ถ์–ด์„œ ์ด๋ฒˆ ๊ธฐํšŒ์— ์ •๋ฆฌ๋ฅผ ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
 

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ข…๋ฅ˜

Java์˜ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” JAVA 8๋ถ€ํ„ฐ ๋„์ž…๋œ ๊ธฐ๋Šฅ์œผ๋กœ, ํ•˜๋‚˜์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋งŒ ๊ฐ€์ง€๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ ๋žŒ๋‹ค ํ‘œํ˜„์‹์ด๋‚˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Java์—์„œ๋Š” java.util.function ํŒจํ‚ค์ง€๋ฅผ ํ†ตํ•ด ๋ฏธ๋ฆฌ ์ •์˜๋œ ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
Java์—์„œ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด ๋‘” ์ฃผ์š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. Function<T, R>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๊ฒฐ๊ณผ R์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ฃผ๋กœ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.
    • R apply(T t)
  2. BiFunction<T, U, R>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ ๊ฒฐ๊ณผ R์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
    • R apply(T t, U u)
  3. Consumer<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ ์—†์œผ๋ฉฐ, ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.
    • void accept(T t)
  4. BiConsumer<T, U>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ๋ฐ˜ํ™˜ ๊ฐ’์€ ์—†๋‹ค.
    • void accept(T t, U u)
  5. Supplier<T>: ์ž…๋ ฅ ์ธ์ˆ˜ ์—†์ด ๊ฒฐ๊ณผ T๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ฃผ๋กœ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ณต๊ธ‰ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.
    • T get()
  6. Predicate<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ฃผ๋กœ ์กฐ๊ฑด ๊ฒ€์‚ฌ์— ์‚ฌ์šฉ๋œ๋‹ค.
    • boolean test(T t)
  7. BiPredicate<T, U>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
    • boolean test(T t, U u)
  8. UnaryOperator<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๋™์ผํ•œ ์œ ํ˜•์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. Function<T, T>์˜ ์„œ๋ธŒ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฉฐ, ์ฃผ๋กœ ๋‹จํ•ญ ์—ฐ์‚ฐ ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.
    • T apply(T t)
  9. BinaryOperator<T>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๋™์ผํ•œ ์œ ํ˜•์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. BiFunction<T, T, T>์˜ ์„œ๋ธŒ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฉฐ, ์ฃผ๋กœ ์ดํ•ญ ์—ฐ์‚ฐ ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.
    • T apply(T t1, T t2)
  10. ์ด ์™ธ์˜ ํ•จ์ˆ˜๋“ค

 

์˜ˆ์ œ

โญ๏ธ Function<T, R> : ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๊ฒฐ๊ณผ R์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜, ์ฃผ๋กœ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…์— ์‚ฌ์šฉ

import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String, Integer> strLength = str -> str.length();

        System.out.println("Length of 'Hello': " + strLength.apply("Hello")); // ์ถœ๋ ฅ: Length of 'Hello': 5
    }
}

 

โญ๏ธ BiFunction<T, U, R>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ ๊ฒฐ๊ณผ R์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜

import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;

        System.out.println("10 + 20 = " + add.apply(10, 20)); // ์ถœ๋ ฅ: 10 + 20 = 30
    }
}

 

โญ๏ธ Consumer<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜, ๋ฐ˜ํ™˜๊ฐ’์€ ์—†์œผ๋ฉฐ, ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉ

import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase());

        printUpperCase.accept("hello world"); // ์ถœ๋ ฅ: HELLO WORLD
    }
}

 

โญ๏ธ BiConsumer<T, U>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜, ๋ฐ˜ํ™˜ ๊ฐ’์€ ์—†์Œ

import java.util.function.BiConsumer;

public class Main {
    public static void main(String[] args) {
        BiConsumer<String, Integer> printNTimes = (str, n) -> {
            for (int i = 0; i < n; i++) {
                System.out.println(str);
            }
        };

        printNTimes.accept("Hello", 3);
        // ์ถœ๋ ฅ:
        // Hello
        // Hello
        // Hello
    }
}

 

โญ๏ธ Supplier<T>: ์ž…๋ ฅ ์ธ์ˆ˜ ์—†์ด ๊ฒฐ๊ณผ T๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜, ์ฃผ๋กœ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ณต๊ธ‰ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉ

import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) {
        Supplier<Double> randomSupplier = () -> Math.random();

        System.out.println("Random number: " + randomSupplier.get()); // ์ถœ๋ ฅ: Random number: 0.123456789 (์˜ˆ์‹œ)
    }
}

 

โญ๏ธ Predicate<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜, ์ฃผ๋กœ ์กฐ๊ฑด ๊ฒ€์‚ฌ์— ์‚ฌ์šฉ

import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        Predicate<Integer> isEven = num -> num % 2 == 0;

        System.out.println("10์€ ์ง์ˆ˜์ž…๋‹ˆ๊นŒ? " + isEven.test(10)); // ์ถœ๋ ฅ: 10์€ ์ง์ˆ˜์ž…๋‹ˆ๊นŒ? true
        System.out.println("15์€ ์ง์ˆ˜์ž…๋‹ˆ๊นŒ? " + isEven.test(15)); // ์ถœ๋ ฅ: 15์€ ์ง์ˆ˜์ž…๋‹ˆ๊นŒ? false
    }
}

 

โญ๏ธ BiPredicate<T, U>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T์™€ U๋ฅผ ๋ฐ›์•„ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜

import java.util.function.BiPredicate;

public class Main {
    public static void main(String[] args) {
        BiPredicate<Integer, Integer> areBothEven = (a, b) -> a % 2 == 0 && b % 2 == 0;

        System.out.println("10๊ณผ 20์€ ๋ชจ๋‘ ์ง์ˆ˜์ธ๊ฐ€? " + areBothEven.test(10, 20)); // ์ถœ๋ ฅ: 10๊ณผ 20์€ ๋ชจ๋‘ ์ง์ˆ˜์ธ๊ฐ€? true
        System.out.println("10๊ณผ 15์€ ๋ชจ๋‘ ์ง์ˆ˜์ธ๊ฐ€? " + areBothEven.test(10, 15)); // ์ถœ๋ ฅ: 10๊ณผ 15์€ ๋ชจ๋‘ ์ง์ˆ˜์ธ๊ฐ€? false
    }
}

 

โญ๏ธ UnaryOperator<T>: ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๋™์ผํ•œ ์œ ํ˜•์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜, ์ฃผ๋กœ ๋‹จํ•ญ ์—ฐ์‚ฐ ์ž‘์—…์— ์‚ฌ์šฉ

import java.util.function.UnaryOperator;

public class Main {
    public static void main(String[] args) {
        UnaryOperator<Integer> square = num -> num * num;

        System.out.println("5์˜ ์ œ๊ณฑ: " + square.apply(5)); // ์ถœ๋ ฅ: 5์˜ ์ œ๊ณฑ: 25
    }
}

 

โญ๏ธ BinaryOperator<T>: ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ˆ˜ T๋ฅผ ๋ฐ›์•„ ๋™์ผํ•œ ์œ ํ˜•์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜, ์ฃผ๋กœ ์ดํ•ญ ์—ฐ์‚ฐ ์ž‘์—…์— ์‚ฌ์šฉ

import java.util.function.BinaryOperator;

public class Main {
    public static void main(String[] args) {
        BinaryOperator<Integer> multiply = (a, b) -> a * b;

        System.out.println("5 * 10 = " + multiply.apply(5, 10)); // ์ถœ๋ ฅ: 5 * 10 = 50
    }
}

 

 

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์žฅ์ 

  • ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ: ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์„ ๋†’์ธ๋‹ค.
  • ๋†’์€ ๋ชจ๋“ˆ์„ฑ: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜์™€ ๋†’์€ ๋ชจ๋“ˆ์„ฑ์„ ์ง€ํ–ฅํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์›Œ์ง€๋ฉฐ, ํ…Œ์ŠคํŠธ์™€ ๋””๋ฒ„๊น…์ด ์šฉ์ดํ•ด์ง„๋‹ค.
  • ๋ถˆ๋ณ€์„ฑ: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ตœ์†Œํ™”ํ•˜๋ฉฐ ๋ถˆ๋ณ€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋กœ ์ธํ•ด ์•ˆ์ „์„ฑ์ด ๋†’์•„์ง€๋ฉฐ, ๋ฒ„๊ทธ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ์ค„์–ด๋“ ๋‹ค.
  • ๊ณ ์ฐจ ํ•จ์ˆ˜ ์‚ฌ์šฉ: ๊ณ ์ฐจ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ฑฐ๋‚˜ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๊ธฐ์—, ๊ณ ์ฐจํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ์กฐํ•ฉํ•˜๊ฑฐ๋‚˜ ์ถ”์ƒํ™”ํ•˜์—ฌ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ถ€์ˆ˜ ํšจ๊ณผ(Side Effect)๊ฐ€ ์—†๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ฅผ ์„ ํ˜ธํ•˜๋ฏ€๋กœ, ๋™์‹œ์„ฑ๊ณผ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ์— ์ ํ•ฉํ•˜๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ€ํ‹ฐ์ฝ”์–ด ์‹œ์Šคํ…œ์—์„œ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
  • ์ง€์—ฐ ํ‰๊ฐ€: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ์ง€์—ฐ ํ‰๊ฐ€(Lazy Evaluation)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ์„ ํ”ผํ•˜๊ณ , ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ์˜ ํšจ์œจ์„ฑ: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ŠคํŠธ๋ฆผ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปฌ๋ ‰์…˜์„ ์‰ฝ๊ฒŒ ์กฐ์ž‘ํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋ฒˆ์™ธ

์ถ”๊ฐ€๋กœ ์ œ๊ฐ€ ์•Œ๊ณ ์‹ถ์—ˆ๋˜ BiFunction์— ๋Œ€ํ•ด์„œ ๋” ์ž์„ธํžˆ ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๋จผ์ € BiFunction ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ •์˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

์—ฌ๊ธฐ์„œ T, U, R์€  ์ œ๋„ค๋ฆญ ํƒ€์ž…์ด๋ฉฐ, ๊ฐ๊ฐ ๋‘ ๊ฐœ์˜ ์ž…๋ ฅ ์ธ์ž์™€ ๋ฐ˜ํ™˜ ๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
BiFunction ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ๋‹ค์Œ ๋ฉ”์„œ๋“œ๋“ค์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. apply(T t, U u): ๋‘ ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›์•„์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์‹ค์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  2. andThen(Function<? super R, ? extents V> after): ์ด ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ์˜ BiFunction ์ธ์Šคํ„ด์Šค์™€ ๋‹ค๋ฅธ Function ์ธ์Šคํ„ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉฐ, ํ˜„์žฌ ์ธ์Šคํ„ด์Šค์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜์˜ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ตœ์ข…์ ์œผ๋กœ ์ƒˆ๋กœ์šด BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
        // BiFunction ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        BiFunction<Integer, Integer, Integer> adder = (a, b) -> a + b;

        // apply ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•จ
        int result = adder.apply(5, 3);
        System.out.println("5 + 3 = " + result);

        // andThen ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐ
        BiFunction<Integer, Integer, Integer> multiplier = (a, b) -> a * b;
        Function<Integer, String> toString = num -> "๊ฒฐ๊ณผ: " + num;

        BiFunction<Integer, Integer, String> combined = adder.andThen(toString);
        String combinedResult = combined.apply(5, 3);
        System.out.println(combinedResult);
    }
}

์ถœ๋ ฅ ๊ฒฐ๊ณผ
5 + 3 = 8
๊ฒฐ๊ณผ: 8

์œ„ ์ฝ”๋“œ๋Š” ๋‘ ๊ฐœ์˜ BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , apply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ์ˆซ์ž๋ฅผ ๋”ํ•œ ๋‹ค์Œ, andThen ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์™€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

import java.util.function.BiFunction;
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        // ๋ฌธ์ž์—ด ๊ฒฐํ•ฉ BiFunction ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        BiFunction<String, String, String> concat = (a, b) -> a + b;

        // apply ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๋ฌธ์ž์—ด์„ ๊ฒฐํ•ฉ
        String result = concat.apply("Hello, ", "World!");
        System.out.println("๊ฒฐ๊ณผ: " + result);

        // andThen ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€๋ฌธ์ž ๋ณ€ํ™˜ ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐ
        Function<String, String> toUpperCase = String::toUpperCase;
        BiFunction<String, String, String> combined = concat.andThen(toUpperCase);

        // ์—ฐ๊ฒฐ๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด ๊ฒฐํ•ฉ ๋ฐ ๋Œ€๋ฌธ์ž ๋ณ€ํ™˜ ์ˆ˜ํ–‰
        String combinedResult = combined.apply("hello, ", "world!");
        System.out.println(combinedResult);
    }
}

์ถœ๋ ฅ ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ: Hello, World!
HELLO, WORLD!

์œ„ ์ฝ”๋“œ๋Š” ๋ฌธ์ž์—ด ๊ฒฐํ•ฉ์„ ์ˆ˜ํ–‰ํ•˜๋Š” BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ, apply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๋ฌธ์ž์—ด์„ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ andThen ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€๋ฌธ์ž ๋ณ€ํ™˜ ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ , ์—ฐ๊ฒฐ๋œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด ๊ฒฐํ•ฉ๊ณผ ๋Œ€๋ฌธ์ž ๋ณ€ํ™˜์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
        // Map ์ƒ์„ฑ ๋ฐ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
        Map<String, Integer> map = new HashMap<>();
        map.put("A", 10);
        map.put("B", 20);
        map.put("C", 30);

        // BiFunction ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        BiFunction<Map<String, Integer>, String[], Integer> sumValues = (m, keys) -> {
            int sum = 0;
            for (String key : keys) {
                sum += m.getOrDefault(key, 0);
            }
            return sum;
        };

        // ๋‘ ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์˜ ํ•ฉ๊ณ„๋ฅผ ๋ฐ˜ํ™˜
        String[] keys = {"A", "B"};
        int result = sumValues.apply(map, keys);
        System.out.println("ํ‚ค A์™€ ํ‚ค B์˜ ๊ฐ’์˜ ํ•ฉ๊ณ„: " + result);
    }
}

์ถœ๋ ฅ ๊ฒฐ๊ณผ
ํ‚ค A์™€ ํ‚ค B์˜ ๊ฐ’์˜ ํ•ฉ๊ณ„: 30

์œ„ ์ฝ”๋“œ๋Š” Map์— ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•œ ํ›„, ๋‘ ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์˜ ํ•ฉ๊ณ„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. apply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Map๊ณผ ํ‚ค ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ฉด, ํ•จ์ˆ˜๋Š” ํ‚ค ๋ฐฐ์—ด์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’๋“ค์˜ ํ•ฉ๊ณ„๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
        // ๋‘ ๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ
        List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 3));
        List<Integer> list2 = new ArrayList<>(Arrays.asList(4, 5, 6));

        // BiFunction ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        BiFunction<List<Integer>, List<Integer>, List<Integer>> addLists = (l1, l2) -> {
            List<Integer> result = new ArrayList<>();
            int size = Math.min(l1.size(), l2.size());
            for (int i = 0; i < size; i++) {
                result.add(l1.get(i) + l2.get(i));
            }
            return result;
        };

        // ๋‘ ๋ฆฌ์ŠคํŠธ์—์„œ ๋™์ผํ•œ ์ธ๋ฑ์Šค์˜ ์š”์†Œ๋“ค์„ ๋”ํ•จ
        List<Integer> sumList = addLists.apply(list1, list2);
        System.out.println("๋‘ ๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ๋ณ„ ํ•ฉ๊ณ„: " + sumList);
    }
}

์ถœ๋ ฅ ๊ฒฐ๊ณผ
๋‘ ๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ๋ณ„ ํ•ฉ๊ณ„: [5, 7, 9]

์œ„ ์ฝ”๋“œ๋Š” ๋‘ ๊ฐœ์˜ ์ •์ˆ˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ ํ›„, ๋™์ผํ•œ ์ธ๋ฑ์Šค์˜ ์š”์†Œ๋“ค์„ ๋”ํ•˜๋Š” BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. apply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด, ํ•จ์ˆ˜๋Š” ๊ฐ ์ธ๋ฑ์Šค๋ณ„ ํ•ฉ๊ณ„๋ฅผ ๊ฐ€์ง„ ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ Java์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‹ค๋ฅธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์™€ ์กฐํ•ฉํ•˜์—ฌ ๋” ๋ณต์žกํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, BiFunction๊ณผ Function ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ž…๋ ฅ ๋ฐ ์ถœ๋ ฅ ์œ ํ˜•์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํŠน์ • ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import java.util.function.BiFunction;
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        // BiFunction ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        BiFunction<String, Integer, String> repeat = (str, count) -> {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < count; i++) {
                sb.append(str);
            }
            return sb.toString();
        };

        // Function ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        Function<String, Integer> countVowels = str -> {
            int count = 0;
            String vowels = "AEIOUaeiou";
            for (char c : str.toCharArray()) {
                if (vowels.indexOf(c) != -1) {
                    count++;
                }
            }
            return count;
        };

        // ๋ฌธ์ž์—ด ๋ฐ˜๋ณต ๋ฐ ๋ชจ์Œ ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ
        String repeatedStr = repeat.apply("Hello", 3);
        int vowelCount = countVowels.apply(repeatedStr);

        System.out.println("๋ฐ˜๋ณต๋œ ๋ฌธ์ž์—ด: " + repeatedStr);
        System.out.println("๋ชจ์Œ ๊ฐœ์ˆ˜: " + vowelCount);
    }
}

์ถœ๋ ฅ ๊ฒฐ๊ณผ
๋ฐ˜๋ณต๋œ ๋ฌธ์ž์—ด: HelloHelloHello
๋ชจ์Œ ๊ฐœ์ˆ˜: 6

์œ„ ์ฝ”๋“œ์—์„œ๋Š” repeat๋ผ๋Š” BiFunction ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ์ฃผ์–ด์ง„ ํšŸ์ˆ˜๋งŒํผ ๋ฐ˜๋ณตํ•˜๊ณ , countVowels๋ผ๋Š” Function ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฌธ์ž์—ด์—์„œ ๋ชจ์Œ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„, ๋‘ ํ•จ์ˆ˜ํ˜• ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฌธ์ž์—ด์—์„œ ๋ชจ์Œ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ตœ์ข…์ ์œผ๋กœ ๋‘ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ๋ฐ˜๋ณตํ•œ ํ›„ ๋ชจ์Œ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด์ฒ˜๋Ÿผ BiFunction์„ ๋‹ค๋ฅธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ์กฐํ•ฉํ•˜๊ณ , ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์—ฐ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ์ด์ ์„ ์ ๊ทน ํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ, ์œ ์ง€ ๊ด€๋ฆฌ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๊ธฐ์— ์ž˜ ์ˆ™์ง€ํ•ด์„œ ์‚ฌ์šฉํ–ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

๋Œ“๊ธ€