본문

StringTokenizer

반응형

# StringTokenizer


StringTokenizer는 긴 문자열을 지정된 구분자(delimiter)를 기준으로 토큰(token)이라는 여러 개의작은 문자열로 잘라내는 데 사용된다. 예를 들어 "100,200,300,400"라는 문자열이 있을 때 ','를 구분자로 잘라내면 "100", "200", "300", "400"이라는 4개의 문자열(토큰)을 얻을 수 있다.


StringTokenizer를 이용하는 방법 이외에도 String의split(String regex)를 사용해서
String[] result = "100,200,300,400".split(",");과 같이 하거나
Scanner(String source)와 Scanner useDelimiter(String pattern)를 사용해서
Scanner sc2 = new Scanner("100,200,300,400").useDelimiter(",");과 같이 할 수도 있지만
이 두 가지 방법은 정규식 표현(Regular expression)을 사용해야하므로
정규식 표현에 익숙하지 않은 경우 StringTokenizer를 사용하는 것이 간단하면서도 명확한 결과를 얻을 수 있을 것이다.

그러나 StringTokenizer는 구분자로 단 하나의 문자 밖에 사용하지 못하기 때문에
보다 복잡한 형태의구분자로 문자열을 나누어야 할 때
Scannersplit메서드를 사용해야 할 것
이다.


','를 구분자로 하는 StringTokenizer를 생성해서 문자열(source)을 나누어 출력하는 예제이다.

Source 01) TokenEx01.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package tokenEx;
 
import java.util.StringTokenizer;
 
public class TokenEx01 {
 
    public static void main(String[] args) {
        String source = "100,200,300,400";
        StringTokenizer st = new StringTokenizer(source, ",");
 
        while (st.hasMoreElements()) {
            System.out.println(st.nextToken());
        }
    }
}
cs

Result)

1
2
3
4
100
200
300
400
cs


Source 02) TokenEx02.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package tokenEx;
 
import java.util.StringTokenizer;
 
public class TokenEx02 {
 
    public static void main(String[] args) {
        String expression = "x=100*(200+300)/2";
 
        /*
         * 생성자 StringTokenizer(String str, String delim, boolean returnDelims)를
         * 사용해서 구분자로 토큰을 간주되도록 하였다. 구분자로여러 문자들을 지정한 것을 눈여겨보자. StringToken은 단
         * 한문자의 구분자만 사용할 수 있기 때문에 "+-=()" 전체가 하나의 구분자가 아니라 각각의 문자가 모두 구분자라는 것에 주의해야한다.
         * 만일 반드시 두 문자 이상의 구분자를 사용해야 한다면, Scanner나 String클래스의 split메서드를 사용해야한다.
         */
        StringTokenizer st = new StringTokenizer(expression, "+-*/=()"true);
 
        while (st.hasMoreTokens()) {
            System.out.println(st.nextToken());
        }
    }
}
cs

Result)
1
2
3
4
5
6
7
8
9
10
11
x
=
100
*
(
200
+
300
)
/
2
cs



문자열에 포함된 데이터가 두 가지 종류의 구분자로 나뉘어져 있을 때, 
두 개의 StringTokenizer와 이중 반복문을 사용해서 처리하는 방법을 보여주는 예제이다.
한 학생의 정보를 구분하기위해 "|"를 사용하였고, 학생의 이름과 점수 등을 구분하기 위해 ","를 사용하였다.

Source 03) 
TokenEx03.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package tokenEx;
 
import java.util.StringTokenizer;
 
public class TokenEx03 {
 
    public static void main(String[] args) {
        String source = "1,임승한,100,100,100|2,홍길동,95,80,80|3,아무개,70,90,90";
        StringTokenizer st = new StringTokenizer(source, "|");
 
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
 
            StringTokenizer st2 = new StringTokenizer(token, ",");
            while (st2.hasMoreElements()) {
                System.out.println(st2.nextToken());
            }
 
            System.out.println("-----");
        }
    }
}
cs

Result)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
임승한
100
100
100
-----
2
홍길동
95
80
80
-----
3
아무개
70
90
90
-----
cs


한글로 된 숫자를 아라비아 숫자로 변환하는 예제이다.
Source 04) TokenEx04.java
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package tokenEx;
 
import java.util.StringTokenizer;
 
public class TokenEx04 {
 
