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

람다가 익명 클래스보다 나은 점 = 간결함

코드 예시: 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);
}

메소드 참조의 유형