πŸ“‚ JAVA/μ£Όμš” κ°œλ…

λžŒλ‹€μ‹(Lambda Expression) - (1)

Amenable 2023. 1. 29. 10:58

 

  JDK1.8λΆ€ν„° λžŒλ‹€μ‹(Lambda Expression)을 μ‚¬μš©ν•  수 있게 λ˜μ—ˆλ‹€. 이것은 μžλ°”μ˜ 맀우 큰 λ³€ν™” 쀑에 ν•˜λ‚˜μ΄λ‹€. 이번 글을 톡해 'λžŒλ‹€μ‹μ˜ κ°œλ…', 'λžŒλ‹€μ‹ μž‘μ„±λ²•', 'ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€'λ₯Ό μ•Œμ•„λ³΄μž.

 

1. λžŒλ‹€μ‹(Lambda Expression) 🍣

    λžŒλ‹€μ‹(Lambda Expression)은 λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜μ˜ '식(expression)'으둜 ν‘œν˜„ν•œ 것이닀. 이λ₯Ό 톡해 μžλ°”λŠ” 객체지ν–₯언어인 λ™μ‹œμ— ν•¨μˆ˜ν˜• μ–Έμ–΄κ°€ λ˜μ—ˆλ‹€. μ•„λž˜λŠ” λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°κ³Ό μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ— λŒ€ν•œ κ°„λž΅ν•œ λ‚΄μš©μ΄λ‹€. 이λ₯Ό μ•Œκ³  λžŒλ‹€μ‹μ„ λ°°μš΄λ‹€λ©΄ λžŒλ‹€μ‹μ˜ λ‚΄μš©μ΄ 더 μ‰½κ²Œ λ‹€κ°€μ˜¬ 것이닀.

  • λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ° (⊃ 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°) : ν΄λž˜μŠ€μ—μ„œ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•˜κ³ , ν•„μš”ν•  λ•Œ κ·Έ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” λͺ…령을 ν•˜μ—¬ λ™μž‘ν•˜λŠ” 것
  • μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ° (⊃ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°) : 데이터가 μž…λ ₯으둜 μ£Όμ–΄μ§€κ³ , 데이터가 μ²˜λ¦¬λ˜λŠ” κ³Όμ •(흐름)을 μ •μ˜ν•˜λŠ” κ²ƒμœΌλ‘œ λ™μž‘ν•˜λŠ” 것.

  λžŒλ‹€μ‹μ€ 읡λͺ… ν•¨μˆ˜(anonymous function)라고도 ν•œλ‹€. 객체지ν–₯κ°œλ…μ—μ„œλŠ” ν•¨μˆ˜(function) λŒ€μ‹  κ°μ²΄μ˜ ν–‰μœ„λ‚˜ λ™μž‘을 μ˜λ―Έν•˜λŠ” λ©”μ„œλ“œ(method)λΌλŠ” μš©μ–΄λ₯Ό μ‚¬μš©ν•œλ‹€. λ©”μ„œλ“œλŠ” ν•¨μˆ˜μ™€ 같은 μ˜λ―Έμ΄μ§€λ§Œ, νŠΉμ • ν΄λž˜μŠ€μ— λ°˜λ“œμ‹œ 속해야 ν•œλ‹€λŠ” μ œμ•½μ΄ μžˆλ‹€. κ·Έλž˜μ„œ 객체지ν–₯μ—μ„œλŠ” 기쑴의 ν•¨μˆ˜μ™€ 같은 의미의 λ‹€λ₯Έ μš©μ–΄λ₯Ό μ„ νƒν•΄μ„œ μ‚¬μš©ν•œ 것이닀.
  ν•˜μ§€λ§Œ λžŒλ‹€μ‹μ„ μ΄μš©ν•œλ‹€λ©΄ λ©”μ„œλ“œλΌλŠ” 단어λ₯Ό μ“΄ λͺ©μ κ³Ό λ‹€λ₯΄κ²Œ ν•˜λ‚˜μ˜ 독립적인 κΈ°λŠ₯을 ν•˜κ²Œ λœλ‹€.(νŠΉμ • ν΄λž˜μŠ€μ— λ°˜λ“œμ‹œ 속할 ν•„μš”κ°€ μ—†λ‹€.) κ·Έλž˜μ„œ λžŒλ‹€μ‹μ„ 읡λͺ… λ©”μ„œλ“œκ°€ μ•„λ‹Œ 읡λͺ… ν•¨μˆ˜λΌκ³  λΆ€λ₯΄λŠ” 것이닀.

 

2. λžŒλ‹€μ‹ μž‘μ„±λ²• 🍜

  λ©”μ„œλ“œκ°€ μ•„λ‹Œ 읡λͺ… ν•¨μˆ˜μ΄λ―€λ‘œ λ©”μ„œλ“œμ—μ„œ 이름과 λ°˜ν™˜ νƒ€μž…μ„ μ œκ±°ν•˜μ—¬ μ‚¬μš©ν•œλ‹€. 그리고 λ§€κ°œλ³€μˆ˜ 선언뢀와 λͺΈν†΅{ } 사이에 '->'을 μΆ”κ°€ν•œλ‹€. 

