자바(Java)로 알고리즘 문제를 풀거나 문자열을 다루다 보면, 로직은 완벽한 것 같은데 이상하게 에러가 나거나 결과가 중간에 잘리는 경험을 하곤 합니다. 오늘은 자바 입문자들이 가장 많이 겪는 문자열 처리 관련 3가지 실수와 올바른 해결법을 정리해 보았습니다.
StringTokenizer의 함정: countTokens()는 고정값이 아니다!토큰의 개수만큼 배열을 만들고, 반복문을 돌려 값을 채워 넣는 아래 코드를 볼까요?
잘못된 방식
BufferedReader br = new BufferedReader(new InputStreamReader([System.in](http://system.in/)));
StringTokenizer st = new StringTokenizer(br.readLine().replace("\"", ""), ", ");
String[] arr = new String[st.countTokens()];
// 함정 발생 구간!
for(int i = 0; i < st.countTokens(); i++){
arr[i] = st.nextToken();
}
언뜻 보면 문제없어 보이지만, 이 코드는 배열을 끝까지 채우지 못하고 중간에 멈춰버립니다.
이유는 st.nextToken()을 호출할 때마다 남아있는 토큰이 줄어들면서 st.countTokens()의 값도 계속 작아지기 때문입니다. (처음엔 3개여서 통과 ➔ 다음 바퀴엔 2개 ➔ 1개... 결국 반복문이 일찍 종료됩니다.)
올바른 방식
int count = st.countTokens(); // 변수에 미리 개수를 고정해둔다!
String[] arr = new String[count];
for(int i = 0; i < count; i++){
arr[i] = st.nextToken();
}
반드시 count라는 변수에 초기 토큰 개수를 미리 저장해두고, 그 고정된 숫자를 기준으로 반복문을 돌려야 합니다.
String.join의 올바른 사용법배열에 있는 문자열들을 하나로 합치고 싶을 때, 굳이 반복문을 돌릴 필요가 없습니다.
잘못된 방식 (반복문 사용)
String answer = "";
for(int i = 0; i < arr.length; i++){
answer = String.join(arr[i]); // 이렇게 쓰면 안 됩니다!
}
올바른 방식 (한 줄로 끝내기)
return String.join("", arr);
String.join은 반복문 없이 배열 전체를 한 번에 합쳐주는 마법 같은 메서드입니다. 첫 번째 인자로 들어가는 ""는 구분자입니다. 빈 문자열("")을 주면 글자 사이에 아무것도 넣지 않고("abc") 다닥다닥 예쁘게 붙여줍니다.
'') vs 쌍따옴표("") 완벽 구분파이썬이나 자바스크립트와 달리, 자바는 따옴표의 종류에 아주 엄격합니다.
| 구분 | 홑따옴표 ('w') | 쌍따옴표 ("w") |
|---|---|---|
| 데이터 타입 | char (기본형) | String (참조형/객체) |
| 의미 | 딱 한 글자의 '문자' | 글자들의 모음인 '문자열' |
| 비교 방법 | == 연산자 사용 | .equals() 메서드 사용 |
charAt(3) == "w"는 컴파일 에러가 날까?string.charAt(3)은 문자열에서 3번 인덱스에 있는 딱 한 글자(char)만 쏙 뽑아옵니다.
string.charAt(3) ➔ char 타입"w" ➔ String 타입 자바 입장에서는 "가벼운 기본형 문자(char)와 무거운 객체(String)는 태생부터 달라서 비교할 수 없어!" 라며 에러를 냅니다.1. 같은 char 타입으로 비교하기 (추천)
if (string.charAt(3) == 'w') { // 둘 다 char 타입이므로 == 사용 가능
// ...
}
2. 굳이 쌍따옴표(String)와 비교하고 싶다면?
// char를 String으로 바꾼 뒤, .equals()로 비교해야 합니다.
String 뽑은글자 = String.valueOf(string.charAt(3));
if (뽑은글자.equals("w")) {
System.out.println("w가 맞습니다!");
}