2017-09-18 5 views
2

버퍼링 된 리더는 사용자로부터 값을 입력하는 경우 스캐너 클래스보다 훨씬 빠르지 만 알고리즘 경쟁의 대부분 또는 인터뷰의 경우 단일 입력 행에 여러 정수가있는 경우가 많습니다. 따라서,이 스캐너 클래스를 사용하기 쉽게된다 - (가 readInt 옵션이 없습니다로) 버퍼 리더의 경우Java의 한 줄에 여러 정수를 사용하는 경우 스캐너 클래스 대신 BufferedReader를 사용하는 것이 가장 좋습니까?

Scanner in=new Scanner(System.in); 
    int a=in.nextInt(); 
    int b=in.nextInt(); 

먼저 입력 라인을해야합니다 다음 정수의 수에 따라 라인을 구문 분석 가에 -

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    int a,b; 
    String line = br.readLine(); 
    String[] strs = line.trim().split("\\s+"); 
    a=Integer.parseInt(strs[0]); 
    b=Integer.parseInt(strs[1]); 

입력은 구문 분석 indiviual 정수로 얻은 문자열을 분할하기 위해 많은 시간을 차지하지 않습니다, 후자의 경우에 더 빠를 수 있지만? 따라서 이러한 경우 중 하나가 더 빠르거나 빠릅니까?

감사합니다.

+1

실제로 차이를 감지 할 수 있다면 완전히 다른 문제가 발생할 수 있습니다. – Fildor

+0

가장 빠른 방법은 바이트 블록을 배열로 읽어서 각 바이트를 반복하고 문자 시퀀스를 정수 값으로 수동 변환하는 것입니다. 이렇게하면 문자열 객체를 할당하고 split()을 호출하거나 regexes를 사용하지 않아도됩니다. – Nayuki

+0

스택 오버 플로우에 익숙하지 않아서 더 많은 답변을 기다려야 할 수도 있습니다. 감사합니다. – user8321763

답변

3

매우 잘못된 접근 방식 : 사용자 입력에 대해 이야기하고 있습니다. 상관 없어요. 당신은 인간 시간 규모로 제공되는 것을 처리합니다.

인간은 "밀리 초"의 일부 시나리오에서 "초"로 작동합니다. 검사기 및 성능면에서의 BufferedReader 간의 델타 반면

마이크로초, 어쩌면 나노초의 범위 아마도.

그리고 심지어 우리가 콘솔 (그러나 cat somefile | java Whatever처럼 배관 사용)에 대한 함량의 인간 입력에 대해 이야기하지 않을 때 - 당신은 여전히 ​​IO이 대규모로 일어나고있다. 응용 프로그램은 IO가 발생하기까지 99.99 %의 시간을 소비합니다. 결국 들어오는 문자열이 어떻게 처리되는지는 중요하지 않습니다. 즉

: 당신이 더 잘 인간 독자들에게 이해하기 쉬운 정직하게 일을 얻을 수 깨끗한 코드를 작성하는 시간을 보냈다. JIT가 마술을하도록하십시오.

질문은 구체적으로 "파일 기반"입력 처리에 관한 것이므로 프로필으로 이동하십시오. 내가 여기 어떻게 할 것인지 :

  • 가 다른 구현
  • 사이에 나에게 쉽게 스위치가 그때 벤치 마크에 다른 솔루션을 시작하는 것입니다 수있는 추상화 계층을 생성 (주의 등을 준비하기 위해 this 읽기 활동) 당신이 볼

, 결국 코드의 모두 조각은 매우 을 할 것입니다 비슷한 가지.스캐너가 여전히 에서 작동하고 있으므로 스캐너 파싱과 BufferedReader 읽기 + 수동 파싱의 잠재적 차이점을 이해하기 위해 해당 소스 코드를 파헤쳐 야합니다.

+0

질문은 프로그래밍 경쟁에서 테스트 사례와 같이 텍스트 파일에서 입력 한 것일 수 있다고 제안했습니다. – Nayuki

+0

@Nayuki 그 부분을 해결하기 위해 내 대답을 다시 고쳤습니다. – GhostCat

+1

예, 저는 당신이하는 말의 의미를 완전히 이해합니다. 그러나, 내 문제는 인간의 입력에 대한 것이 아니라 이미 설계된 코드 컴파일러 및 테스트 케이스에 대한 것입니다. 예제에서 두 개의 정수를 사용했지만 코드 테스터 중 일부가 사용하는 테스트 케이스는 최대 10^5 개까지 입력 할 수 있습니다. 또한 이러한 시나리오에서 허용되는 실행 시간은 약 1 초 또는 그 이하입니다. 10^5 크기의 문자열 배열로 나누고 각 값을 정수로 파싱하려면 약 10^5 개의 정수가 포함 된 문자열을 나누는 것이 중요합니다. – user8321763

3

코드 선명도가 속도보다 중요한 경우 중 하나입니다.

코드 Scanner을 사용하는 코드가 무슨 일이 벌어지는 지점까지 곤란 해지는 것을 쉽게 볼 수 있으며 매우 자연스럽게 읽습니다.

BufferedReader을 사용하는 코드는 수행해야 할 작업 (입력에서 두 개의 정수 읽기)을하기 전에 몇 가지 추가 작업을 수행하므로 코드 판독기가 몇 초 동안 무슨 일이 일어나는지 볼 수 있습니다 .

물론 두 구현에서 일부 오류 처리 코드가 누락되었습니다. 예를 들어 두 번째 구현에서는 split이 정확히 두 항목을 반환했는지 확인해야합니다. 첫 번째 구현에서 모든 오류 검사를 생략하면 호출자는 입력에 정수가 없다는 메시지를 받게됩니다. 두 번째 구현은 범위를 벗어난 인덱스를 얻게 될 것이고, 이는 계속 진행되고있는 것을보기 위해 추가 조사가 필요합니다.

파싱이 진행되는 한, 두 경우 모두에서 발생해야하므로 처리하는 데 동일한 CPU주기를 소비하게됩니다.