// λ©”μ„œλ“œ
λ°˜ν™˜νƒ€μž… λ©”μ„œλ“œμ΄λ¦„ (λ§€κ°œλ³€μˆ˜ μ„ μ–Έ) {
 ...
}

// 읡λͺ… ν•¨μˆ˜ (λžŒλ‹€μ‹)
(λ§€κ°œλ³€μˆ˜ μ„ μ–Έ) -> {
 ...
}

  μœ„μ˜ 틀이 기본적인 것이고 μ•„λž˜μ˜ 5κ°€μ§€λ§Œ κΈ°μ–΅ν•œλ‹€λ©΄ μ†μ‰½κ²Œ λžŒλ‹€μ‹μ„ λ§Œλ“€ 수 μžˆλ‹€.

  1. λ°˜ν™˜κ°’μ΄ μžˆλŠ” λ©”μ„œλ“œμ˜ 경우, returnλ¬Έ λŒ€μ‹  '식(expression)'으둜 λŒ€μ‹ ν•  수 μžˆλ‹€. 식(expression)은 λ¬Έμž₯(statement)이 μ•„λ‹ˆλ―€λ‘œ 끝에 ';'을 μƒλž΅ν•  수 μžˆλ‹€.

// 식(expression) μ‚¬μš©X
(int a, int b) -> {return a > b ? a : b; }

// 식(expression) μ‚¬μš©O
(int a, int b) -> a > b ? a : b

  2. λžŒλ‹€μ‹μ— μ„ μ–Έλœ λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ€ 좔둠이 κ°€λŠ₯ν•œ κ²½μš°λŠ” μƒλž΅ν•  수 μžˆλ‹€. (λŒ€λΆ€λΆ„μ˜ κ²½μš°μ— μƒλž΅μ΄ κ°€λŠ₯ν•˜λ‹€.)

// μΆ”λ‘  κ°€λŠ₯ν•œ νƒ€μž… μƒλž΅ μ „
(int a, int b) -> a > b ? a : b

// μΆ”λ‘  κ°€λŠ₯ν•œ νƒ€μž… μƒλž΅ ν›„
(a, b) -> a > b ? a : b

  3. λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜λΏμΈ κ²½μ—λŠ” κ΄„ν˜Έ( )λ₯Ό μƒλž΅ν•  수 μžˆλ‹€. (λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ΄ 있으면 κ΄„ν˜Έ μƒλž΅ λΆˆκ°€λŠ₯)

// λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΈ 경우 κ΄„ν˜Έ μƒλž΅ μ „
(a) -> a * a

// λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΈ 경우 κ΄„ν˜Έ μƒλž΅ ν›„
a -> a * a

// λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ΄ 있으면 κ΄„ν˜Έ( ) μƒλž΅ λΆˆκ°€λŠ₯
(int a) -> a * a
int a -> a * a // Error

  4. κ΄„ν˜Έ{ } μ•ˆμ˜ λ¬Έμž₯이 ν•˜λ‚˜μΌ λ•ŒλŠ” κ΄„ν˜Έ{ }λ₯Ό μƒλž΅ν•  수 μžˆλ‹€. μ΄λ•Œ λ¬Έμž₯ 끝에 ';'λ₯Ό 뢙이지 말아야 ν•œλ‹€.

// κ΄„ν˜Έ{ }μ•ˆμ— λ¬Έμž₯이 ν•˜λ‚˜μΌ λ•Œ κ΄„ν˜Έ{ } μƒλž΅ μ „
(String name, int i) -> {
  System.out.println(name + "=" + i);
}

// κ΄„ν˜Έ{ }μ•ˆμ— λ¬Έμž₯이 ν•˜λ‚˜μΌ λ•Œ κ΄„ν˜Έ{ } μƒλž΅ ν›„
(String name, int i) ->
  System.out.println(name + "=" + i) // λ¬Έμž₯ 끝에 ';'λ₯Ό 뢙이지 μ•Šμ•„μ•Ό 함!

  5. κ΄„ν˜Έ { } μ•ˆμ˜ λ¬Έμž₯이 return문일 경우 κ΄„ν˜Έ { }λ₯Ό μƒλž΅ν•  수 μ—†λ‹€.

//  κ΄„ν˜Έ{ }μ•ˆμ˜ λ¬Έμž₯이 return문일 경우 κ΄„ν˜Έ{ }λ₯Ό μƒλž΅ν•  수 μ—†λ‹€!
(int a, int b) -> { return a > b ? a : b;} // OK
(int a, int b) -> return a > b ? a : b // Error

 

3. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(Functional Interface) 🍀

  Comparatorμ—μ„œ μ‚΄νŽ΄λ³Έ κ²ƒμ²˜λŸΌ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬ μ΅λͺ… ν΄λž˜μŠ€μ˜ κ°μ²΄λ₯Ό μƒμ„±ν•  μˆ˜ μžˆμ—ˆλ‹€.

