더북(TheBook)

유니코드 대리 쌍의 한 예가 잘 알려진 하트 두 개짜리 기호다. 이 기호는 \uD83D와 \uDC95, 두 값을 포함하는 char[]로 표현된다. 이 기호의 코드 포인트는 128149다. String str = String.valueOf(Character.toChars(128149))를 호출하면 이 코드 포인트로부터 String 객체를 얻는다. str.codePointCount(0, str.length())를 호출하면 str 내 코드 포인트를 셀 수 있고, str의 길이가 2여도 1을 반환한다. str.codePointAt(0)을 호출하면 128149를, str.codePointAt(1)을 호출하면 56469를 반환한다. 128149라는 코드 포인트를 유니코드 대리 쌍으로 표현하려면 문자 두 개가 필요하므로 Character.toChars(128149)를 호출하면 2를 반환한다. 아스키와 유니코드 16비트 문자라면 1을 반환한다.

따라서 첫 번째 해법(문자열 문자를 순회하며 문자를 키로, 빈도수를 값으로 Map에 저장하는 방법)을 아스키와 유니코드(대리 쌍 포함) 모두 지원하도록 다시 작성하면 다음 코드와 같다.

public static Map<String, Integer>
    countDuplicateCharacters(String str) {
  Map<String, Integer> result = new HashMap<>();

  for (int i = 0; i < str.length(); i++) {
    int cp = str.codePointAt(i);
    String ch = String.valueOf(Character.toChars(cp));
    if(Character.charCount(cp) == 2) {  // 2는 대리 쌍을 뜻한다
      i++;
    }

    result.compute(ch, (k, v) -> (v == null) ? 1 : ++v);
  }

  return result;
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.