• Java Character 클래스, toUpperCase()와 toLowerCase() 중 하나로는 완전한 비교가 불가능하다?!

    2021. 4. 24.

    by. SDev

    728x90

     

    프로그래머스의 해시 카테고리에서 전화번호 목록 문제를 풀다가, 문득 String 클래스의 정렬 방식이 어떻게 구현돼있는지 궁금해져 코드를 까봤다. 

    private static class CaseInsensitiveComparator
                implements Comparator<String>, java.io.Serializable {
            // use serialVersionUID from JDK 1.2.2 for interoperability
            private static final long serialVersionUID = 8575799808933029326L;
    
            public int compare(String s1, String s2) {
                int n1 = s1.length();
                int n2 = s2.length();
                int min = Math.min(n1, n2);
                for (int i = 0; i < min; i++) {
                    char c1 = s1.charAt(i);
                    char c2 = s2.charAt(i);
                    if (c1 != c2) {
                        c1 = Character.toUpperCase(c1);
                        c2 = Character.toUpperCase(c2);
                        if (c1 != c2) {
                            c1 = Character.toLowerCase(c1);
                            c2 = Character.toLowerCase(c2);
                            if (c1 != c2) {
                                // No overflow because of numeric promotion
                                return c1 - c2;
                            }
                        }
                    }
                }
                return n1 - n2;
            }
    
            /** Replaces the de-serialized object. */
            private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
        }

     

    가만히 코드를 보는데, 코드가 좀 이상하다. compare() 메서드 내에서 c1c2를 비교하는 과정에 Character.toUpperCase()와 Character.toLowerCase()를 한번씩 사용해 결과를 비교해주고 있는 것이다. 

    toUpperCase()에서 같지 않았던 값이 toLowerCase()를 수행했을 때 같은 값을 갖게 되는 경우가 존재할 수 있나?

     

    뭔가 잘못 생각하고 있는지 한참을 고민하다, 구글링을 시작했는데 여기에 대해 다룬 포스팅을 찾지 못했다.

    답답함을 못참고 okky로 가서 QnA를 남겨봤는데, 어떤 고수분이 아주 감사하게도 한 링크로 댓글을 달아주셨다.

    https://stackoverflow.com/questions/39084032/java-why-string-compareignorecase-uses-both-character-touppercase-and-chara 

     

    스택오버플로우에 정확하게 같은 질문이 있었다. 
    (내가 이리저리 검색했을땐 안나왔는데... 창피했지만 한번 더 구글링 키워드도 여쭤봤더니 친절히 알려주셨다ㅠㅠ)

     

    문제는 바로 Unicode 다국어 처리!

    stackoverflow 캡처

    상상도 못했는데, 일반적으로 알고 있는 영문 알파벳들 사이에 존재하는 다국어 유니코드가 있다고 한다. 이 때문에 toUpperCase()메서드로 검사했을 때는 true를 반환하는데 toLowerCase()로 검사했을 땐 false를 반환하는 경우가 존재하는 것이다. 또, 반대의 경우도 물론 존재한다.

     

    글로벌 서비스를 개발할 때는, 이런 세세한 부분까지 고려할 부분이 참 많을 것 같다. 
    그래서 더 그런 서비스를 개발해보고 싶다 ㅎㅅㅎ

    댓글