Comparator<String> comparator = new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
};

  λžŒλ‹€μ‹λ„ μ‹€μ œλ‘œλŠ” μ΅λͺ… κ°μ²΄μ΄λ―€λ‘œ μœ„μ˜ μ½”λ“œλ₯Ό λžŒλ‹€μ‹μœΌλ‘œ λŒ€μ²΄ν•  μˆ˜ μžˆλ‹€.

Comparator<String> comparator1 = (String o1, String o2) -> o1.length() - o2.length();

  μœ„μ˜ 과정을 μ‚΄νŽ΄λ³΄λ©΄ ν•˜λ‚˜μ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λžŒλ‹€μ‹μœΌλ‘œ 닀루고 μžˆλ‹€. μ΄λŠ” μžλ°”μ˜ κ·œμΉ™μ„ μ–΄κΈ°μ§€ μ•ŠμœΌλ©΄μ„œλ„ μžμ—°μŠ€λŸ½λ‹€. κ·Έλž˜μ„œ μΈν„°νŽ˜μ΄μŠ€λ₯΄ ν†΅ν•΄ λžŒλ‹€μ‹μ„ λ‹€λ£¨κΈ°λ‘œ κ²°μ •ν•˜μ˜€κ³ , λžŒλ‹€μ‹μ„ λ‹€λ£¨κΈ° μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 'ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(functional interface)'라고 λΆ€λ₯΄κΈ°λ‘œ ν–ˆλ‹€. μ‚¬μš©λ°©λ²•μ€ μ•„λž˜μ™€ κ°™λ‹€.

  • μ»΄νŒŒμΌλŸ¬κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ •μ˜ν–ˆλŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•˜μ—¬ @FunctionalInterfaceλ₯Ό λΆ™μ—¬μ€€λ‹€.
  • 였직 ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ μ •μ˜ν•œλ‹€.
  • staticλ©”μ„œλ“œμ™€ defaultλ©”μ„œλ“œμ˜ κ°œμˆ˜μ—λŠ” μ œμ•½μ΄ μ—†λ‹€.
@FunctionalInterface
interface FunctionForLambda {
    public abstract int method();
}

  λ§€κ°œλ³€μˆ˜μ˜ κ°œμˆ˜μ™€ 리턴 νƒ€μž…μ— λ”°λΌμ„œ μ—¬λŸ¬ 개의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

// λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” 경우
@FunctionalInterface
interface FunctionForLambda1 {
    public abstract void method();
}

// λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΈ 경우
@FunctionalInterface
interface FunctionForLambda2 {
    public abstract void method(int a);
}

// λ§€κ°œλ³€μˆ˜κ°€ λ‘κ°œμΈ 경우
@FunctionalInterface
interface FunctionForLambda3 {
    public abstract void method(int a, int b);
}

// λ¦¬ν„΄νƒ€μž…μ΄ int인 경우
@FunctionalInterface
interface FunctionForLambda4 {
    public abstract int method();
}

// λ¦¬ν„΄νƒ€μž…μ΄ Boolean인 경우
@FunctionalInterface
interface FunctionForLambda5 {
    public abstract boolean method();
}

  5개만 μ μ—ˆμ§€λ§Œ μ‹€μ œλ‘œλŠ” 더 λ§Žμ€ 개수의 μΈν„°νŽ˜μ΄μŠ€κ°€ μ‘΄μž¬ν•  수 μžˆλ‹€. (λ§€κ°œλ³€μˆ˜λŠ” 0개, 1개, 2개 정도λ₯Ό 자주 μ‚¬μš©ν•˜λ―€λ‘œ) λ§Œμ•½ Genericsλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 자주 μ“°λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” λͺ‡ κ°œκ°€ λ˜μ§€ μ•Šμ„ 것이닀. κ·Έλž˜μ„œ 자주 μ“°μ΄λŠ” ν˜•μ‹μ˜ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό java.util.functionνŒ¨ν‚€μ§€μ— 이미 μ •μ˜ν•΄ λ†“μ•˜λ‹€. μ΄λŠ” λ‹€μŒ κΈ€μ—μ„œ μžμ„Ένžˆ μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

  

  λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ„ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ μ§€μ •ν•  수 μžˆλ‹€. λ³€μˆ˜μ²˜λŸΌ λ©”μ„œλ“œλ₯Ό μ£Όκ³ λ°›λŠ”λ‹€κ³  λ³Ό μˆ˜λ„ 있긴 ν•œλ°, μ •ν™•νžˆλŠ” λ©”μ„œλ“œκ°€ μ•„λ‹ˆλΌ 객체λ₯Ό μ£Όκ³ λ°›λŠ” 것이닀. (λ‹Ήμ—°ν•˜κ²Œ ν•  수 μžˆλŠ” 것이닀.)

void method (MyFunction f) {
    f.FunctionalInterfaceMethod();
}

MyFunction f = () -> System.out.println("MyFunction f");
method(f);

 

ν•΄λ‹Ή 글은 남ꢁ μ„±λ‹˜μ˜ Java의 정석을 읽고 μž‘μ„±ν•œ κ²ƒμž…λ‹ˆλ‹€.