람다가 익명 클래스보다 나은 점 = 간결함
코드 예시: String array에서 해당 문자열을 키로, 문자열이 나온 횟수를 값으로 하는 TreeMap 반환
@Slf4j
class LambdaTest {
String[] args;
Map<String, Integer> frequencyTable;
@BeforeEach
void setup(){
args = new String[4];
args[0] = "ab";
args[1] = "cd";
args[2] = "ef";
args[3] = "ab";
frequencyTable = new TreeMap<>();
}
// merge를 사용하지 않은 경우
@Test
void nonFunctionTest(){
for (String s : args) {
int value = frequencyTable.getOrDefault(s, 0) + 1;
frequencyTable.put(s, value);
}
log.info("{}", frequencyTable);
}
// 익명 클래스로 구현
@Test
void annoymousTest(){
for (String s : args) {
frequencyTable.merge(s, 1, new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
});
}
log.info("{}", frequencyTable);
}
}
@Test
void lambdaTest(){
for (String s : args) {
frequencyTable.merge(s, 1, (count, incr) -> count + incr); // Lambda
}
log.info("{}", frequencyTable);
}
람다를 사용할 경우 익명 클래스를 사용했을 때보다는 훨씬 간결해진 것을 볼 수 있다. 하지만 여기에서 더 줄이는 방법이 존재하고, 그 방법을 사용할 수 있는 이유로는 merge를 적용하는 함수 부분의 로직이 단순하고, 이는 이미 Integer에 구현이 되어 있다(sum)
@Test
void referenceTest(){
for (String s : args) {
frequencyTable.merge(s, 1, Integer::sum); // Method reference
}
log.info("{}", frequencyTable);
}
// 추가
@Test
void forEachWithReferenceTest(){
Arrays.stream(args).forEach(s -> frequencyTable.merge(s, 1, Integer::sum));
log.info("{}", frequencyTable);
}
매개변수의 수가 늘어날 수록 코드가 길이가 더욱 짧아진다.
하지만 람다에서 매개변수의 이름 자체가 프로그래머에게 좋은 가이드가 되기에 무조건 메서드 참조가 유리하다고 보기도 힘들다.
람다로 할 수 없는 일이라면 메서드 참조로도 대부분 할 수 없다.
IDE는 람다를 메서드 참조로 대체하라고 권할 것이다(대부분) → 코드의 간결성을 높이기 위함
람다를 메서드 참조로 바꿨을 떄 가독성이 반대로 안좋은 경우가 존재
// 메서드 참조
service.execute(GoshThisClassNameIsHumongous::action);
// 람다 사용
service.execute(() -> action());