코테 문제를 풀다보면 다음과 같은 입력 방식이 많이 보인다.
260000
4
20000 5
30000 2
10000 6
5000 8
위의 입력 형식을 살펴보면 처음 2줄은 총 결과 값과 for문을 돌릴 조건을 주고 그 아래에는 공백으로 구분된 입력 값이 들어오는 것을 확인 할 수 있다.
처음 구현할 때에는 Split 메서드를 이용하여 ArrayList에 String 배열 형태로 집어 넣고 꺼내쓰는 방식을 사용하였다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
T = Integer.parseInt(br.readLine());
ArrayList<String[]> arr = new ArrayList<>();
for(int i = 0;i<T;i++){
arr.add(br.readLine().split(" "));
}
int result = 0;
for(String[] num : arr){
result = Integer.parseInt(num[0]) + Integer.parseInt(num[1]);
System.out.println(result);
}
그런데 다른 사람이 만든 코드를 보다보니 StringTokenizer를 이용하여 다른 형태로 저장하여 사용할 수 있는 것을 발견하였다.
그럼 StringTokenizer가 뭔지부터 알아보자.
ChatGPT에게 StringTokenizer에 대해 질의를 해보았다.
StringTokenizer 클래스는 Java에서 문자열을 지정한 구분자(delimiter)를 기준으로 토큰(token)으로 분리하는 데 사용되는 유용한 클래스입니다. 주로 CSV 파일과 같이 구분자로 구분된 문자열을 처리하거나, 텍스트 파싱에 활용됩니다.
StringTokenizer 클래스는 java.util 패키지에 속해 있으며, 아래와 같은 생성자와 메서드를 제공합니다:
생성자:
- StringTokenizer(String str, String delim): 문자열 str을 지정한 구분자 delim로 토큰으로 분리합니다.
- StringTokenizer(String str, String delim, boolean returnDelims): returnDelims 매개변수를 통해 구분자도 토큰으로 포함할지 여부를 결정합니다.
주요 메서드:
- boolean hasMoreTokens(): 더 이상 토큰이 없는지 여부를 반환합니다.
- String nextToken(): 다음 토큰을 반환하고 커서를 다음 토큰으로 이동시킵니다.
- String nextToken(String delim): 다음 토큰을 반환하며, 지정한 delim을 구분자로 사용합니다.
- int countTokens(): 남아 있는 토큰의 갯수를 반환합니다.
아래는 StringTokenizer의 간단한 사용 예제입니다:
import java.util.StringTokenizer; public class StringTokenizerExample { public static void main(String[] args) { String text = "apple,banana,cherry,date"; StringTokenizer tokenizer = new StringTokenizer(text, ","); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); System.out.println("토큰: " + token); } } }
위 예제에서는 ,를 구분자로 사용하여 문자열을 토큰으로 분리하고 출력합니다. 실행 결과로 "토큰: apple", "토큰: banana", "토큰: cherry", "토큰: date"와 같은 출력이 될 것입니다.
위의 설명을 보면 여러 문자열이 들어왔을 때 해당 문자열을 구분자에 따라 잘라 하나하나를 토큰 형태로 저장하고 nextToken() 메서드를 이용하여 그 값을 받아서 이용할 수 있다.
이러면 굳이 배열을 사용할 것 없이 입력된 문자열을 순서대로 사용 할 수 있게 되는 것!
그래서 Split이랑 차이가 뭐야????
여러가지 차이가 있겠지만 가장 큰 차이는 리턴하는 타입의 형식에 있다.
StringTokenizer는 받은 문자열을 스스로 잘라 토큰 형태로 저장하기 때문에 리턴시에도 각 구분자로 잘린 토큰을 문자열 형태로 반환한다.
하지만 Split의 경우, 문자열 배열의 형태로 반환하게 된다. 바꿔 말하면, StringTokenizer는 전체 토큰을 보기 위해서는 반복문을 사용하여 하나하나 토큰을 뽑아내야 한다는 말이다.
또한, StringTokenizer는 위에서 언급 되었듯이 java.util에 포함되어 있는 클래스지만, Split은 String 클래스에 속해있는 메서드 이다.
아예 개념 자체가 다른 친구들이라 이 말이다.
또다른 소소한 차이가 있는데
- StringTokenizer는 빈 문자열을 토큰으로 인식하지 않지만, Split은 빈 문자열이 들어온다.
예를 들어서 "haha..haha.haha" 라는 문자열이 있을때, '.'으로 잘라낸다면 StringTokenizer는 [haha],[haha],[haha]로 들어오겠지만 Split은 [haha],[ ],[haha],[haha]로 들어오게 된다.
- StringTokenizer는 문자 혹은 문자열이 구분자이지만, Split은 정규표현식이 구분자이다.
이 말이 무엇이냐... 결론적으로 StringTokenizer는 복잡한 문자열 처리는 어렵다는 이야기이다.
예를 들어, VarcharC2K@tistory.com 이라는 url을 @와 .을 이용하여 VarcharC2K,tistory,com으로잘라낸다고 하자.
이 경우, Split은 정규식 표현을 사용하여 여러 데이터를 한번에 처리할 수 있지만, StringTokenizer는 문자 혹은 문자열을 구분자로 사용하기에 그렇게 자를 수 없다.
결론은
StringTokenizer는 복잡한 문자열 처리가 어렵다. 그런 경우, split 메서드를 이용하여 배열 형태로 받아 처리하는 것이 훨씬 효율적이다. 하지만, 단일 구분자를 사용하여 데이터가 날아오는 csv와 같은 파일의 처리라 던지, 간단한 문자열의 처리는 split 메서드를 이용하는 것 보다 StringTokenizer를 이용하는 것이 더 효율적이다. 앞서 설명하였듯, 문자열로 바로 리턴하기에 컨트롤 하기도 편리하고 토큰으로 잘라서 일부만 보관하는 형식이라 메모리 효율도 더 좋기 때문이다.
두 개의 처리 방식을 잘 비교해 보며 필요한 상황에서 더 효율적인 것을 선택하면 될 것이다.
'JAVA > 입출력' 카테고리의 다른 글
BufferedWriter - 출력을 보다 빠르게! (0) | 2023.08.09 |
---|