자바에서의 입력은 Scanner 클래스나, BufferedReader 클래스를 사용해 받는다.
하지만 백준같은 곳에서 알고리즘을 풀다보면 Scanner를 사용했을 때는 시간초과가 나지만 BufferedReader 를 사용했을 때는 통과가 되는 경험을 하게 될 것이다.
Scanner 와 BufferedReader의 속도둘의 속도가 차이나는 이유는 buffer의 사용 여부 때문인데, 여기서 버퍼란 무엇일까?
버퍼(buffer)란, 데이터가 전송될 때, 일시적으로 저장되는 메모리 영역이다.
Scanner 는 1KB의 버퍼를 갖기 때문에 입력이 바로 전달되지만, BufferedReader는 8KB의 버퍼를 가져 입력을 저장했다가 한번에 전송하기 때문에 더 빠르다.
그리고 Scanner 는 입력을 읽는 과정에서 내부에서 정규 표현식 적용, 입력값 분학, 파싱 과정 등을 거치기 때문에 속도 면에서 BufferedReader가 유리할 수 밖에 없다.
// Scanner
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
}
}
// BufferedReader
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();
}
}
백준님의 블로그 글을 보면 각 언어의 입력 속도 비교한 표가 있는데, Java의
Scanner과BufferedReader는 각각 평균 4.8448초와 0.6585초로 상당히 큰 차이가 있음을 확인할 수 있다.
위의 두 클래스 모두 System.in 을 매개변수로 받고있다. 아래의 System 클래스를 살펴보자.
public final class System{
public static final InputStream in = null;
...
}
in 은 System 클래스에 존재하는 InputStream 타입의 정적변수이다. InputStream 은 바이트 단위 입력을 받기 위한 최상위 입력 스트림 클래스이다. 따라서 System.in 을 매개변수로 사용하기 때문에 사용자의 키보드 입력을 받을 수 있다.
그런데 둘을 비교해보면 BufferedReader에 Scanner에는 없는 throws IOException이 붙어있는 것을 볼 수 있다.
Scanner는 System.in을 생성할 때 내부에서 try~catch를 사용해 예외처리를 해주기 때문에 우리가 명시적으로 예외 처리를 해줄 필요는 없지만 BufferedReader는 예외처리를 반드시 해줘야 한다.
BufferedReader은 매개변수로 InputStreamReader를 사용하는데, InputStreamReader는 무엇일까?
InputStreamReader란, 문자 입력 스트림의 한 종류로 입력 값을 자바 응용 프로그램으로 전달하는 객체이다. 자바 응용 프로그램은 입력장치로부터 직접 데이터를 읽지 않고 입력 스트림을 통해 데이터를 얻는다.
즉, 입출력 장치와 자바 응용프로그램을 연결하는 통로 역할이라고 보면 될 것 같다.