JAVA/Effective Java
item 43. 람다보다는 메서드 참조를 사용하라
Garonguri
2022. 6. 17. 02:23
728x90
자바에서 함수를 간결하게 하는 방법!
: 메서드 참조 > 람다 > 익명 클래스
Map의 merge 메소드를 통하여 예시를 살펴보자.
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 2);
map.put(3, 4);
map.put(5, 6);
int key = 1;
map.merge(key, 2, (count, incr) -> count + incr);
[코드 설명]
- Map 타입 객체에 key를 매핑한다.
- Map 안에 key가 존재한다면, value와 기존 key에 매핑되는 value를 더한다.
- 존재하지 않을 경우에는 key, value를 추가한다.
: 깔끔해 보이지만, 매개변수 count와 incr은 크게 하는 일 없이 공간을 많이 차지하기 때문에, 거추장스럽다.
: 또한 여기서 사용된 람다는 두 인수의 합을 반환하는 역할만을 한다. (비교적 가벼운 역할?)
위에서 사용된 람다와 같은 기능을 하는 정적 메서드 sum을 사용해 위 코드를 메서드 참조를 사용하도록 바꿔보자.
map.merge(key, 2, (count, incr) -> count + incr);
map.merge(key, 2, Integer::sum);
위와 같은 경우 매개 변수가 늘어날 수록 메서드 참조로 제거할 수 있는 코드의 양도 늘어나고, 따라서 더 간결해진다.
Q. 그럼 무조건 메서드 참조가 좋나?
A. 아니!
어떤 람다에서는 매개변수 이름 자체가 프로그래머에게 가이드(문서)이기도 하다. 따라서 람다가 더 길어도 유지보수나 가독성 면에서 더 좋기 때문에 이런 경우에는 람다를 사용하는 것이 좋다.
Q. 어떤 경우에 람다가 더 좋은데?
A. 메서드와 람다가 같은 클래스 내에 있을 때는, 람다가 메서드 참조보다 간결하다.
map.merge(key, 2, (count, incr) -> count + incr);
람다로 할 수 없는 일은 메서드 참조로도 할 수 없다.
따라서, 메서드 참조를 사용했을 때 더 간결하고 짧은 코드가 되고, 람다를 사용했을 경우 너무 길거나 복잡한 코드가 될 경우에는 메서드 참조를 사용해보자.
즉, 람다로 작성할 코드를 새로운 메서드에 담은 다음 그 메서드를 참조하는 식으로 사용하라는 말이다.
service.execute(GoshThisClassNameIsHumongous::action);
service.execute(() -> action());
메서드 참조의 유형은 다섯 가지이다.
메서드 참조 유형 | 예 | 같은 기능을 하는 람다 | 의미 |
정적(Static) | Integer::parseInt | str -> Integer.parseInt(str) | 정적 메서드를 가리키는 메서드 참조 |
한정적(인스턴스) | Instant.now()::isAfter | Instant then = Instant.now(); t -> then.isAfter(t); | 수신 객체를 특정한다. 함수 객체가 받는 인수와 참조되는 메서드가 받는 인수가 같다. |
비한정적(인스턴스) | String::toLowerCase | str -> str.toLowerCase(); | 수신 객체를 특정하지 않는다. 함수 객체를 적용하는 시점에 수신 객체를 알려준다. 스트림 파이프라인에서의 매핑, 필터 함수에 쓰임 |
클래스 생성자 | TreeMap<K,V>::new | () -> new TreeMap<K,V>(); | 클래스 생성자를 가리키는 메서드 참조, 팩터리 객체로 사용한다. |
배열 생성자 | int[]::new | len -> new int[len]; | 배열 생성자를 가리키는 메서드 참조, 팩터리 객체로 사용한다. |
핵심 정리
메서드 참조가 짧고 명확하다면 메서드 참조를, 그렇지 않을 때는 람다를 사용해라!
728x90