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

2023. 12. 19. 21:40Book/이펙티브 자바

람다의 큰 장점중 하나는 간결함인데, 이보다 더 간결하게 만든느 방법은 메서드 참조이다.

 

다음 코드를 보자

String 타입의 키와 Integer 값의 매핑을 관리하는 프로그램의 일부다.

public static void main(String[] args) {
    Map<String, Integer> map = new HashMap<>();

    map.merge("key1", 1, (count, incr) -> count + incr);
    map.merge("key1", 1, (count, incr) -> count + incr);
    map.merge("key2", 1, (count, incr) -> count + incr);
    map.merge("key2", 1, (count, incr) -> count + incr);
    map.merge("key2", 1, (count, incr) -> count + incr);

    System.out.println(map);
}

=> {key1=2, key2=3}

 

merge 메서드는 키, 값, 함수를 인수로 받으며

 

1) 주어진 키가 맵 안에 없다면

=> 키, 값을 맵에 저장

 

2) 주어진 키가 맵 안에 있다면

=> 세번째 인수로 받은 함수에 현재 값과 주어진 값에 적용한 다음, 그 결과로 현재 값을 덮어쓴다.

 

세번째 인수인 람다는 단순히 두 인수를 받아 그 합을 반환하는데, 람다 대신 두 개의 인수를 받아 더해주는 sum이라는 정적 메서드를 사용할 수 있다. 따라서 람다 대신 이 메서드의 참조를 전달하면 똑같은 결과를 더 간결하게 얻을 수 있다.

map.merge("key2", 1, (count, incr) -> count + incr);
.
.
//Integer.sum 사용
map.merge("key2", 1, (count, incr) -> Integer.sum(count, incr));
.
.
//메서드 참조
map.merge("key2", 1, Integer::sum);

 

 

 

메서드 참조의 유형은 다섯 가지로, 가장 흔한 유형은 위의 정적 메서드를 가리키는 메서드 참조다.

 

인스턴스 메서드 참조

 

1. 수신 객체를 특정하는 한정적 인스턴스 메서드 참조

- 함수 객체가 받는 인수와 참조되는 메서드가 받는 인수가 같다

Instant.now()::isAfter

Instant then = Instant.now();
t -> then.isAfter(t)

 

2. 수신 객체를 특정하지 않는 비한정적 인스턴스 메서드 참조

- 함수 객체를 적용하는 시점에 수신 객체를 알려준다. 그렇기 때문에 수신 객체 전달용 매개변수가 매개변수 목록 첫 번째로 추가되며 그 뒤로 참조되는 메서드 선언에 정의된 매개변수들이 온다.

String::toLowerCase

str -> str.toLowerCase()

 

마지막으로 클래스 생성자, 배열 생성자를 가리키는 메서드 참조가 있다.

HashMap<String, String>::new
() -> new HashMap<String, String>()

int[]::new
lem -> new int[len]