    public static void main(String[] args) {
        String input = "삼십만삼천백십오";
 
        System.out.println(input);
        System.out.println(hangulToNum(input));
    }
 
    // 한글로 숫자롤 변경하는 메서드
    private static long hangulToNum(String input) {
        long result = 0;
        long tmpResult = 0;
        long num = 0;
 
        final String NUMBER = "영일이삼사오육칠팔구";
        final String UNIT = "십백천만억조";
        final long[] UNIT_NUM = { 10100100010000, (long) Math.pow(108), (long) Math.pow(1012) };
 
        StringTokenizer st = new StringTokenizer(input, UNIT, true);
 
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            // 숫자인지,단위(UNIT)인지 확인한다.
            int check = NUMBER.indexOf(token);
 
            if (check == -1) { // 단위인 경우
                if ("만억조".indexOf(token) == -1) {
/*
     * "만삼천"과 같이 숫자 없이 바로 단위로 시작하는 경우에는 num의 값이 0이기 때문에 단위의 값을 곱해도 그
     * 결과가 0이므로 삼항 연산자를 이용해서 num의값을 1로 바꾼 후 단위값을 곱하도록 하였다.
 */
                    tmpResult += (num != 0 ? num : 1* UNIT_NUM[UNIT.indexOf(token)];
                } else {
/*
                     * "만역조"와 같이 큰 단위가 나오면 tmpResult에 저장된 값에 큰 단위 값을 곱해서 result에
                     * 저장하고 tmpResult는 0으로 초기화 한다. 예를 들어 "삼십만"은 tmpResult에 저장되어
                     * 있던 30에 10000을 곱해서 result에 저장하고, tmpResult는 0으로 초기화 한다.
                     */
                    tmpResult += num;
                    result += (tmpResult != 0 ? tmpResult : 1* UNIT_NUM[UNIT.indexOf(token)];
                    tmpResult = 0;
                }
                num = 0;
            } else { // 숫자인 경우
                num = check;
            }
        }
 
        return result + tmpResult + num;
    }
 
}
cs

Result)
1
2
삼십만삼천백십오
303115
cs

tmpResult는 "만억조"와 같은 큰 단위가 나오기 전까지"십백천"단위의값을 저장하기위한 임시공간이고 
result는 실제 결과 값을 저장하기 위한 공간이라는 것을 알아두자.
한글로 된 숫자를 구분자(단위)로 잘라서, 토큰이 숫자면 num에 저장하고 단위면 num에다 단위(UNIT_NUM배열 중의 한 값)를 곱해서tmpResult에 저장한다. 예를 들어 "삼십"이면 3*10이 되어 30이 tmpResult에 저장된다.


# Stirng클래스의split()과 StringTokenizer의 비교

Source 01) TokenEx05.java
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
package tokenEx;
 
import java.util.StringTokenizer;
 
public class TokenEx05 {
 
    public static void main(String[] args) {
        String data = "100,,,200,300";
 
        String[] result = data.split(",");
        StringTokenizer st = new StringTokenizer(data, ",");
 
        for (int i = 0; i < result.length; i++) {
            System.out.print(result[i] + "|");
        }
 
        System.out.println("개수 : " + result.length);
 
        int i = 0;
        for (; st.hasMoreTokens(); i++) {
            System.out.print(st.nextToken() + "|");
        }
 
        System.out.println("개수 : " + i);
    }
}
cs

Result)
1
2
100|||200|300|개수 : 5                <-- split() 사용결과
100|200|300|개수 : 3                   <-- StringTokenizer 사용결과
cs


실행결과를 보면, split()은 빈 문자열도 토큰으로 인식하는 반면
StringTokenizer는 빈 문자열을 토큰으로 인식하지 않기때문에 인식하는 토큰 개수가 서로 다른 것을 알 수 있다.
이 외에도 성능의 차이가 있는데, split()은 데이터를 토큰으로 잘라낸 결과를 배열에 달아서 반환하기 때문에
데이터를 토큰으로 바로바로 잘라서 반환하는
StringTokenizer보다 성능이 떨어질 수 밖에 없다.
그러나 데이터의 양이 많은 경우가 아니라면 별 문제가 되지 않으므로 크게 신경쓸 부분은 아니다.



출처 및 참고자료 : JAVA의정석(남궁성 저)


반응형

공유

댓글