Coding Planet
λλ€μ(Lamda expression) μ΄μ 리μ νμ©μμ λ³Έλ¬Έ
λλ€μ(Lamda expression) μ΄μ 리μ νμ©μμ
jhj.sharon 2024. 3. 4. 12:30μλ ν¬μ€νΈμ μμ λ° λ΄μ©μ λ¨κΆμ± μ μμ μλ°μ μ μμ λ§μ΄ μ°Έκ³ νλ€.
| λλ€μμ΄λ
λλ€μμ κ°λν λ§ν΄μ λ©μλλ₯Ό νλμ 'μ(expression)'μΌλ‘ ννν κ²μ΄λ€. μλ° 8λΆν° λ±μ₯ν κ°λ μΌλ‘ κ°μ²΄μ§ν₯μΈμ΄μΈ μλ°μ ν¨μν νμ©μ λν΄μ£Όμλ€. λλ€μμ λ©μλμ 맀κ°λ³μλ‘ μ λ¬λμ΄μ§λ κ²μ΄ κ°λ₯νκ³ , λ©μλμ κ²°κ³Όλ‘ λ°νλ μλ μλ€. λλ€μμΌλ‘ μΈν΄ λ©μλλ₯Ό λ³μμ²λΌ λ€λ£¨λ κ²μ΄ κ°λ₯ν΄μ§ κ²μ΄λ€.
λ©μλλ₯Ό λλ€μμΌλ‘ νννλ©΄ λ©μλμ μ΄λ¦κ³Ό λ°νκ°μ΄ μμ΄μ§λ―λ‘ λλ€μμ 'μ΅λͺ ν¨μ'λΌκ³ νκΈ°λ νλ€.
μλ μμμ (i) -> (int)(Math.random()*5+1) λΆλΆμ΄ λλ€μμ΄λ€.
int[] arr = new int[5];
Arrays.setAll(arr, (i) -> (int)(Math.random()*5+1));
| λλ€μ μμ±λ²
λλ€μμ κΈ°λ³Ένν λ©μλμμ μ΄λ¦κ³Ό λ°ννμμ μ κ±°νκ³ λ§€κ°λ³μ μ μΈλΆμ λͺΈν΅{} μ¬μ΄μ -> λ₯Ό μΆκ°νλ€.
//μΌλ°ν
λ°ννμ
λ©μλμ΄λ¦(맀κ°λ³μ μ μΈ){
λ¬Έμ₯λ€
}
//λλ€μ
(맀κ°λ³μ μ μΈ) -> {
λ¬Έμ₯λ€
}
λλ€μ μμ±μ κΈ°λ³Έ κ·μΉμ λ€μκ³Ό κ°λ€.
- κΈ°λ³Έ ꡬ쑰: (맀κ°λ³μ λͺ©λ‘) -> { μ€νλ¬Έ; }
- 맀κ°λ³μ λͺ©λ‘: λλ€μμ΄ λ°μλ€μ΄λ 맀κ°λ³μλ€μ κ΄νΈ μμ μ μνλ€. 맀κ°λ³μμ νμ
μ μλ΅ κ°λ₯νλ©°, μ»΄νμΌλ¬κ° λ¬Έλ§₯μ ν΅ν΄ μ μΆνλ€.
- λ€λ§ (int a, int b) νΉμ ( a, b) λ‘ μλ΅κ°λ₯ν λΆ (int a, b) μ²λΌ μ¬λ¬ 맀κ°λ³μ μ€ μ΄λ νλμ νμ λ§ μλ΅ν μλ μλ€.
- νμ΄ν(->): 맀κ°λ³μμ λλ€μμ λͺΈμ²΄λ₯Ό ꡬλΆνλ€.
- μ€νλ¬Έ: μ€μ λλ€μμ΄ μνν μ½λ λΈλ‘. 맀κ°λ³μλ₯Ό μ΄μ©ν μ°μ°μ΄λ λ©μλ νΈμΆ λ±μ΄ ν¬ν¨λ μ μλ€.
- 맀κ°λ³μ λͺ©λ‘: λλ€μμ΄ λ°μλ€μ΄λ 맀κ°λ³μλ€μ κ΄νΈ μμ μ μνλ€. 맀κ°λ³μμ νμ
μ μλ΅ κ°λ₯νλ©°, μ»΄νμΌλ¬κ° λ¬Έλ§₯μ ν΅ν΄ μ μΆνλ€.
- 맀κ°λ³μ
- 맀κ°λ³μκ° νλμΈ κ²½μ°, 맀κ°λ³μλ₯Ό κ°μΈλ κ΄νΈλ₯Ό μλ΅ν μ μλ€. λ¨, νμ
μ λͺ
μνλ κ²½μ°λ κ΄νΈλ₯Ό μλ΅ν μ μλ€.
- κ΄νΈ μλ΅ : a -> a * a
- νμ μ λͺ μν κ²½μ° (int a) -> a * a
- 맀κ°λ³μκ° μλ κ²½μ°, λΉ κ΄νΈλ₯Ό μ¬μ©νλ€(μ: () -> System.out.println("Hello")).
- 맀κ°λ³μκ° νλμΈ κ²½μ°, 맀κ°λ³μλ₯Ό κ°μΈλ κ΄νΈλ₯Ό μλ΅ν μ μλ€. λ¨, νμ
μ λͺ
μνλ κ²½μ°λ κ΄νΈλ₯Ό μλ΅ν μ μλ€.
- μ€νλ¬Έ
- μ€νλ¬Έμ΄ λ¨μΌ λ¬Έμ₯μΈ κ²½μ°, μ€κ΄νΈ {}λ₯Ό μλ΅ν μ μλ€. κ·Έ λ¬Έμ₯μ΄ κ°μ λ°ννλ κ²½μ°, return ν€μλλ μλ΅ν μ μλ€
- λλ€ ννμ: λ μμ ν©μ λ°ν (μ€κ΄νΈ μλ΅)
(a, b) -> a + b
- λλ€ ννμ: λ μμ ν©μ λ°ν (μ€κ΄νΈ μλ΅)
- μ€νλ¬Έμ΄ μ¬λ¬ λ¬Έμ₯μΌλ‘ ꡬμ±λ κ²½μ°, μ€κ΄νΈ {}λ‘ κ°μΈμΌ νλ©°, λ°ν κ°μ΄ μλ κ²½μ° return ν€μλλ₯Ό λͺ
μν΄μΌ νλ€
- λλ€ ννμ: λ μμ ν©μ κ³μ° ν λ°ν(μ¬λ¬μ€ μΌ κ²½μ° μ€κ΄νΈ μλ΅ λΆκ°)
(a, b) -> {
int sum = a + b; // 첫 λ²μ§Έ λ¬Έμ₯: ν©κ³ κ³μ°
return sum; // λ λ²μ§Έ λ¬Έμ₯: κ³μ°λ ν©κ³ λ°ν
}
- λλ€ ννμ: λ μμ ν©μ κ³μ° ν λ°ν(μ¬λ¬μ€ μΌ κ²½μ° μ€κ΄νΈ μλ΅ λΆκ°)
- μ€νλ¬Έμ΄ λ¨μΌ λ¬Έμ₯μΈ κ²½μ°, μ€κ΄νΈ {}λ₯Ό μλ΅ν μ μλ€. κ·Έ λ¬Έμ₯μ΄ κ°μ λ°ννλ κ²½μ°, return ν€μλλ μλ΅ν μ μλ€
- λ°νκ°
- λλ€μμμ κ°μ λ°νν΄μΌ νλ κ²½μ°, return λ¬Έμ μ¬μ©νλ€. λ¨μΌ μ€νλ¬Έλ§ μλ κ²½μ° returnκ³Ό μ€κ΄νΈ {}λ₯Ό μλ΅ν μ μλ€.
- νμ
μΆλ‘
- λλ€μμ 맀κ°λ³μ νμ μ μλ΅ κ°λ₯νλ€. μ»΄νμΌλ¬κ° 맀κ°λ³μμ νμ μ λ¬Έλ§₯μ μ μΆν μ μκΈ° λλ¬Έμ΄λ€.
- ν¨μν μΈν°νμ΄μ€
- λλ€μμ ν¨μν μΈν°νμ΄μ€μ ꡬνμ²΄λ‘ μ¬μ©λλ€. ν¨μν μΈν°νμ΄μ€λ μ€μ§ νλμ μΆμ λ©μλλ₯Ό κ°μ§ μΈν°νμ΄μ€λ₯Ό λ§νλ€. @FunctionalInterface μ΄λ Έν μ΄μ μ μ¬μ©νμ¬ ν¨μν μΈν°νμ΄μ€μμ λͺ μν μ μλ€.
- ν¨μν μΈν°νμ΄μ€ : Runnable, Predict, Consumer, Supplier λ±
| ν¨μν μΈν°νμ΄μ€(Functional Interface)
ν¨μν μΈν°νμ΄μ€(Functional Interface)λ μ€μ§ νλμ μΆμ λ©μλλ₯Ό κ°μ§ μΈν°νμ΄μ€λ₯Ό λ§νλ€. μλ° 8λΆν° ν¨μν νλ‘κ·Έλλ°μ μ§μνκΈ° μν΄ λμ λμμΌλ©°, λλ€ ννμ(Lambda Expression)μ μ¬μ©νμ¬ μ΄λ¬ν μΈν°νμ΄μ€μ ꡬν체λ₯Ό κ°λ¨νκ³ λͺ λ£νκ² μ 곡ν μ μλ€.
μμΉμ μΌλ‘ μλ°μμ λͺ¨λ λ©μλλ ν΄λμ€ λ΄μ ν¬ν¨λμ΄μΌ νλ€. κ·Έλ λ€λ©΄ λλ€μμ μ΄λ€ ν΄λμ€μ ν¬ν¨λλ κ²μΌκΉ? λλ€μμ΄ νλμ λ©μλλ‘ μΈμλκΈ° μ½μ§λ§ μ¬μ€ λλ€μμ μ΅λͺ ν΄λμ€μ κ°μ²΄μ λλ±νλ€.
μλ°μμ λͺ¨λ λ©μλλ ν΄λμ€μ μΌλΆλ‘ μ‘΄μ¬ν΄μΌ νκΈ° λλ¬Έμ νλ©΄μ μΌλ‘λ ν΄λμ€ μμ΄ λ 립μ μΌλ‘ μ‘΄μ¬νλ κ²μ²λΌ 보μ΄λ λλ€ ννμλ λ΄λΆμ μΌλ‘λ μ΄λ€ ν΄λμ€μ μνλ ννλ‘ λ³νλμ΄ μ²λ¦¬λλ κ²μ΄λ€.
λλ€ ννμμ μ΅λͺ ν΄λμ€μ κ°μ²΄λ₯Ό μμ±νλ κ²κ³Ό μ μ¬ν λ°©μμΌλ‘ μλνλ€. μ΅λͺ ν΄λμ€λ μ΄λ¦μ΄ μλ ν΄λμ€λ‘, μ£Όλ‘ μΌνμ±μΌλ‘ μ¬μ©λλ κ°μ²΄λ₯Ό μμ±ν λ μ¬μ©λλ€.
μλ° μ»΄νμΌλ¬λ λλ€ ννμμ ν¨μν μΈν°νμ΄μ€μ μ΅λͺ ꡬνμ²΄λ‘ λ³ννλ€. μ¦, λλ€ ννμμ μ€ν μμ μμ μ΅λͺ ν΄λμ€μ μΈμ€ν΄μ€λ‘ ννλλ©°, μ΄ μΈμ€ν΄μ€λ ν¨μν μΈν°νμ΄μ€μ λ¨ νλμ μΆμ λ©μλλ₯Ό ꡬνν κ²μΌλ‘ μ²λ¦¬λλ€.
μλ μμμ λλ€ ννμμ Runnable μΈν°νμ΄μ€μ run λ©μλλ₯Ό ꡬννλ μ΅λͺ ν΄λμ€μ κ°μ²΄λ₯Ό μμ±νλ κ²κ³Ό λλ±ν μμ μ μννλ€. μ»΄νμΌλ¬λ μ΄ λλ€ ννμμ μ΅λͺ ν΄λμ€μ μΈμ€ν΄μ€ μμ± μ½λλ‘ λ³ννλ κ²μ΄λ€.
// λλ€μ
Runnable r = () -> System.out.println("Hello, world!");
// μ΅λͺ
ν΄λμ€μ μΈμ€ν΄μ€ μμ± μ½λ
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello, world!");
}
};
μ μμμμ λ³Έ κ² μ²λΌ νλμ λ©μλκ° μ μΈλ μΈν°νμ΄μ€λ₯Ό μ μν΄μ λλ€μμ λ€λ£¨λ κ²μ κΈ°μ‘΄μ μλ°μ κ·μΉμ μ΄κΈ°μ§ μν₯λ©΄μλ μμ°μ€λ½λ€. κ·Έλμ μΈν°νμ΄μ€λ₯Ό ν΅ν΄ λλ€μμ λ€λ£¨κΈ°λ‘ κ²°μ λμμΌλ©°, λλ€μμ λ€λ£¨κΈ° μν μΈν°νμ΄μ€λ₯Ό 'ν¨μν μΈν°νμ΄μ€(Funcational interface)'λΌκ³ λΆλ₯΄κΈ°λ‘ νλ€.
λ¨, ν¨μν μΈν°νμ΄μ€μλ μ€μ§ νλμ μΆμ λ©μλλ§ μ μλμ΄μΌ νλ€. κ·ΈλμΌ λλ€μκ³Ό μΈν°νμ΄μ€μ λ©μλκ° 1:1 맀μΉμ΄ λκΈ° λλ¬Έμ΄λ€. λ°λ©΄ static λ©μλμ default λ©μλμ΄ κ°μμλ μ μ½μ΄ μλ€.
1) ν¨μν μΈν°νμ΄μ€ μμ
- @FuntionalInterfaceλ₯Ό λΆμ΄λ©΄ μ»΄νμΌλ¬κ° ν¨μν μΈν°νμ΄μ€λ₯Ό μ¬λ°λ₯΄κ² μ μνμλμ§ νμΈν΄μ£Όλ―λ‘, κΌ λΆμ΄λλ‘ νμ
@FunctionalInterface
public interface MyFunctionalInterface {
// νλμ μΆμ λ©μλλ§ μ μ
void abstractMethod();
// default λ©μλλ μ¬λ¬ κ° μ μν μ μμ
default void defaultMethod1() {
System.out.println("Default method 1");
}
default void defaultMethod2() {
System.out.println("Default method 2");
}
// static λ©μλλ μ¬λ¬ κ° μ μν μ μμ
static void staticMethod1() {
System.out.println("Static method 1");
}
static void staticMethod2() {
System.out.println("Static method 2");
}
}
2) ν¨μν μΈν°νμ΄μ€μ 맀κ°λ³μν λ°ννμ μμ
- λλ€μμ μ°Έμ‘°λ³μλ‘ λ€λ£ΈμΌλ‘μ¨ λ©μλλ₯Ό ν΅ν΄ λλ€μμ μ£Όκ³ λ°μ μ μκ²λ€. μ¦, λ³μμ²λΌ λ©μλλ₯Ό μ£Όκ³ λ°λ κ²μ΄ κ°λ₯ν΄μ§ κ²μ΄λ€.
@FunctionalInterface
interface MyFunction{
void run(); // public void abstract run();
}
public class LamdaEx1 {
static void execute(MyFunction f){ //맀κ°λ³μ νμ
μ΄ MyFunctionμΈ λ©μλ
f.run();
}
static MyFunction getMyFunction(){ // λ°ννμ
μ΄ MyFunctionμΈ λ©μλ
MyFunction f = () -> System.out.println("f3.run()");
return f;
}
public static void main (String[] args){
//λλ€μμΌλ‘ MyFuntionμ run()μ ꡬν
MyFunction f1 = () -> System.out.println("f1.run()");
MyFunction f2 = new MyFunction(){ //μ΅λͺ
ν΄λμ€λ‘ run()μ ꡬν
public void run(){ // public λ°λμ λΆμ¬μΌν¨
System.out.println("f2.run()");
}
};
MyFunction f3 = getMyFunction();
f1.run();
f2.run();
f3.run();
execute(f1);
execute( () -> System.out.println("run()"));
}
}
| λλ€μμ νμ κ³Ό νλ³ν
ν¨μν μΈν°νμ΄μ€λ‘ λλ€μμ μ°Έμ‘°ν μ μλ κ²μΌ λΏ, λλ€μμ νμ μ΄ ν¨μν μΈν°νμ΄μ€μ νμ κ³Ό μΌμΉνλ κ²μ μλλ€. λλ€μμ μ΅λͺ κ°μ²΄μ΄κ³ μ΅λͺ κ°μ²΄λ νμ μ΄ μλ€. μ ννλ νμ μ μμ§λ§ μ»΄νμΌλ¬κ° μμλ‘ μ΄λ¦μ μ νκΈ° λλ¬Έμ μ μ μλ€(μ μ μ€λͺ ν κ² μ²λΌ μλ° μ»΄νμΌλ¬λ λλ€ ννμμ ν¨μν μΈν°νμ΄μ€μ μ΅λͺ ꡬνμ²΄λ‘ λ³ννλ€).
κ·Έλμ λμ μ°μ°μμ μλ²μ νμ μ μΌμΉμν€κΈ° μν΄ νλ³νμ΄ νμνλ€. λ€λ§ μ΄ νλ³νμ κ²½μ° λλΆλΆ μλ΅κ°λ₯νλ€.
λλ€μμ MyFunction μΈν°νμ΄μ€λ₯Ό μ§μ ꡬννμ§ μμμ§λ§, μ΄ μΈν°νμ΄μ€λ₯Ό ꡬνν ν΄λμ€μ κ°μ±μ μμ ν λμΌνκΈ° λλ¬Έμ μλμ κ°μ νλ³νμ νμ©νλ€.
MyFunction f = (MyFunction)((0 -> {}); // μλ³μ νμ
μ΄ λ€λ₯΄λ―λ‘ νλ³νμ΄ νμ
λ€λ§, λλ€μμ μ΄λ¦μ΄ μμ λΏ λΆλͺ ν κ°μ²΄μΈλ°λ, μλμ κ°μ΄ Object νμ μΌλ‘ νλ³ν ν μ μλ€. λλ€μμ μ€μ§ ν¨μν μΈν°νμ΄μ€λ‘λ§ νλ³νμ΄ κ°λ₯νλ€. λλ€ ννμμ Object νμ μ΄λ ꡬ체μ μΈ ν΄λμ€ νμ μΌλ‘ μ§μ νλ³ν ν μ μλ€.
μ΄ μ μ½μ λλ€ ννμμ΄ κ΅¬ννλ κ²μ΄ μΈν°νμ΄μ€μ κ·Έ νλμ μΆμ λ©μλμμ λͺ νν νκΈ° μν¨μ΄λ€. Objectλ νλμ ν΄λμ€μ΄λ―λ‘ ν¨μν μΈν°νμ΄μ€λ₯Ό ꡬνν κ°μ²΄μΈ λλ€κ° νμΌμΌλ‘ μΌμ μ μλ κ²μ΄λ€. λν, Object νμ μ μ΄λ€ λ©μλλ μΆμ λ©μλλ‘ κ°μ§κ³ μμ§ μκΈ° λλ¬Έμ, λλ€ ννμμ νκ²μ΄ λ μ μλ€.
λ§μΌ, κ΅³μ΄ λλ€μμ Object κ°μ²΄λ‘ νλ³ν νκ³ μΆλ€λ©΄ ν¨μν μΈν°νμ΄μ€ νμ μΌλ‘ λ³ν μν¨ μ Object νμ μΌλ‘ νλ³ν ν΄μΌνλ€.
1. λλ€ ννμμ ν¨μν μΈν°νμ΄μ€ νμ μΌλ‘ λ³ν
λ¨Όμ , λλ€ ννμμ Runnable μΈν°νμ΄μ€ νμ μ λ³μμ ν λΉνλ€. μ΄λ κ² νλ©΄ λλ€ ννμμ Runnable μΈν°νμ΄μ€μ ꡬν체λ‘μμ μν μ νκ² λλ€.
2. ν¨μν μΈν°νμ΄μ€ νμ μ Object νμ μΌλ‘ νλ³ν
μ΄μ Runnable νμ μ λ³μλ₯Ό Object νμ μΌλ‘ νλ³νν μ μλ€. μ΄ λ¨κ³μμλ Runnableμ΄ μ΄λ―Έ ꡬ체μ μΈ νμ μΌλ‘ μ‘΄μ¬νκΈ° λλ¬Έμ, μ΄λ₯Ό Object νμ μΌλ‘ νλ³ννλ κ²μ΄ κ°λ₯νλ€.
public class LambdaToObjectExample {
public static void main(String[] args) {
// λλ€ ννμμ ν¨μν μΈν°νμ΄μ€ νμ
μΌλ‘ λ³ν
Runnable runnable = () -> System.out.println("Hello, Runnable!");
// ν¨μν μΈν°νμ΄μ€ νμ
μ Object νμ
μΌλ‘ νλ³ν
Object obj = (Object) runnable;
// objλ₯Ό λ€μ Runnable νμ
μΌλ‘ νλ³ννμ¬ μ¬μ©
((Runnable) obj).run();
}
}
| μΈλΆ λ³μλ₯Ό μ°Έμ‘°νλ λλ€μ
μμ μ½λλ λλ€μμ΄ μμ μ λλ¬μΌ μΈλΆ μ€μ½νμ λ³μλ€μ μ΄λ»κ² μ°Έμ‘°νλμ§ λ³΄μ¬μ£Όλ μμμ΄λ€.
λλ€μ λ΄μμ μ°Έμ‘°νλ μ§μλ³μλ finalμ΄ λΆμ§ μμμ΄λ μμλ‘ κ°μ£Όλλ€.
@FunctionalInterface
interface MyFunction3{
void myMethod();
}
class Outer{
int val = 10; //Outer.this.val
class Inner{
int val =20; // this.val
void method(int i){ // void method(final int i)
int val = 30; // final int val =30;
// i = 10; // μλ¬. μμμ κ°μ λ³κ²½ν μ μμ
MyFunction3 f = () ->{// λ©μλ λ΄μμ MyFunction3 νμ
μ fλ₯Ό λλ€μμΌλ‘ ꡬν
System.out.println(" i : " + i);
System.out.println(" val : " + val);
System.out.println(" this.val : " + this.val);
System.out.println(" Outer.this.val : " + Outer.this.val);
};
f.myMethod();
}
}
}
public class LamdaEx3 {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.method(100);
}
}
- λλ€μ λ΄μμ μ§μλ³μ iμ valμ μ°Έμ‘°νκ³ μμΌλ―λ‘ λλ€μ λ΄μμλ λ€λ₯Έ μ΄λ κ³³μμλ μ΄ λ³μλ€μ κ°μ λ³κ²½νλ μΌμ νμ©λμ§ μλλ€.
- λ°λ©΄μ Innerν΄λμ€μ Outerν΄λμ€μ μΈμ€ν΄μ€ λ³μμΈ this.valκ³Ό Outer.this.valμ μμλ‘ κ°μ£Όλμ§ μμΌλ―λ‘ κ°μ λ³κ²½ν΄λ λλ€.
- λν μΈλΆ μ§μλ³μμ κ°μ μ΄λ¦μ λλ€μ 맀κ°λ³μλ νμ©λμ§ μλλ€.