시작하며
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); } } |
- 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의 차이에 대한 코드는 추후 작성 예정입니다.)
'알고리즘 공부 > 알고리즘 지식' 카테고리의 다른 글
Integer.valueOf()와 Integer.parseInt()의 차이 (0) | 2018.11.13 |
---|