web-dev-qa-db-ja.com

STDINを1行ずつ読み取るための最速の方法は?

STDINを1行ずつ読み取る最も時間効率の良い方法を探しています。

最初の行は、テストする条件の数です。以下のすべての行は、最大100 000文字の条件(文字列)です。

私はすでに次のことを試しました(4回、90 000文字の結果:

  • Whileループ付きスキャナー(7255 ms)

    Scanner sc = new Scanner(System.in);
    int numberOfLines = Integer.parseInt(sc.nextLine());
    long start = 0;
    int i = 1;
    while (i<=numberOfLines){
        start = System.currentTimeMillis();
        sc.nextLine();
        Debug.println((System.currentTimeMillis()-start) + "ms for scanner while");
        i++;
    }
    
    • 結果 :
      1. スキャナーで3228ms
      2. スキャナー用2264ms
      3. スキャナーで1309ms
      4. スキャナーで454ms
  • Forループ付きスキャナー(7078 ms)

    Scanner sc = new Scanner(System.in);
    int numberOfLines = Integer.parseInt(sc.nextLine());
    long start = 0;
    for (int i = 1; i<= numberOfLines;i++){
        start = System.currentTimeMillis();
        sc.nextLine();
        Debug.println((System.currentTimeMillis()-start) + "ms for scanner for");
        //i++;     
    }
    
    • 結果 :
      1. スキャナー用3168ms
      2. スキャナー用2207ms
      3. スキャナー用1236ms
      4. スキャナー用467ms
  • Forループ付きのBufferedReader(7403ミリ秒)

    try {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    int numberOfLines = Integer.parseInt(br.readLine());
    long start = 0;
    for (int i = 0; i< numberOfLines;i++){
        start = System.currentTimeMillis();
        br.readLine();
        Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader for");
        //i++;
    }
     } catch (Exception e) {
    System.err.println("Error:" + e.getMessage());
    

    }

    • 結果 :
      1. バッファリーダーの3273ms
      2. バッファリーダーの2330ms
      3. バッファリーダーの1293ms
      4. バッファリーダーの507ms
  • Whileループを備えたBufferedReader(7461 ms)

    try {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    int numberOfLines = Integer.parseInt(br.readLine());
    int i=0;
    long start = 0;
    while(i< numberOfLines){
        start = System.currentTimeMillis();
        br.readLine();
        Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader while");
        i++;
    }
     } catch (Exception e) {
    System.err.println("Error:" + e.getMessage());
    

    }

    • 結果 :
      1. バッファリーダーの場合は3296ms
      2. バッファリーダーの2358ms
      3. バッファリーダーの場合は1307ms
      4. バッファリーダーで500ミリ秒

かかった時間をデバッグしているときに、読み取りごとに時間がかかっていることに気付きました。初期化されるバイトを制限することは可能ですか(例:最大100.000文字の場合、scanner/bufferedreaderを初期化するのは100 000文字のみに制限します。読み取り後、次の100 000文字でそれ自体を補充する必要があります)

この問題に関するアイデアは大歓迎です。

編集:各シナリオのコードを、1行の読み取りにかかった時間とともに追加しました。また、読みやすくするために100.000を100 000に変更しました。

20

BufferedReader#readLineソース。私が見るいくつかの問題があります:

  1. StringBuilderではなくStringBufferを使用するため、同期のオーバーヘッドが発生します。
  2. また、データコピーのオーバーヘッドがあるようです-完全にはわからないので、チェックしてみてください。
  3. BufferedReaderの専用モニターオブジェクトと、さらに多くの同期オーバーヘッド。

次の2つのことでチャンスをつかむことができます。

  1. 独自のバッファリングを記述すると、データの二重コピーの時間を節約できます。
  2. StringBuilderを使用して、単純なサイクルでソースデータを調べる独自のnextLineメソッドを作成します。
5
Andrei LED