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

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ & ๋žŒ๋‹ค

by MuGeon Kim 2023. 1. 28.
๋ฐ˜์‘ํ˜•

๐Ÿ˜ถ‍๐ŸŒซ๏ธํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ


Java๋Š” ๊ฐ์ฒด์ง€ํ–ฅ ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ํ•˜์ง€๋งŒ JDK8๋ถ€ํ„ฐ Stream API์™€ ๋žŒ๋‹ค์‹, ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ๋“ฑ์„ ์ง€์›ํ•˜๋ฉด์„œ Java๋ฅผ ์ด์šฉํ•ด ํ•จ์ˆ˜ํ˜•์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•  ์ˆ˜ ์žˆ๋Š” API ๋“ค์„ ์ œ๊ณตํ•ด์ฃผ๊ณ  ์žˆ๋‹ค.

First Class Citizon

  • First Class Citizon ์€ ์•„๋ž˜์˜ ์†์„ฑ๋“ค์„ ๋ชจ์ฃผ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

• ๋ณ€์ˆ˜์— ๊ฐ’์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

• ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

• ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์ด ๋  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html

 

Function (Java Platform SE 8 )

 

docs.oracle.com

@FunctionalInterface


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

  • ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋”ฑ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์ด๋‹ค.
๐Ÿ’ก public abstract๊ฐ€ ๋‹จ ํ•˜๋‚˜๋งŒ ์žˆ์œผ๋ฉด ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ์ •์˜๊ฐ€ ๋˜์–ด์ ธ ์žˆ๋Š” ๊ฒƒ์€ ์ƒ๊ด€์ด ์—†๋‹ค.
@FunctionalInterface
public interface PracticeLambda {
    void practice(); //public abstract ์ƒ๋žต

    static void practice2() {
        System.out.println("์—ฐ์Šต1");
    }

    default void practice3() {
        System.out.println("์—ฐ์Šต2");
    }
}

๋งŒ์•ฝ์— ์ถ”์ƒ ๋ฉ”์†Œ๋“œ๊ฐ€ 2๊ฐœ ์ด์ƒ์ด๋ฉด @functionalInterface์—์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์˜จ๋‹ค.

์ž๋ฐ”์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

  • Function<T,R> , UnaryOperator<T>
    • ๋‘๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›์•„์„œ ํ•˜๋‚˜์˜ ๊ฒฐ๊ณผ๋ฅผ Returnํ•œ๋‹ค.
    • ์—ฌ๊ธฐ์„œ ๋‘๊ฐœ์˜ ์ธ์ž์˜ ํƒ€์ž…์€ T,R ์„œ๋กœ ๋‹ค๋ฅด๊ฑฐ๋‚˜ ๊ฐ™์•„๋„ ์ƒ๊ด€์ด ์—†๋‹ค.
    • ๋งŒ์•ฝ์— ๋‘๊ฐœ์˜ ์ธ์ž๊ฐ€ ๊ฐ™์€ ํƒ€์ž…์ด๋ฉด UnaryOperator<T>๋ฅผ ์‚ฌ์šฉ

๐Ÿฆ–ํ˜„์žฌ์˜ ์ด ์ฝ”๋“œ๋Š” Function ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ต๋ช…๊ฐ์ฒด ์Šคํƒ€์ผ๋กœ ๊ตฌํ˜„์„ ํ–ˆ๋‹ค.

public class PracticeLamdba {
    public static void main(String[] args) {
        Function<Integer, Integer> pricaticeTest = new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer+10;
            }
        };
        
        System.out.println(pricaticeTest.apply(3));
    }
}
  • ๊ฐ’์„ ๋ฐ›์•„์™€์„œ apply๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•ด์„œ +10์„ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

๐Ÿฆ–์ด๋Ÿฌํ•œ ์ต๋ช…์˜ ๋Š๋‚Œ์„ ๋žŒ๋‹ค๋กœ ํ‘œํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

public class PracticeLamdba {
    public static void main(String[] args) {
        Function<Integer, Integer> pricaticeTest = integer -> integer+10;
        System.out.println(pricaticeTest.apply(3));
    }
}
  • ์ฝ”๋“œ๊ฐ€ ์—„์ฒญ ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ€๋…์„ฑ์ด ๋†’์•„์กŒ๋‹ค.

Function<T,R> → apply()

→T๋Š” ์ž…๋ ฅํ•˜๋Š” ํƒ€์ž…์„ ์˜๋ฏธํ•˜๋ฉฐ R์€ return ๋˜๋Š” ๊ฐ’์˜ ํƒ€์ž…์„ ์˜๋ฏธํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ๋งŒ์•ฝ์— Funciotn ํ•จ์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ์žˆ์„ ๋•Œ Function์˜ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„

