Programming/Java

[Java] 람다식 (Lambda Expression)

Isaac S. Lee 2023. 8. 10. 11:15

💡람다식


람다식 (Lambda Expression)은 기존에 하던 작업을 편리하고 간결하게 만들어주는 기술로, 함수형 프로그래밍 개념을 자바에 도입한 것이다.

주로 컬렉션 조작을 위해 스트림(Stream)과 함께 사용되며, 람다식을 사용하면 코드의 양을 줄이고 작업을 더 효율적으로 처리할 수 있다.

 

람다식의 형식

인터페이스 변수 = (매개변수) -> {
    // 실행 코드
};

 

람다식의 구성 요소

  • 매개변수(Parameter): 메서드의 매개변수와 동일한 역할을 한다.
  • 화살표(->): 코드 블럭을 호출하는 역할을 한다.
  • 실행 코드(Block): 메소드의 본문과 같은 역할을 하며, 중괄호 내에 실제 작업 내용을 작성한다.

 

MyInterface를 구현한 객체를 살펴보며 람다식을 이해해 보도록 하자.

// 실명 클래스에서 구현
MyInterface m1 = new MyClass();
m1.test(); // 실명 클래스에서 구현한 메소드

// 익명 클래스에서 구현
MyInterface m2 = new MyInterface() {
    @Override
    public void test() {
        System.out.println("익명 클래스에서 구현한 메소드");
    }
};
m2.test(); // 익명 클래스에서 구현한 메소드

// 람다식에서 구현
MyInterface m3 = ()->{
    System.out.println("람다식에서 구현한 메소드");
};
m3.test(); // 람다식에서 구현한 메소드

인터페이스를 선언하는 것부터 클래스를 만들기 위한 구문이 없더라도 MyInterface를 알고 있으면 컴파일러가 추측하도록 할 수 있다.

이러한 람다식의 표현 방식은 익명 클래스(객체)를 편하게 만드는 표현식이라고 할 수 있다.

아래는 실명 클래스와 익명 클래스에서 구현하기 위해 선언된 인터페이스와 클래스이다.

interface MyInterface {
	void test();
}

class MyClass implements MyInterface{
	@Override
	public void test() {
		System.out.println("실명 클래스에서 구현한 메소드");
	}
}

class Student {
	private String name;
	private int kor;
	private int eng;
	private int math;
	
	// 생성자
	public Student(String name, int kor, int eng, int math) {
		super();
		this.name = name;
		this.kor = kor;
		this.eng = eng;
		this.math = math;
	}

	public int getTotal() {
		return this.kor + this.eng + this.math;
	}
	
	public String getName() {
		return name;
	}

	public int getKor() {
		return kor;
	}

	public int getEng() {
		return eng;
	}

	public int getMath() {
		return math;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", kor=" + kor + ", eng=" + eng + ", math=" + math + "]";
	}
}

 

 

[Java] 인터페이스 (Interface)

인터페이스는 클래스의 일종으로, 클래스가 자료형인 것처럼 인터페이스도 마찬가지로 자료형이다. 인터페이스는 상속받는 여러 클래스들을 행동(사용법, 메소드)들을 통일시키는 역할을 하며

isaac-christian.tistory.com

인터페이스에 대해서는 위 글을 참고하도록 하자.

 

익명 클래스 vs 람다식

// Math.random() // 0 ~ 1 > 실수 난수
Random rnd = new Random();
System.out.println(rnd.nextInt(10)); // 0~9

ArrayList<Integer> nums = new ArrayList<Integer>();

// 난수 생성
for (int i = 0; i < 10; i++) {
    nums.add(rnd.nextInt(10) + 1);
}
System.out.println(nums); // [3, 10, 1, 8, 4, 10, 1, 2, 8, 4]

// 익명 클래스 활용
nums.sort(new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1 - o2;
    }
});
System.out.println(nums); // [1, 1, 2, 3, 4, 4, 8, 8, 10, 10]

// 람다식 활용
nums.sort((Integer o1, Integer o2) -> {
    return o1 - o2;
});
nums.sort((o1, o2) -> o1 - o2);
System.out.println(nums); // [1, 1, 2, 3, 4, 4, 8, 8, 10, 10]

난수를 10개 생성한 뒤, 오름차순으로 정렬하는 코드이다.

익명 클래스를 활용해 오름차순을 구현하는 것 보다 람다식으로 구현하는 게 더욱 간결한 것을 확인할 수 있다.

 

💡람다식의 활용


// 파라미터도 없고 리턴도 없는 경우
interface NoParameterNoReturn {
	void call();
}

interface parameterNoReturn {
	void call(int num);
}

interface MultiParameterNoReturn {
	void call(String name, int age);
}

interface NoParameterReturn {
	int call();
}

// 파라미터도 있고 리턴도 있는 경우
interface parameterReturn {
	int call(String name);
}

 

NoParameterNoReturn

NoParameterNoReturn pr1 = new NoParameterNoReturn() {
    @Override
    public void call() {
        System.out.println("pr1");
    }
};
NoParameterNoReturn pr2 = () -> {
    System.out.println("pr2");
};
pr2.call(); // pr2
// NoParameterNoReturn pr3 = () -> { System.out.println("pr3") };
NoParameterNoReturn pr3 = () -> System.out.println("pr3");

람다식은 코드를 쉽게 만들려고 쓰는 것이다.

람다식을 한 줄로 작성할 수 있을 때에는 길이를 늘이지 말고 한 줄로 적어주는 것이 좋다.

parameterNoReturn pr4 = (int num) -> {
    System.out.println(num);
};
pr4.call(100); // 100
pr4.call(200); // 200
pr4.call(300); // 300

 

parameterNoReturn

parameterNoReturn pr5 = (num) -> System.out.println(num); // 매개변수의 자료형 생략
// parameterNoReturn <- 이걸 알면 자료형을 충분히 추측할 수 있기 때문이다.
pr5.call(400); // 400
pr5.call(500); // 500

 

람다식은 매개변수의 자료형을 생략할 수 있다.

parameterNoReturn pr6 = num -> System.out.println(num); // 매개변수의 () 생략
pr6.call(600); // 600
pr6.call(700); // 700

또한 람다식은 매개변수의 ()를 생략할 수 있다.

MultiParameterNoReturn pr7 = (String name, int age) -> {
    System.out.println(name + "," + age);
};
pr7.call("Isaac", 24); // Isaac,24

 

MultiParameterNoReturn

MultiParameterNoReturn pr8 = (name, age) -> System.out.println(name + "," + age);
pr8.call("Sopia", 25); // Sopia,25

매개변수의 소괄호는 매개변수가 1개일 때만 생략할 수 있다.

 

NoParameterReturn

NoParameterReturn pr9 = () -> {
    return 100;
};
System.out.println(pr9.call()); // 100
// NoParameterReturn pr10 = () -> return 100; 
NoParameterReturn pr10 = () -> 100; 
System.out.println(pr10.call());

return문이 하나만 있을 때에는 return문 마저 생략을 해야 한다.

 

parameterReturn

parameterReturn pr11 = name -> name.length();
System.out.println(pr11.call("Isaac"));