시작하며


 Java에서는 흔히들 출력을 할 때, java.util 패키지에 있는 Scanner 클래스를 import하여 Scanner sc = new Scanner(System.in); 형식으로 출력을 하도록 배운다. 하지만, 위의 방식보다 java.io 패키지에서 BufferedReader클래스를 import하여 사용하는 것이 속도면에서 우월하다는 것을 알게 되었고 그에 대해 정리해보고자 한다.



들어가며


  • Scanner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Scanner;
 
public class prac1 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
 
        int a = sc.nextInt();
        float b = sc.nextFloat();
        String str = sc.next();
        String strWithSpace = sc.nextLine();        //공백을 포함
 
        sc.close();
 
        System.out.println(a);
        System.out.println(b);
        System.out.println(str);
        System.out.println(strWithSpace);
    }
}
 

cs


  • BufferedReader


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.*;
 
public class prac1 {
    public static void main(String[] args){
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
 
        OutputStreamWriter osw = new OutputStreamWriter(System.out);
        BufferedWriter bw = new BufferedWriter(osw);
 
        try {
            String str = br.readLine();     //입력
 
            bw.write(str);                  //출력
            bw.flush();
            bw.close();
 
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
cs


  위의 두 가지 코드의 차이에 대해서 알아보자.

 

우선, 코드상에서 보이는 가장 큰 차이는 

  • InputStreamReader를 인자로 갖는 BufferedReader
  • try/catch문의 유무이다.


1. InputStreamReader는 입력을 character로 받아오기 때문에 줄단위의 문자열을 입력으로 받아올 떄 불편한 점이 생기고, 이에 따라서 BufferedReader가 생겨나 함께 쓰이기 시작했다.

BufferedReader는 이런 InputStreamReader에 버퍼 기능을 추가한 것인데, 데이터를 한 번에 읽어서 버퍼에 보관시킨 후에 사용자의 요청에 따라 버퍼에서 읽어오게 된다.


2. BufferedReader는 throws Exception을 선언해주어야만 에러없이 사용할 수 있다.


장단점 비교를 하자면


Scanner의 장점은 쓰기 간략하고 편하다(?)를 생각할 수 있겠고, 단점은 속도가 BufferedReader보다 느리다.

BufferedReader의 장점은 Scanner에 비해 처리속도가 빠르다는 것이고, 단점은 InputStreamReader클래스와 BufferedReader클래스 두 가지를 불러오며 try/catch문으로 써야해서 Scanner보다 불편할 수 있다는 것이다.


이렇게 장단점만 비교한다면 Scanner가 하기쉽고 편해서 좋아보이지만


<백준 알고리즘 1000번 문제를 풀었을 때>


<출처 : algospot>


위의 사진들을 보면 알 수 있듯이 시간이 상당히 절약되는 것을 쉽게 알 수 있다.


왜 이러한 결과가 나타나는 걸까?

 

 그 이유는 Scanner는 Regex(Regular Expression)을 많이 사용하여 알아서 Tokenizing과 Parsing을 해주기 때문에 패턴을 분석하는 데에 있어서 시간을 많이 잡아먹기 때문인데, Regex를 이용하면 패턴을 이용해 문자열을 좀 더 세밀히 분석할 수 있다고 한다.



끝마치며

 알고리즘 문제를 풀다보면 str.toString()을 이용해 문자열에 문자를 추가하는 방법과 StringBuilder를 이용해 append로 붙이는 방법처럼 메모리나 시간을 절약해서 풀어야하는 경우가 많았고, 실제로 협업해서 코드를 진행할 때 위와 같은 요소들을 항상 체크하고 서로의 약속으로 만드는 경우가 많았다. 이처럼 항상 메모리와 런타임 시간을 고려하면서 푸는것이 앞으로를 위해 도움이 될 것 같다.


(※위의 toString()과 StringBuilder의 append의 차이에 대한 코드는 추후 작성 예정입니다.)

+ Recent posts