์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. compose
  • ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์„ค๋ช…์„ ํ•˜๊ฒ ๋‹ค.
public class PracticeLamdba {
    public static void main(String[] args) {
        Function<Integer, Integer> plus = (number) -> number+10;
        
        Function<Integer , Integer> multiple = number2 ->number2*2;
        
        int result=plus.compose(multiple).apply(10);
				System.out.println(result);
        
    }
}
  • ๋”ํ•˜๊ธฐ ๊ธฐ๋Šฅ๊ณผ ๊ณฑํ•˜๊ธฐ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์—ˆ๊ณ  copose๋ฅผ ์‚ฌ์šฉ์„ ํ–ˆ๋‹ค.

์ด๋•Œ result์˜ ๊ฐ’์€ ์–ด๋–ป๊ฒŒ ๋‚˜์˜ฌ๊นŒ? —> ๊ฒฐ๊ณผ๋Š” 30์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

Compose๋ž€

()์˜ ๊ธฐ๋Šฅ์„ ๋จผ์ € ์—ฐ์‚ฐ์„ ํ•˜๊ณ  ๊ทธ ๋’ค์— ์ฒซ๋ฒˆ ์งธ๋กœ ์˜ค๋Š” ๊ธฐ๋Šฅ์„ ์—ฐ์‚ฐ์„ ํ•œ๋‹ค.

multiple → ๊ฒฐ๊ณผ → ๊ฒฐ๊ณผ & plus ๋ผ๊ณ  ์ƒ๊ฐ์„ ํ•˜๋ฉด ์ข‹๋‹ค.

andThen๋ž€

public class PracticeLamdba {
    public static void main(String[] args) {
        Function<Integer, Integer> plus = (number) -> number+10;
        Function<Integer , Integer> multiple = number2 ->number2*2;
        int result=plus.andThen(multiple).apply(10);
        System.out.println(result);
    }
}

andThen์€ compose์™€ ๋ฐ˜๋Œ€๋กœ ๋จผ์ €์˜ค๋Š” ๊ธฐ๋Šฅ์„ ์—ฐ์‚ฐํ•˜๊ณ  ๊ทธ ๋’ค์— () ๊ธฐ๋Šฅ์„ ์—ฐ์‚ฐ์„ ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

์ฆ‰. plus → ๊ฒฐ๊ณผ → multiple์„ ํ•˜๋ฉฐ ๊ฒฐ๊ณผ๋Š” 40์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

  • BiFuntion<T,U,R>
    • BiFunction์€ ์ž…๋ ฅ๊ฐ’์ด 2๊ฐœ๋ฅผ ๋ฐ›๊ณ  ๋‘๊ฐœ์˜ ์—ฐ์‚ฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๊ฐ’ R๋กœ
    • ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„๋‹ค.
    • ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์€ Function<T,R>๊ณผ ๋น„์Šทํ•˜๋ฉฐ ์ž…๋ ฅ๊ฐ’์ด 2๊ฐœ๋ผ๋Š” ์ฐจ์ด๋งŒ ์žˆ๋‹ค.

 

์ต๋ช…

public class PracticeLamdba {
    public static void main(String[] args) {
        BiFunction<Integer,Integer,Integer>biFunction = new BiFunction<Integer, Integer, Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer+integer2;
            }
        };
        int result=biFunction.apply(10 , 20);
        System.out.println(result);
    }
}

๋žŒ๋‹ค

public class PracticeLamdba {
    public static void main(String[] args) {
        BiFunction<Integer,Integer,Integer>biFunction = (integer, integer2) -> integer+integer2;
        int result=biFunction.apply(10 , 20);
        System.out.println(result);
    }
}

 

 

 

Function<T,R> & BiFunction<T,U,R> ๊ฐ™์€ ํƒ€์ž…

<aside> ๐Ÿ’ก ๋งŒ์•ฝ์— T ,U ,R์ด ๋‹ค ๋˜‘๊ฐ™์€ Integer ํƒ€์ž…์ด๋ฉด ๋‹ค ์ ์–ด์•ผ ๋˜๋Š”๊ฐ€?

</aside>

๋งŒ์•ฝ์— ํƒ€์ž…์ด ๊ฐ™์œผ๋ฉด Function์€ UnaryOperator<T>๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ž…๋ ฅ , ์ถœ๋ ฅ๊ฐ’์˜ ํƒ€์ž…์ด ๋ชจ๋‘ T๋กœ ์ •ํ•ด์ง„๋‹ค.

BiFunction<T,U,R>์€ ์ž…๋ ฅ ์ถœ๋ ฅ ๋ชจ๋‘ ๊ฐ™์œผ๋ฉด BinaryOperator<T>๋ฅผ ์‚ฌ์šฉ

