compareTo는 동일 여부뿐만 아니라 대소비교(어떤 문자열이 사전순으로 더 우선인지)도 할 수 있습니다.
compareTo
String s1 = "abc";
String s2 = "def";
System.out.println("abc compareTo def : " + s1.compareTo(s2));
System.out.println("def compareTo abc : " + s2.compareTo(s1));
System.out.println("abc compareTo abc : " + s1.compareTo(s1));
공식 문서에는 비교 기준이 lexicographic ordering(사전순서)라고 나와있습니다.
매개변수 문자열이 더 크면 음수, 같으면 0, 작으면 양수가 나옵니다.
실제 compareTo의 로직은 두 문자열을 문자(char)단위로 비교한후 다른문자가 있으면 문자끼리 뺀 값을 리턴합니다.
만약 두 문자가 같으면 두 문자의 길이를 뺀 값이 리턴됩니다.
예를 들어, aaa와 aab를 비교할때는 0, 1번째 문자끼리는 같지만 2번째 문자가 서로 다릅니다.
그래서 기준문자열 aaa의 2번째 문자인 a와 비교문자열 aab의 두번째 문자인 b의 값을 뺀 -1이 리턴됩니다.
String s1 = "aaa";
String s2 = "aab";
System.out.println("aaa compareTo aab : " + s1.compareTo(s2));
-1이 리턴되는 이유는 'a'의 아스키코드 번호가 97이고 'b'는 98이라 두 값을 빼면 -1이 나옵니다.
또 다른 예시를 보여드리면
System.out.println("! compareTo A : " + "!".compareTo("A"));
'!'의 아스키코드 번호는 33, 'A'는 65라서 -32가 리턴됩니다.
그래서 compareTo메소드는 대소문자를 구분하여 비교를 합니다.
'A'는 65, 'a'는 97이기때문에 두 값을 뺀 -32가 리턴됩니다.
compareToIgnoreCase
equalsIgnoreCase처럼 compareTo도 compareToIgnoreCase 메소드가 존재합니다.
compareToIgnoreCase는 대소문자 구분없이 비교합니다.
System.out.println("a compareTo A : " + "a".compareTo("A"));
System.out.println("a compareToIgnoreCase A : " + "a".compareToIgnoreCase("A"));
'a'와 'A'의 비교값이 0이 나오는 것을 확인할 수 있습니다.
실제 compareToIgnoreCase의 코드는 String클래스에 있는 CASE_INSENSITIVE_ORDER 변수를 사용하는데,
문자열의 문자들을 대문자로 변환한 뒤 두 문자가 서로 다르면 소문자로 바꾼뒤 그 값들을 뺀 값을 리턴하는 로직으로 구현되어 있습니다.
그래서 a와 A를 모두 대문자로 바꾸면 A, A가 되고, 두 문자를 빼면 0이 나오게 됩니다.
가끔 compareTo결과가 헷갈리는 경우가 있습니다.
그럴때는 기준문자열을 생각하면 됩니다.
만약에 "a".compareTo("b")가 -1이라면 음수니까 기준문자열 "a"가 더 작구나 생각하고 그 반대가 되면 양수가 나오니까 "a"가 크구나 생각하면 덜 혼동됩니다.
읽으면 좋은 글
[Java] Comparable compareto 오버라이딩 사용법