• 자바 입력 클래스 활용하기 :: 마이구미
    Java 2016. 12. 20. 19:30
    반응형

    이번 글은 자바의 입력 클래스에 대해서 다뤄볼 것이다.

    입력 클래스? 쉽게 말해서 코드를 실행하고 입력하는 부분을 말한다.

    C언어를 보자면 scanf()를 예로 들 수 있겠다.

    자바를 처음 다뤄본다면 알고리즘 문제와 같은 것들을 풀 때 입력을 어떻게 해야할 지 모를 수 있다.

    Scanner를 쓰는 것은 대부분 알고 있을 것이다.

    하지만 백준 알고리즘과 같은 사이트에서 자바의 풀이를 보면 대부분 BufferedReader, StringTokenizer를 많이 볼 수 있다.

    이제부터 그 방법을 알아보고, 어떻게 더 효율적으로 입력할 수 있는 지에 대해 다뤄보자.


    입력 클래스 Scanner, BufferedReader, StringTokenizer 세가지를 살펴보자.

    기본적으론 자바에서 입력을 사용할 때는 Scanner를 많이 사용하고 있다.

    Scanner는 가장 기본적인 입력 클래스이다.

    게다가 제일 최근에 나왔다. 즉, 버전이 낮으면  import가 되지 않을 것이다.


    Scanner sc = new Scanner(System.in);


    int n = sc.nextInt(); // int

    long l = sc.nextLong(); // int

    String s = sc.next(); // String

    String s = sc.nextLine(); // String


    입력이 필요하다면 원하는 타입에 맞게 위와 같이 사용할 수 있다.

    그렇다면 BufferedReader, StringTokenizer는 사용하는 목적이 무엇일까?

    간단하다. 문자열로 활용하기 위해서이다.

    예를 들어보겠다.


    1 2 3 4 5 6 7 8 9 10 11 12 // 한줄 입력


    for(int i=0;i<12;i++) {

    sc.nextInt();

    }


    위와 같이 한줄로 입력을 하라고 했을 때 sc.nextInt()를 12번 호출해주면 된다.

    하지만 입력 부분의 12번에서 1000번 10000번 100000번 커지면 어떻게 될까?

    그만큼 sc.nextInt()를 호출해야한다는 것이다.

    그렇기에 입력갯수가 크다면 알고리즘 문제의 경우에는 시간 제한에 걸리게 된다.

    그리하여 아래와 같이 사용한다.


    1 2 3 4 5 6 7 8 9 10 11 12 // 한줄 입력

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    String[] s = br.readLine().split(" ");


    // s[0] = "1"; Integer.parseInt(s[0]) => 1

    // s[1] = "2";

    // s[2] = "3";

    // .....


    문자열로 받고 split 메소드를 이용해서 공백을 기준으로 잘라서 활용하는 것이다.

    그리고 Integer.parseInt() 형변환을 통해 사용하면 된다.

    근데 사실 Scanner도 nextLine()을 통해 입력받고 split 메소드로 자르면 된다.

    하지만 굳이 BufferedReader를 사용하는 것은 속도가 Scanner보다 빠르기 때문이다.

    빠른 이유는 깊게는 살펴보지 않았지만 BufferedReader는 문자열에 최적화되어 있고, Scanner는 다양한 기능을 지원하기 때문이지 아닐까 싶다.


    그렇다면 StringTokenizer는 어떤 목적으로 사용하는가?

    BufferedReader는 잘라서 배열과 같이 인덱스를 사용하여 접근하여 사용한다.

    이와는 달리 공백이 있다면 뒤에 문자열이 공백을 자리를 땡겨 채워진다.


    BufferedReader br = new BufferedReader(new InputStreamReader(System.in);

    StringTokenizer st = new StringTokenizer(br.readLine());


    // AB CDD EFFF GH 입력


    st.nextToken() // AB

    st.nextToken() // CDD

    st.nextToken() // EFFF

    st.nextToken() // GH


    위와 같이 StringTokenizer를 사용하여 문자열을 활용할 수 있다.

    결국 문자열 잘라서 쓰는건 똑같은 맥락이다.

    그렇다면 본인 마음대로 편한 것을 쓰면 된다?

    그건 아니다. 이유는 StringTokenizer가 BufferedReader보다 빠르게 사용될 수 있다.

    그 이유는 문자열을 자르기 위해서는 split를 사용해야한다.

    split는 정규식을 기반으로 자르는 로직이므로 내부는 복잡하다.

    그에 비해 StringTokenizer의 nextToken() 메소드는 단순히 공백 자리를 땡겨 채우는 것이다.


    그렇기에 속도 차이가 날 수 밖에 없다.

    결론은 경우에 따라 다르다는 것이다.

    정규식이나 인덱스 접근과 같은 처리가 필요없다면 StringTokenizer를 사용하는 것이 효율적이다.


    입력부분은 알고리즘 문제를 풀 때 가장 기본적이고, 당연히 익히고 있어하는 것이다.

    혹시나 시간초과를 경험한 적이 있거나, 남들보다 시간이 더 걸린다면 문자열을 통해 다시 한번 풀어보길 바란다.


    반응형

    댓글

Designed by Tistory.