원본 글: https://www.baeldung.com/java-compare-strings
String 객체를 비교하는방법에는 여러가지가 있는데, 이 글은 여러 방법들을 비교 분석하는 글입니다.
1. String Comparison With String Class
1.1 '=='연산자를 이용한 비교
'=='를 이용한 비교는 흔히 사용하는 방법중 하나지만 좋은 방법은 아닙니다. 왜냐하면 해당 연산자는 참조 동일성만 확인하기 때문입니다.
여기서 참조 동일성이란 비교하는 두 대상의 참조, 주소값이 같은지 확인하는 것을 의미합니다.
@Test
public void operator_Test() {
String s1 = "hello minseok";
String s2 = "hello minseok";
String s3 = new String("hello minseok");
Assertions.assertTrue(s1 == s2);
Assertions.assertFalse(s1 == s3);
}
다른 포스팅에서도 동등성, 동일성에 대한 설명은 많이 하여서 이 코드가 왜 성공하는지 알 수 있을것입니다.
1.2 Using equals()
String클래스에서 제공하는 equals()메서드는 Object클래스에서 상속받아서 사용하고 있습니다. 해당 메서드는 오로지 값만을 비교하여, 위와는 다른 결과가 나옵니다.
@Test
public void string_equals_test() {
String s1 = "hello minseok";
String s2 = "hello minseok";
String s3 = "hello MINSEOK";
String s4 = new String("hello minseok");
Assertions.assertTrue(s1.equals(s2));
Assertions.assertTrue(s1.equals(s4));
Assertions.assertFalse(s1.equals(null));
Assertions.assertFalse(s1.equals(s3));
}
해당 메서드는 값만 비교하기에 s1과 s4을 비교했을때 같다는 결론이 나옵니다.
또한, 대소문자를 구분하고 null과의 비교도 가능하다는 것을 알 수 있습니다.
1.3 Using equalsIgnoreCase()
위에서 대소문자를 구분하는 메서드를 확인하였습니다.
equalsIgnoreCase()는 대소문자를 구분하지 않습니다.
@Test
public void string_equalsIgnoreCase_test() {
String s1 = "hello minseok";
String s2 = new String("hello MINseok");
Assertions.assertTrue(s1.equalsIgnoreCase(s2));
}
1.4 Using compareTo()
해당 메서드는 코드를 보고 설명을 보는게 더 이해하기 쉽습니다.
@Test
public void string_compareTo_test() {
String s1 = "apple";
String s2 = "banana";
String s3 = "banana";
Assertions.assertEquals(s1.compareTo(s2), -1);
Assertions.assertEquals(s2.compareTo(s1), 1);
Assertions.assertEquals(s2.compareTo(s3), 0);
}
해당 메서드는 두 문자열을 사전순기준으로 비교합니다. apple이 banana보다 사전에서 앞서있기에 음수값을 리턴하고, banana기준으로 apple보다는 뒤에있기에 양수값을 리턴하게 됩니다. 만약 두 값이 동일하다면 '0'을 리턴합니다.
- 기준값이 사전순으로 앞선 경우: return 음수값
- 기준값이 사전순으로 뒤에 있는 경우: return 양수값
- 기준값과 값이 동일한 경우: return 0
1.5 Using compareToIgnoreCase()
위에서 비슷한 메서드를 확인했듯이, 해당 메서드는 compareTo()메서드에 대소문자를 구분하지 않은 버전입니다.
@Test
public void string_compareToIgnoreCase_test() {
String s1 = "apple";
String s2 = "banana";
String s3 = "BANANA";
Assertions.assertEquals(s1.compareTo(s2), -1);
Assertions.assertEquals(s2.compareTo(s1), 1);
Assertions.assertTrue(s2.compareTo(s3) > 0);
Assertions.assertEquals(s2.compareToIgnoreCase(s3), 0);
}
2. String Comparison With Objects Class
Objects 유틸클래스에서 제공하는 메서드를 통해서 비교하는방법이 있습니다.
Objects 유틸 클래스에서 제공하는 equals()메서드가 있습니다.
@Test
public void object_equals_test() {
String s1 = "hello minseok";
String s2 = "hello minseok";
String s3 = new String("hello minseok");
Assertions.assertTrue(Objects.equals(s1, s2));
Assertions.assertTrue(Objects.equals(s1, s3));
Assertions.assertTrue(Objects.equals(null, null));
Assertions.assertFalse(Objects.equals(null, s1));
}
특이한 사항으로는 해당 값은 비교할때 먼저, 동일성을 확인합니다(==). 동일하지 않은 경우 동등성을 확인합니다.(equals)
이는 해당 메서드의 구현상태를 보면 쉽게 확인이 가능합니다.

