쉽게 쉽게

[Java] StringTokenizer 사용법 - split()과의 차이점 본문

Java/Java

[Java] StringTokenizer 사용법 - split()과의 차이점

곱마2 2026. 7. 17. 18:14
반응형

📌 핵심 요약
  • StringTokenizer는 문자열을 구분자 기준으로 잘라주는 클래스 — 정규식을 쓰지 않아 split()보다 단순하고 빠르다
  • 세 번째 인자를 true로 주면 구분자도 토큰으로 반환 — 수식 파싱처럼 구분자 자체가 필요한 경우에 유용하다
  • 빈 토큰은 무시된다 — 구분자가 연속으로 나올 때 split()과 결과가 달라지므로 주의

1 StringTokenizer란?

java.util.StringTokenizer는 문자열을 구분자(delimiter) 기준으로 잘라 토큰 단위로 꺼내 쓸 수 있게 해주는 클래스다. 문자열을 한 번에 배열로 바꾸는 split()과 달리, hasMoreTokens()로 남은 토큰이 있는지 확인하면서 nextToken()으로 하나씩 꺼내는 방식으로 동작한다.

왜 사용하는가? (split과의 차이)

split()은 인자를 정규식으로 해석한다.

그래서 +, *, | 같은 정규식 특수문자를 구분자로 쓰려면 이스케이프가 필요하고, 내부적으로 정규식 엔진을 거치기 때문에 단순 분리 작업치고는 비용이 크다.

반면 StringTokenizer는 구분자를 문자 집합으로 그대로 해석한다.

"+-*"를 넘기면 정규식이 아니라 "+ 또는 - 또는 * 중 하나"라는 뜻이라 이스케이프를 고민할 필요가 없다.

코딩테스트에서 공백으로 구분된 입력을 대량으로 읽을 때 BufferedReader와 함께 표준 조합으로 쓰이는 이유이기도 하다.

ℹ️
구분자는 "문자열"이 아니라 "문자들의 집합"
new StringTokenizer(str, "+-")는 "+-"라는 두 글자짜리 문자열을 찾는 게 아니라, +와 - 각각을 구분자로 취급한다. 여러 종류의 구분자를 한 번에 처리할 수 있다는 뜻이지만, 두 글자 이상의 문자열 자체를 구분자로 쓰고 싶다면 StringTokenizer로는 안 되고 split()을 써야 한다.

2 StringTokenizer 사용법

생성자 3가지

생성자는 인자 개수에 따라 세 가지 형태가 있다. 세 번째 인자가 이 클래스의 핵심 기능이다.

 
Java — 생성자 3가지
// 1. 구분자 생략 — 기본값은 공백류(" \t\n\r\f")
StringTokenizer st1 = new StringTokenizer("1 2 3");
// 토큰: "1", "2", "3"

// 2. 구분자 지정 — 각 문자를 구분자로 취급
StringTokenizer st2 = new StringTokenizer("100-200+300", "+-");
// 토큰: "100", "200", "300" — 구분자는 버려진다

// 3. 세 번째 인자 true — 구분자도 토큰으로 반환
StringTokenizer st3 = new StringTokenizer("100-200+300", "+-", true);
// 토큰: "100", "-", "200", "+", "300" — 구분자가 살아있다

주요 메서드

 
Java — hasMoreTokens / nextToken / countTokens
StringTokenizer st = new StringTokenizer("10 20 30");

// 1. countTokens() — 남은 토큰 개수 반환
int count = st.countTokens();  // 3

// 2. hasMoreTokens() + nextToken() — 표준 순회 패턴
while (st.hasMoreTokens()) {
    String token = st.nextToken();  // "10" → "20" → "30"
}

// 3. 개수를 알고 있다면 for문으로도 가능
StringTokenizer st2 = new StringTokenizer("1 2 3 4 5");
int[] arr = new int[st2.countTokens()];
for (int i = 0; i < arr.length; i++) {
    arr[i] = Integer.parseInt(st2.nextToken());
}
⚠️
토큰이 없는데 nextToken()을 호출하면 예외 발생
남은 토큰이 없는 상태에서 nextToken()을 호출하면 NoSuchElementException이 발생한다. 항상 hasMoreTokens()로 확인하거나, countTokens()만큼만 반복해야 한다.

