| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- AWS배포
- 프로그래머스 2개 이하로 다른 비트
- 자바의 정석
- 혼공얄코
- 백트래킹
- 오블완
- DFS
- Ubuntu서버
- 둘만의 암호 자바
- spring security
- 둘만의 암호
- java
- Comparable
- 프로그래머스 둘만의 암호
- LocalDate
- systemd
- 티스토리챌린지
- 서버초기설정
- 리눅스
- hackerrank
- 프로그래머스
- spring security 설정
- 분할정복
- 자바의정석
- 알고리즘
- 분할정복 알고리즘
- EC2배포
- 스프링부트 배포
- SQL Mapper
- BFS
- Today
- Total
쉽게 쉽게
[Java] StringTokenizer 사용법 - split()과의 차이점 본문
- 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가지
생성자는 인자 개수에 따라 세 가지 형태가 있다. 세 번째 인자가 이 클래스의 핵심 기능이다.
// 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" — 구분자가 살아있다
주요 메서드
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()을 호출하면 NoSuchElementException이 발생한다. 항상 hasMoreTokens()로 확인하거나, countTokens()만큼만 반복해야 한다.전체 메서드 한눈에 보기
| 메서드 | 설명 | 비고 |
|---|---|---|
hasMoreTokens() |
남은 토큰이 있으면 true | while 조건으로 사용 |
nextToken() |
다음 토큰 반환 | 없으면 NoSuchElementException |
nextToken(delim) |
구분자를 새로 바꿔서 다음 토큰 반환 | 이후 호출에도 새 구분자 유지 |
countTokens() |
남은 토큰 개수 반환 | nextToken() 호출 시마다 감소 |
3 split()과의 비교
가장 헷갈리기 쉬운 차이는 빈 토큰 처리다. 구분자가 연속으로 나오거나 문자열이 구분자로 시작하면 두 방식의 결과가 달라진다.
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 스타일) | 배열로 한 번에 반환 |
4 실전 활용
BufferedReader와 조합 (입력 파싱)
코딩테스트에서 가장 자주 쓰는 형태다. Scanner보다 훨씬 빠르기 때문에 입력량이 많은 문제에서는 이 조합이 표준이다.
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로 주면 별도 처리 없이 숫자와 연산자가 번갈아 담긴 리스트를 바로 만들 수 있다.
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) - 완전탐색
글에서 확인할 수 있다.
| 잘못된 내용이 있다면 지적부탁드립니다. 방문해주셔서 감사합니다. |

'Java > Java' 카테고리의 다른 글
| [Java] Collections.sort() 완벽 정리 — Comparable vs Comparator (0) | 2026.03.06 |
|---|---|
| [Java] StringBuilder와 StringBuffer 사용법 (0) | 2026.01.16 |
| [Java/알고리즘] 시간복잡도 계산 (0) | 2026.01.10 |
| [Java/알고리즘] 비트 연산자 사용법 (1) | 2026.01.02 |
| [Java] LocalTime , LocalDate의 타입변환 (0) | 2025.12.17 |
