백준에서 입력 속도 테스트를 했을 때 BufferedReader 로 입력을 받으면 0.6585s가 걸리고, Scanner로 입력을 받으면 4.8448s가 걸립니다. 왜 이렇게 속도 차이가 나는지 알아보았습니다.

Scanner

사용법

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // System.in을 입력 스트림으로 하는 Scanner 생성
        Scanner scanner = new Scanner(System.in);

        // 사용자로부터 입력받기
        System.out.println("Enter some text:");
        while (scanner.hasNext()) {
            String input = scanner.next();
            System.out.println("You entered: " + input);
        }

        // Scanner 닫기
        scanner.close();
    }
}

내부

...
/**
 * Constructs a new {@code Scanner} that produces values scanned
 * from the specified input stream. Bytes from the stream are converted
 * into characters using the
 * {@linkplain Charset#defaultCharset() default charset}.
 *
 * @param  source An input stream to be scanned
 * @see Charset#defaultCharset()
 */
public Scanner(InputStream source) {
    this(new InputStreamReader(source), WHITESPACE_PATTERN);
}
...

특징

java.util 패키지에 속한 클래스로 입력을 바로 int, short, float, String 등으로 바로 변환하여 읽을 수 있습니다. 또한, 버퍼 크기가 1KB으로 키보드의 입력 작업(I/O)이 발생할 때마다 Scanner로 바로 전달됩니다. Scanner로 전달한 값을 읽는 동안 내부에서 정규 표현식 적용, 입력값 분할, 파싱 과정 등을 거칩니다. 이 특징 때문에 Scanner가 BufferedReader보다 더 느린 성능을 가지게 된 것입니다.

더해서, System.in을 파라미터로 Scanner 생성 시 내부에서 try-catch를 하고 클래스 생성자에서 InputStreamReader를 생성하여 사용하기 때문에 개발자가 직접 해당 작업들을 처리하지 않아도 됩니다.

System.in : 사용자(키보드) 입력 받을 수 있게 하는 정적 변수, 바이트 스트림(InputStream) 형태로 입력값을 읽습니다.

 

BufferedReader

사용법

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class SimpleBufferedReaderExample {
    public static void main(String[] args) {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

        System.out.println("Enter a line of text:");

        try {
            String inputLine = bufferedReader.readLine();

            System.out.println("You entered: " + inputLine);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // BufferedReader 닫기
                bufferedReader.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

내부

...
/**
 * Creates a buffering character-input stream that uses a default-sized
 * input buffer.
 *
 * @param  in   A Reader
 */
public BufferedReader(Reader in) {
    this(in, defaultCharBufferSize);
}
...

특징

java.io 패키지에 속한 클래스로 데이터를 파싱하지 않고 String 으로 값을 받습니다. 또한 버퍼 크기가 8KB이며 키보드의 입력이 있을 때마다 한 문자씩 버퍼로 전송합니다. 버퍼가 가득 차거나 개행 문자가 나타나면 버퍼의 내용을 한 번에 전송하는 방식으로 Scanner보다 I/O 작업이 줄어들기 때문에 성능이 더 좋습니다. 내부적으로 처리된 것이 없기 때문에 개발자가 직접 IOException 처리와 InputStreamReader를 생성하여 매개변수로 전달해줘야 사용 가능합니다.

동기화가 가능하며 Thread Safe하다는 특징을 가집니다.

InputStreamReader: 입력 장치(키보드 등)으로부터 받은 입력 값을 자바 응용 프로그램으로 전달하는 객체, 바이트 스트림(InputStream) 을 문자 스트림(Reader)로 로 변환해주는 브릿지(bridge) 클래스입니다.

 

참고

https://dlee0129.tistory.com/238

'java|spring' 카테고리의 다른 글

JDK, JRE, JVM  (0) 2024.07.16

+ Recent posts