람다보다는 메서드 참조를 사용하라

메서드 참조

map.merge(key, 1, (count, incr) -> count + incr);

위 코드는 Map의 merge 메서드를 사용했다. merge 메서드는 키, 값, 함수를 인수로 받으며, 주어진 키가 맵 안에 아직 없다면 주어진 키,값 쌍을 그래도 저장한다. 반대로 키가 이미 있다면 세 번째 인수로 받은 함수를 현재 값과 주어진 값에 적용한 다음, 그 결과로 현재 값을 덮어쓴다.
매개변수인 count와 incr은 크게 하는 일 없이 공간을 꽤 차지한다. 람다는 두 인수의 합을 반환할 뿐이다. 따라서 람다 대신 이 메서드의 참조를 전달하면 똑같은 결과를 더 보기 좋게 얻을 수 있다.

map.merge(key, 1, Integer::sum);

람다에서는 매개변수의 이름 자체가 프로그래머에게 좋은 가이드가 되기도 한다. 이 경우 람다가 더 길지만 메서드 참조보다 읽기 쉽고 유지보수도 쉬울 수 있다.

람다가 메서드 참조보다 간결할 때

주로 메서드와 람다가 같은 클래스에 있을 때 그렇다.

service.execute(GoshThisClassNameIsHumongous::action);
service.execute(() -> action()));

같은 예로 java.util.function 패키지의 제네릭 정적 팩터리 메서드인 Function.identity() 보다 (x -> x) 를 사용하는 편이 더 낫다.

메서드 참조 유형

메서드 참조 유형 람다
정적 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]

함수형 인터페이스의 추상 메서드가 제네릭일 수 있듯이 함수 타입도 제네릭일 수 있다. 함수형 인터페이스를 위한 제네릭 함수 타입은 메서드 참조 표현식으로는 구현할 수 있지만, 람다식으로는 불가능하다. 제네릭 람다식이라는 문법이 존재하지 않기 때문이다.

Comments