String

문자(char)들의 시퀀스를 다루는 불변(immutable) 객체입니다. Java에서 가장 많이 쓰이는 클래스 중 하나.

불변(Immutable)이란

String s = "hello";
s = s + " world";    // 기존 "hello"가 변하는 게 아니라
                     //   새로운 "hello world" 객체가 생성되고
                     //   변수 s가 그쪽을 가리킴

[ 메모리 ]
"hello"            ← 그대로 남음 (다른 곳에서 참조 가능)
"hello world"      ← 새로 생성

→ 문자열을 자주 변경한다면 StringBuilder 사용 (가변)

자주 쓰는 메서드

메서드용도
String.startsWith특정 문자열로 시작하는지
endsWith특정 문자열로 끝나는지
String.charAti번째 문자
String.length문자열 길이
substring(start, end)부분 문자열 추출
indexOf / lastIndexOf특정 문자/문자열의 위치
equals / equalsIgnoreCase내용 비교
compareTo사전식 비교 (정렬용)
split(regex)구분자로 분리
replace문자/문자열 치환
toCharArray()char[] 배열로 변환
toLowerCase / toUpperCase대소문자 변환
trim / strip앞뒤 공백 제거
contains특정 문자열 포함 여부
isEmpty / isBlank빈 문자열 / 공백만 있는지

정적 메서드

메서드용도
String.valueOf(x)숫자 등을 문자열로
String.format(fmt, args)포맷 문자열 생성
String.join(delim, ...)배열/컬렉션 → 문자열

문자열 비교: == vs equals

String a = "hello";
String b = "hello";
String c = new String("hello");

a == b           // true  ← 문자열 풀 (literal pool) 공유
a == c           // false ← 새 객체 생성
a.equals(c)      // true  ← 내용 비교

→ 문자열 비교는 항상 .equals() 사용

문자열 풀 (String Pool)

"hello" 같은 리터럴은 String Pool에 한 번만 생성:

String a = "hello";    ┐
String b = "hello";    ├─ 같은 객체 참조
String c = "hello";    ┘

new String("hello")    ← 풀과 별개로 새 객체 생성

→ 메모리 효율을 위해 리터럴 사용 권장

자주 쓰는 패턴

사전식 정렬 후 인접 비교

String[] arr = {"119", "97674223", "1195524421"};
Arrays.sort(arr);
// ["119", "1195524421", "97674223"]
//   ↑ "119"가 "1195524421"의 접두사 → 인접 위치

문자별 순회

String s = "hello";

for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    // ...
}

// 또는 char[] 변환
for (char c : s.toCharArray()) {
    // ...
}

분리하여 토큰 처리

String csv = "apple,banana,cherry";
String[] tokens = csv.split(",");
// ["apple", "banana", "cherry"]

String vs StringBuilder vs StringBuffer

항목StringStringBuilderStringBuffer
가변성불변가변가변
+ 연산매번 새 객체 생성append (in-place)append (in-place)
스레드 안전O (불변이므로)XO (synchronized)
반복 누적 시간O(n²)O(n)O(n)
언제 쓰는가짧은 문자열, 비교용단일 스레드에서 반복 누적멀티스레드 환경

실무에서는 멀티스레드 환경에서도 문자열 빌더를 지역 변수로 사용하므로 StringBuffer보다 StringBuilder를 압도적으로 많이 씀.

// X 반복문에서 String + 사용 → O(n²)
String result = "";
for (int i = 0; i < n; i++) result += i;

// O StringBuilder 사용 → O(n)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append(i);
String result = sb.toString();

시간복잡도

연산복잡도
charAt(i)O(1)
length()O(1)
substringO(n) — 새 객체 생성 (Java 7+)
equalsO(n)
indexOfO(n × m) (n=긴 쪽, m=찾는 쪽)
startsWithO(m) (찾는 쪽 길이만)
+ 연산O(n)

핵심 정리

String은 자바의 불변 객체로, 한 번 생성된 문자열은 변경되지 않고 새 객체가 만들어집니다. 비교는 항상 .equals()를 사용해야 하며 (==은 참조 비교), 반복적으로 문자열을 누적할 때는 시간복잡도 O(n²)를 피하기 위해 StringBuilder를 사용합니다. 알고리즘 문제에서는 charAt, length, substring, startsWith, split, toCharArray 등이 자주 등장합니다.

CSLOG에서 보기