오늘은 문자열 처리와 관련된 핵심 클래스와 메서드 몇 가지를 학습하고, 왜 StringBuilder를 사용하는 것이 더 효율적인지에 대해 정리했다. 기본적인 내용 같지만, 알고리즘 문제 풀이와 성능 최적화 측면에서 중요한 포인트이기 때문에 TIL로 남긴다.
String vs StringBuilder – 왜 StringBuilder를 사용할까?
- 자바에서 String은 불변(immutable) 객체이다. 따라서 문자열을 수정(추가, 삭제 등)할 때마다 새로운 객체가 생성된다.
String str = "Hello";
str += "World"; // 내부적으로 새로운 String 객체가 만들어짐
- 이와 달리 StringBuilder는 가변(mutable) 객체로, 문자열을 이어 붙일 때도 기존 메모리 공간에서 작업을 수행하기 때문에 성능이 훨씬 우수하다. 특히 반복문 내 문자열 누적 상황에서는 StringBuilder를 반드시 쓰는 것이 바람직하다.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
StringBuilder.reverse()
- 문자열을 뒤집는 가장 간단한 방법 중 하나로 문자열이 회문인지 판별할 때 매우 유용하다. 예를 들어 "racecar" 같은 문자열을 뒤집어 원래 문자열과 비교할 수 있다. 일반 배열이나 리스트는 Collections.reverse()로 뒤집지만, 문자열은 StringBuilder로 처리하는 것이 가장 간단하고 빠르다.
StringBuilder sb = new StringBuilder("abcde");
System.out.println(sb.reverse()); // edcba
StringBuilder.toString()
- StringBuilder는 String과 다르게 직접 출력이 불가능하기 때문에 .toString()으로 변환해주어야 한다. 중간에 문자열로 변환하는 것은 비용이 생기므로, 누적이 모두 끝난 뒤 toString()을 한 번만 호출하자.
StringBuilder sb = new StringBuilder();
sb.append("Hello");
String result = sb.toString(); // String으로 변환
String.valueOf(char[])
- char[] 배열을 문자열로 바꾸는 가장 직관적인 방법이다. String.valueOf(char[])는 내부적으로 new String(char[])을 호출하며, 명시적이고 가독성이 좋은 방법이다.
- "null" 을 넣었을 때 "null" 이라는 문자열을 반환하므로 NullPointerException 없이 사용할 수 있다. 단, 이 "null" 이라는 결과가 의도치 않은 출력이 될 수 있으므로 주의가 필요하다.
char[] chars = {'J', 'A', 'V', 'A'}; String result = String.valueOf(chars); // "JAVA"
Character.isAlphabetic(char ch)
- 해당 문자가 알파벳인지 여부를 판단하는 메서드다. Character.isLetter()와 유사하지만, isAlphabetic()은 더 넓은 유니코드 범위를 지원한다. 두 메서드는 대부분의 알파벳에서 동일한 결과를 반환하지만, isAlphabetic()은 고대 문자나 일부 유니코드 문자 범위를 포함하는 등 더 일반적인 알파벳 개념을 따른다.
- 일반적인 영어 문자열 처리에는 isLetter()로도 충분하지만, 국제화(i18n)를 고려한 서비스라면 isAlphabetic()이 더 적합할 수 있다.
System.out.println(Character.isAlphabetic('A')); // true
System.out.println(Character.isAlphabetic('1')); // false
String.equalsIgnoreCase()
- 대소문자를 무시하고 문자열을 비교할 수 있다. 사용자 입력 검증, 특정 키워드 필터링 등에 유용하게 사용할 수 있다.
- 회원가입 시 ID 또는 이메일 중복 체크를 할 때, 대소문자 구분 없이 비교해야 하는 경우가 많다. 예를 들어 "Apple"과 "apple"을 같은 값으로 간주해야 한다면 equalsIgnoreCase()가 유용하다. 또한 키워드 검색 등에서도 대소문자 구분 없이 결과를 보여줄 때 자주 사용된다.
System.out.println("hello".equalsIgnoreCase("HELLO")); // true
System.out.println("java".equalsIgnoreCase("JaVa")); // true
정리
기능 | 메서드/클래스 | 핵심 특징 |
문자열 누적 | StringBuilder | 성능 최적화 |
문자열 뒤집기 | StringBuilder.reverse() | O(n) |
최종 문자열 변환 | toString() | StringBuilder → String |
문자 배열 → 문자열 | String.valueOf(char[]) | 직관적 변환 |
알파벳 판별 | Character.isAlphabetic() | 유니코드 고려 |
문자열 비교 (대소문자 무시) | equalsIgnoreCase() | 사용자 입력 대응 |
마무리
이번 학습을 통해 자바에서 문자열 처리 시 선택할 수 있는 다양한 방법들을 정리해보았다. 단순한 개념 같지만, 성능 최적화, 알고리즘 풀이, 사용자 입력 처리 등 실전에서 자주 사용되는 기능들이었다. 특히 StringBuilder는 반복적인 문자열 조작에서 필수적인 도구이며, 기타 유틸 메서드들도 알고리즘 문제 풀이에 자주 등장하므로 숙지해둘 필요가 있다.