흔히 자바에서 입력값을 처리하기 위한 용도로 Scanner를 사용한다.
// 해설참조 : sehyeok.tistory.com
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int i = sc.nextInt(); // int형 입력받기
double d = sc.nextDouble(); // double형 입력받기
Long l = sc.nextLong(); // long형 입력받기
String text = sc.nextLine(); // String형(문자열) 입력받기
Boolean b = sc.nextBoolean(); // Boolean형 입력받기
sc.close();
}
}
이외에도 short, float, byte, bigInteger 등 다양한 자료형의 입력기능을 제공한다.
하지만 Scanner를 사용하여 백준 문제를 풀다 보니, 시간 초과 등의 에러가 자주 발생하는 것을 볼 수 있었다.
다른사람들의 풀이를 보니 BufferedReader를 사용하여 문제를 해결하는것을 볼 수 있었고,
Scanner와 BufferedReader 의 차이가 무엇인지 궁금해서 알아보았다.
Scanner (java.util.Scanner)
- 공백(띄어쓰기) 및 개행(줄 바꿈)을 기준으로 읽는다.(' ', '\t', '\r', '\n' 등)
- 원하는 타입으로 읽을 수 있다.
- 버퍼의 사이즈가 1024byte(1KB) 이다.
- UnChecked(Runtime) Exception으로 별도로 예외 처리를 명시할 필요가 없다.
- Thread unsafe 성질을 지니기에 멀티스레드 환경에서 문제가 발생할 수 있다.
- 데이터를 입력받을 경우 즉시 사용자에게 전송되며 입력받을 때마다 전송되어야 하기에 많은 시간이 소요된다.
BufferedReader(java.io.BufferedReader)
- 데이터를 파싱하지 않고 String으로만 읽고 가져온다.
- 버퍼의 사이즈가 8192byte(8KB)이다.
- Checked Exception으로 반드시 예외 처리를 명시해야한다.(I/O Exception을 throw하거나 try/catch 해야한다.)
- Thread safe 성질을 지니기에 멀티스레드 환경에서도 안전하다.
- 버퍼가 가득차거나 개행문자가 나타나면 버퍼의 내용을 한번에 프로그램으로 전달하기에 Scanner보다 소요되는 시간을 절약할 수 있다.
버퍼를 사용하여 버퍼안의 내용을 한번에 전달하는 점이 주요한 차이점인데, 이것이 얼마나 속도에 영향을 끼치는지 확인해보자.
백준에서 제공한 입력 속도 비교 표인데, 6위에 BufferedReader 약 0.65초, 17위에 Scanner 약 4.84초를 기록하는 것을 알 수 있다. 적은 숫자를 입력받을 경우에는 이보다는 차이가 줄어들겠지만, 그래도 유의미한 차이를 보여준다.
이제 BufferedReader의 사용방법을 알아보자.
// 해설참조 : sehyeok.tistory.com
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine(); // String형 입력받기
int i = Integer.parseInt(br.readLine()); // int형 입력받기
long l = Long.parseLong(br.readLine()); // long형 입력받기
br.close();
}
}
BufferedReader의 특징에서 알아보았듯이, 반드시 예외 처리를 명시해야한다.
(I/O Exception을 throw하거나 try/catch 해야한다.)
또한, 버퍼를 통해 한번에 전달되는 값은 문자열 형태로 전달되므로, 이를 정수형, 실수형 등으로 파싱해주는 작업이 필요하다.
Scanner와 BufferedReader의 버퍼 사이즈가 1KB, 8KB로 차이가 나기 때문에 일단은 BufferedReader가 큰 메모리를 차지하게 된다. 다만 Scanner가 입력 하나하나마다 데이터를 전달해주는 과정을 거치므로, 많은 입력이 있을 수록 BufferedReader가 좋은 메모리 효율을 보여준다.
상황에 따라 Scanner와 BufferedReader를 적절히 사용하는것이 좋겠지만, 속도 차이가 영향을 주게 되는 경우나 많은 입력이 요구되는 문제에서는 BufferedReader를 이용해 효율적인 코드를 작성하는 것이 좋을듯 하다.
'Java > 개념정리' 카테고리의 다른 글
[Java] HashSet 에 대해 알아보자 (78) | 2023.10.30 |
---|---|
[Java] 배열 정렬하기 (Arrays.sort(), Collections.reverseOrder() 사용) (39) | 2023.10.30 |
[Java] 문자열 분리 (split, StringTokenizer 사용법) (88) | 2023.10.27 |
Java 용어 정리 (0) | 2020.12.15 |