public class PracticeLamdba {
    public static void main(String[] args) {
        UnaryOperator<Integer>unaryOperator = (n) -> n+10;
        System.out.println(unaryOperator.apply(10));

        BinaryOperator<Integer>binaryOperator=(a,b)->a+10+b;
        System.out.println(binaryOperator.apply(10,20));
    }
}
  • Consumer<T> - apply()

Tํƒ€์ž…์„ ์ž…๋ ฅ ๋ฐ›์•„์„œ ์•„๋ฌด๊ฐ’๋„ ๋ฆฌํ„ดํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์˜๋ฏธ

์ต๋ช…

public class PracticeLamdba {
    public static void main(String[] args) {
        Consumer<String>consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("๋‚ด ์ด๋ฆ„์€ "+s +"์ž…๋‹ˆ๋‹ค.");
            }
        };
        consumer.accept("๊น€๋ฌด๊ฑด");
    }
}

๋žŒ๋‹ค

public class PracticeLamdba {
    public static void main(String[] args) {
        Consumer<String>consumer = (name) -> System.out.println("๋‚ด ์ด๋ฆ„์€"+name+"์ž…๋‹ˆ๋‹ค.");
        consumer.accept("๊น€๋ฌด๊ฑด");
    }
}
  • Suppiler<T>
    • T ํƒ€์ž…์˜ ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜ ์ธํ„ฐํŽ˜์ด์Šค
      • ์ธ์ž๊ฐ€ ํ•„์š” ์—†๋‹ค.
      • ๋‚ด๊ฐ€ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์„์ง€ ๊ฒฐ์ •
      • T get()

์ต๋ช…

public class PracticeLamdba {
    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "๊น€๋ฌด๊ฑด";
            }
        };
        System.out.println("๋‚ด ์ด๋ฆ„์€ "+supplier.get());
    }
}

๋žŒ๋‹ค

public class PracticeLamdba {
    public static void main(String[] args) {
        Supplier<String> supplier = () -> "๊น€๋ฌด๊ฑด";
        System.out.println("๋‚ด ์ด๋ฆ„์€ "+supplier.get());
    }
}
  • Predicate<T>
    • Tํƒ€์ž…์„ ๋ฐ›์•„์„œ Boolean์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜ ์ธํ„ฐํŽ˜์ด์Šค
    • ํ•จ์ˆ˜ ์กฐํ•ฉ์šฉ ๋ฉ”์†Œ๋“œ
      • and
      • or
      • negate()

์ต๋ช…

public class PracticeLamdba {
    public static void main(String[] args) {
      Predicate<Integer>predicate = new Predicate<Integer>() {
          @Override
          public boolean test(Integer integer) {
              return integer%2==0;
          }
      };
        System.out.println(predicate.test(10));
    }
}

๋žŒ๋‹ค

public class PracticeLamdba {
    public static void main(String[] args) {
      Predicate<Integer>predicate = integer -> integer%2==0;
        System.out.println(predicate.test(10));
    }
}

๋งŒ์•ฝ์— ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด and or๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ ์ง์ˆ˜์ด๋ฉด์„œ ๊ฐ’์ด 4์ธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๊ณ  ์‹ถ๋‹ค๊ณ  ์กฐ๊ฑด์„ ๋งŒ๋“ค๋ฉด

  1. ์ง์ˆ˜
  2. ๊ฐ’์ด 4

์ด ๋‘๊ฐœ์˜ ์กฐ๊ฑด์„ and์—ฐ์‚ฐ์„ ํ•˜๋ฉด ๋˜๋Š”๋ฐ

and

public class PracticeLamdba {
    public static void main(String[] args) {
      Predicate<Integer>integerPredicate = integer -> integer%2==0;
      Predicate<Integer>predicate = num ->num==4;
      
      if(integerPredicate.and(predicate).test(4)){
          System.out.println("์ฐธ");
      }else System.out.println("๊ฑฐ์ง“");
      
    }
}

or

public class PracticeLamdba {
    public static void main(String[] args) {
      Predicate<Integer>integerPredicate = integer -> integer%2==0;
      Predicate<Integer>predicate = num ->num==4;
      
      if(integerPredicate.or(predicate).test(4)){
          System.out.println("์ฐธ");
      }else System.out.println("๊ฑฐ์ง“");
      
    }
}

negate()

public class PracticeLamdba {
    public static void main(String[] args) {
      Predicate<Integer>integerPredicate = integer -> integer%2==0;
      Predicate<Integer>predicate = num ->num==4;
        System.out.println(predicate.negate().test(4));
    }
}
๋ฐ˜์‘ํ˜•

'๐ŸŒพBackEnd > ๐Ÿ› Java' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

๋žŒ๋‹ค์‹ ๋กœ์ปฌ ๋ณ€์ˆ˜ - Effectively Final  (0) 2023.01.28