전체 메서드 한눈에 보기

메서드 설명 비고
hasMoreTokens() 남은 토큰이 있으면 true while 조건으로 사용
nextToken() 다음 토큰 반환 없으면 NoSuchElementException
nextToken(delim) 구분자를 새로 바꿔서 다음 토큰 반환 이후 호출에도 새 구분자 유지
countTokens() 남은 토큰 개수 반환 nextToken() 호출 시마다 감소

3 split()과의 비교

가장 헷갈리기 쉬운 차이는 빈 토큰 처리다. 구분자가 연속으로 나오거나 문자열이 구분자로 시작하면 두 방식의 결과가 달라진다.

 
Java — 빈 토큰 처리 차이
String str = "a,,b";

// split() — 빈 문자열도 결과에 포함
String[] arr = str.split(",");
// ["a", "", "b"] — 길이 3

// StringTokenizer — 빈 토큰은 건너뜀
StringTokenizer st = new StringTokenizer(str, ",");
// "a", "b" — 토큰 2개
구분 StringTokenizer split()
구분자 해석 문자 집합 (각 문자가 구분자) 정규식 (특수문자 이스케이프 필요)
빈 토큰 무시 포함
구분자 유지 가능 (세 번째 인자 true) 기본 불가 (lookahead 정규식 필요)
속도 빠름 (정규식 미사용) 상대적으로 느림
결과 형태 하나씩 순회 (Iterator 스타일) 배열로 한 번에 반환
💡
선택 기준
공백/특정 문자로 잘라서 순서대로 읽기만 하면 되는 입력 파싱은 StringTokenizer, 빈 문자열을 보존해야 하거나 인덱스로 접근할 배열이 필요하거나 정규식 패턴으로 잘라야 한다면 split()이 맞다.

4 실전 활용

BufferedReader와 조합 (입력 파싱)

코딩테스트에서 가장 자주 쓰는 형태다. Scanner보다 훨씬 빠르기 때문에 입력량이 많은 문제에서는 이 조합이 표준이다.

 
Java — BufferedReader + StringTokenizer
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

// "5 3" 형태의 한 줄 입력 파싱
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());

구분자를 살려서 수식 파싱하기

세 번째 인자 true가 진가를 발휘하는 경우다. 수식을 파싱할 때는 숫자뿐 아니라 연산자 자체도 토큰으로 필요한데, 세 번째 인자를 true로 주면 별도 처리 없이 숫자와 연산자가 번갈아 담긴 리스트를 바로 만들 수 있다.

 
Java — 수식을 토큰 리스트로 분리
String expression = "100-200*300-500+20";

List<String> tokens = new ArrayList<>();
StringTokenizer st = new StringTokenizer(expression, "+-*", true);
while (st.hasMoreTokens()) {
    tokens.add(st.nextToken());
}

// 결과: [100, -, 200, *, 300, -, 500, +, 20]
// 정규식 없이 숫자와 연산자가 번갈아 담긴 리스트 완성

같은 작업을 split()으로 하려면 split("(?=[+\\-*])|(?<=[+\\-*])") 같은 정규식이 필요하다.

정확히 쓰기도 어렵고 나중에 읽기는 더 어렵다.

구분자를 살려야 하는 파싱이라면 StringTokenizer의 세 번째 인자가 훨씬 단순한 답이 된다.

이 패턴을 실제로 활용한 문제 풀이는

2026.07.17 - [알고리즘/완전 탐색 및 백트래킹] - [프로그래머스] 수식 최대화(Java) - 완전탐색

글에서 확인할 수 있다.

잘못된 내용이 있다면 지적부탁드립니다. 방문해주셔서 감사합니다.

 

 

 

반응형