💡람다식
람다식 (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 + "]";
}
}
인터페이스에 대해서는 위 글을 참고하도록 하자.
익명 클래스 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"));