먼저 동일성을 확인하고, 이후 동등성을 확인하는 것을 알 수 있습니다.
3. String Comparison With Apache Commons
Apache Commons 라이브러리에는 다양한 문자열 유틸함수가 존재합니다.
3.1 Usign equals() and equlsIgnoreCase()
Apache Commons 라이브러리에도 equals(), equlasIgnoreCase() 메서드가 존재합니다.
기존 String에서 제공하는 메서드와 다르고 null를 다룰 수 있습니다.
@Test
public void apache_equals_test() {
Assertions.assertTrue(StringUtils.equals(null, null));
Assertions.assertFalse(StringUtils.equals(null, "minseok "));
Assertions.assertTrue(StringUtils.equals("minseok", "minseok"));
Assertions.assertFalse(StringUtils.equals("minseok", "Minseok"));
Assertions.assertTrue(StringUtils.equalsIgnoreCase("minseok", "minseok"));
Assertions.assertTrue(StringUtils.equalsIgnoreCase("minseok", "Minseok"));
}
3.2 Using equalsAny() and equalsAnyIgnoreCase()
해당 메서드들은 코드를 보는게 이해가 좀 더 빠릅니다.
@Test
public void apache_any_equals_test() {
Assertions.assertTrue(StringUtils.equalsAny(null, null, null));
Assertions.assertTrue(StringUtils.equalsAny("minseok", "minseok", "abc"));
Assertions.assertTrue(StringUtils.equalsAny("minseok", null, "minseok"));
Assertions.assertFalse(StringUtils.equalsAny(null, "abc", "minseok"));
Assertions.assertFalse(StringUtils.equalsAny("minseok", "abc", "Minseok"));
Assertions.assertTrue(StringUtils.equalsAnyIgnoreCase("minseok", "abc", "Minseok"));
}
특이하게 인자들이 여러개 들어갑니다.
기준은 첫 번째인자이며, 다른 인자들과 비교하여 첫 번째 인자와 같은 값이 존재하면 True를 리턴하게 됩니다.
당연하게도 equalsAnyIgnoreCase()메서드는 대소문자를 구분하지 않습니다.
3.3 Using compare() and compareIgnoreCase()
위 예제들을 보면 예상되듯이, null에 안전한 버전들입니다. null값은 기본적으로 어떤 값보다 사전순으로 앞서 있게 설정되어있습니다.
특이한 점은 두 메서드 모두 3번째 인자를 받을 수 있는데, null에 대한 기준값을 변경할 수 있습니다. 자세한건 테스트 코드를 보시면 이해가 편합니다.
@Test
public void apache_compareTo_test() {
Assertions.assertEquals(StringUtils.compare(null,null),0);
Assertions.assertEquals(StringUtils.compare(null,"abc"),-1);
Assertions.assertEquals(StringUtils.compare("abc","bbc"),-1);
Assertions.assertEquals(StringUtils.compare("bbc","abc"),1);
Assertions.assertEquals(StringUtils.compareIgnoreCase("Abc", "bbc"), -1);
Assertions.assertEquals(StringUtils.compareIgnoreCase("bbc", "Abc"), 1);
Assertions.assertEquals(StringUtils.compareIgnoreCase("Abc", "abc"), 0);
Assertions.assertEquals(StringUtils.compare(null, "abc", true),-1);
Assertions.assertEquals(StringUtils.compare(null, "abc", false),1);
Assertions.assertEquals(StringUtils.compareIgnoreCase(null, "Abc", true),-1);
Assertions.assertEquals(StringUtils.compareIgnoreCase(null, "Abc", false),1);
}
세 번째 인자값을 true로 설정하면 null값이 사전순의 맨 앞에 오게되는 것이고, 아니라면 맨 뒤로 가게된다고 이해하면 됩니다.
내 결론
String을 비교하는 여러 방법을 확인하였습니다.
제 생각에는 알고리즘에 자주쓰일 것 같은데, 각각의 특징을 정리하는 편이 좋을 것 같습니다.
1. '==' 비교는 잘 쓰이지 않는다.
2. apache가 제공하는 여러 문자열유틸 클래스들을 잘 활용하자.
- 내 생가에 가장 큰 장점은 Null에대해 안전하다는 것이다.
3. 대소문자 구분이 필요한가?
4. 여러 문자열중 일치하는 문자열이 존재하는가 여부를 판단해야하는가?
'Baeldung번역&공부 > Java-string' 카테고리의 다른 글
Multi-line을 정의하는 여러 방법(Java Multi-line String) (0) | 2025.01.30 |
---|---|
인코딩에 대하여(Guide to Character Encoding) (0) | 2025.01.29 |
문자열 순회 방법들(How to Iterate Over the String Characters in Java) (0) | 2025.01.27 |
String Pool에 대하여(Guide to Java String Pool) (0) | 2025.01.26 |
문자열을 잇는방법(Concatenating Strings in Java) (0) | 2025.01.22 |