그냥 Scanner 사용하면 안 돼?
JAVA를 배울 때 입력 함수로 가장 먼저 배우는 Scanner에 너무 익숙해져서 코딩테스트 문제를 풀 때도 자연스럽게 사용해 왔다.
그런데 인터넷의 문제 답안 코드에서도, 또 주변에서도 코딩테스트 문제를 풀 때는 대부분 Scanner 대신 BufferedReader를 쓰는 것을 볼 수 있었다.
BufferedReader가 뭔데? 그렇게 좋은 거야?
Scanner
// Scanner의 기본 문법
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
Scanner는 문자열에 최적화된 클래스가 아니다.
그에 비해 BufferedReader, StringTokenizer는 문자열 입력에 최적화되어 있어 속도가 빠르다.
예를 들어, 여러 개의 정수를 입력받아야 하는 문제가 있다고 하자.
// 입력값 : 1 2 3 4 5 6 7 8 9 10
for (int i = 0; i < 10; i++) {
scanner.nextInt();
}
Scanner를 통해 입력을 받으면 Enter뿐만 아니라 자동으로 Space를 경계로 인식하기 때문에 입력받은 데이터를 가공하기에 편리하다.
그러나, scanner.nextInt()를 10번 호출해야 하므로 비효율적이다.
만약 입력 개수가 큰 경우 시간 초과가 발생할 수도 있다.
BufferedReader
BufferedReader를 사용할 경우 bf.readLine()를 한 번만 호출해도 된다.
// 입력값 : 1 2 3 4 5 6 7 8 9 10
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] arr = br.readLine().split(" ");
System.out.println(Integer.parseInt(arr[0])); // 1
}
코드가 실행되는 순서는 다음과 같다.
- 입력값 전체를 readLine()을 이용해 문자열로 입력받은 후 split()을 이용해 “ “(공백)을 기준으로 자른다.
- Integer.parseInt()를 이용해 문자열을 정수로 바꾼다.
- main 함수에서 IOException을 이용해 예외 처리를 해 준다.
StringTokenizer
위에서 사용된 split()은 정규식을 이용해 문자열을 자르는 함수이기 때문에 복잡하다.
그에 비해 StringTokenizer의 nextToken()은 단순히 뒤의 문자열이 공백 자리를 당겨 채우는 방식이기 때문에 더욱 효율적이다.
// 입력값 : 1 2 3 4 5 6 7 8 9 10
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
System.out.println(st.nextToken()); // 1
System.out.println(st.nextToken()); // 2
StringTokenizer()의 두 번째 매개변수는 구분자로, “/,”와 같이 문자를 이어 붙여 여러 개 사용도 가능하다.
StringTokenizer의 주로 사용되는 메서드
메서드명 | 설명 |
hasMoreTokens() | 남아 있는 토큰이 있는지 boolean 값으로 반환 (while을 이용해 전체 요소를 출력할 수 있다.) |
nextToken() | 다음 토큰을 문자열로 반환 |
countTokens() | 사용하지 않고 남아 있는 토큰 개수 반환 |
코딩테스트를 풀 때, 좀 더 효율적인 클래스 & 메서드가 있다면 공부하여 적극적으로 사용해보려는 노력을 할 필요가 있다.