2016-10-24 11 views
1

私は次の形式のテキストファイルを持っています。各行は文字列で始まり、一連の数字が続きます。各行の長さは不明です(未知数、0〜1000)。ファイルを読み込んで各行を解析する効果的な方法

string_1 3 90 12 0 3 
string_2 49 0 12 94 13 8 38 1 95 3 
....... 
string_n 9 43 

その後私は2つの引数を受け入れるhandleLine方法で各行を処理する必要があります:文字列の名前と設定番号(以下のコードを参照してください)。

handleLineでファイルを読み取り、各行を効率的に処理する方法は?

私の回避策:java8と線で

  1. 読むファイルの行はFiles.linesをストリーミングします。 ブロックしていますか?
  2. スプリット正規表現と各ライン
  3. ヘッダー文字列に変換各行と数字

私はそれはかなりuneffectiveによる第二と第三のステップだと思うのセット。最初のステップは、Javaがファイルバイトを文字列に変換してから2番目と3番目のステップに変換して、String/Set<Integer>に変換することを意味します。 パフォーマンスには大きな影響がありますか?はいの場合 - よりうまくいく方法?あなたの最初の質問については

public handleFile(String filePath) { 
    try (Stream<String> stream = Files.lines(Paths.get(filePath))) { 
     stream.forEach(this::indexLine); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private void handleLine(String line) { 
    List<String> resultList = this.parse(line); 
    String string_i = resultList.remove(0); 
    Set<Integer> numbers = resultList.stream().map(Integer::valueOf).collect(Collectors.toSet()); 
    handleLine(string_i, numbers); // Here is te final computation which must to be done only with string_i & numbers arguments 
} 

private List<String> parse(String str) { 
    List<String> output = new LinkedList<String>(); 
    Matcher match = Pattern.compile("[0-9]+|[a-z]+|[A-Z]+").matcher(str); 
    while (match.find()) { 
     output.add(match.group()); 
    } 
    return output; 
} 
+1

だけの提案として、多分私が思うに、このメソッドの外Pattern.compileを移動します各行に同じパターンをコンパイルする必要はありません。 – eg04lt3r

答えて

3

、それはあなたがStreamを参照する方法によって異なります。 Streamsは本質的に怠惰で、使用しない場合は動作しません。たとえば、Files.linesへの呼び出しでは、Streamに端末操作を追加するまで、ファイルを実際に読み取ることはありません。

Javaのドキュメントから:

ストリームとしてファイルからすべての行を読んでください。 readAllLinesとは異なり、このメソッドは、リストにすべての行を読んで、代わりにストリームが

を消費するようforEach(Consumer<T>)呼び出しは、端末操作で、かつ、その時点で、ファイルの行が読み込まれいい加減に移入していませんあなたのindexLineメソッドに渡されます。

他のコメントについては、実際にはここで質問はありません。あなたは何を測定しようとしていますか?何かが複数のステップであるからといって、本質的にパフォーマンスが悪くなるわけではありません。 Fileバイトを直接String & Setに変換するwizbangオンライナーを作成したとしても、おそらく中間マッピングを匿名で実行したか、それともコンパイラが実行するように呼び出されたことでしょう。ここで

1

は名前と番号

stream.forEach(line -> { 
    String[] split = line.split("\\b"); //split with blank seperator 
    Set<String> numbers = IntStream.range(1, split.length) 
           .mapToObj(index -> split[index]) 
           .filter(str -> str.matches("\\d+")) //filter numbers 
           .collect(Collectors.toSet()); 
    handleLine(split[0], numbers); 
}); 

それとも別の方法

Map<Boolean, List<String>> collect = Pattern.compile("\\b") 
              .splitAsStream(line) 
              .filter(str -> !str.matches("\\b")) 
              .collect(Collectors.groupingBy(str -> str.matches("\\d+"))); 
handleLine(collect.get(Boolean.FALSE).get(0), collect.get(Boolean.TRUE)); 
1

に行を解析するために、あなたのコードは、私がこの問題に取り掛かると最高としての性能を測定するために、いくつかの方法をテストするために設定しています私は注意を引いた条件の下でできた。ここで添付の結果と一緒に、私がテストしたものを、私はそれをテスト方法は次のとおりです。

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.util.ArrayList; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Random; 
import java.util.Scanner; 
import java.util.Set; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 
import java.util.stream.Stream; 

public class App { 

    public static void method1(String testFile) { 
     List<Integer> nums = null; 
     try (Scanner s = new Scanner(Paths.get(testFile))) { 
      while (s.hasNext()) { 
       if (s.hasNextInt()) 
        nums.add(s.nextInt()); 
       else { 
        nums = new ArrayList<Integer>(); 
        String pre = s.next(); 
        // handleLine(s.next() ... nums ...); 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method2(String testFile) { 
     List<Integer> nums = null; 
     try (BufferedReader in = new BufferedReader(new FileReader(testFile)); 
       Scanner s = new Scanner(in)) { 
      while (s.hasNext()) { 
       if (s.hasNextInt()) 
        nums.add(s.nextInt()); 
       else { 
        nums = new ArrayList<Integer>(); 
        String pre = s.next(); 
        // handleLine(s.next() ... nums ...); 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method3(String testFile) { 
     List<Integer> nums = null; 
     try (BufferedReader br = new BufferedReader(new FileReader(testFile))) { 
      String line = null; 
      while ((line = br.readLine()) != null) { 
       String[] arr = line.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.valueOf(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method3_1(String testFile) { 
     List<Integer> nums = null; 
     try (BufferedReader br = new BufferedReader(new FileReader(testFile))) { 
      String line = null; 
      while ((line = br.readLine()) != null) { 
       String[] arr = line.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.parseInt(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method4(String testFile) { 
     List<Integer> nums = null; 
     try { 
      List<String> lines = Files.readAllLines(Paths.get(testFile)); 
      for (String s : lines) { 
       String[] arr = s.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.valueOf(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method4_1(String testFile) { 
     List<Integer> nums = null; 
     try { 
      List<String> lines = Files.readAllLines(Paths.get(testFile)); 
      for (String s : lines) { 
       String[] arr = s.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.parseInt(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method5(String testFile) { 
     List<Integer> nums = null; 
     try (BufferedReader br = Files.newBufferedReader(Paths.get(testFile))) { 
      List<String> lines = br.lines().collect(Collectors.toList()); 
      for (String s : lines) { 
       String[] arr = s.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.valueOf(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method5_1(String testFile) { 
     List<Integer> nums = null; 
     try (BufferedReader br = Files.newBufferedReader(Paths.get(testFile))) { 
      List<String> lines = br.lines().collect(Collectors.toList()); 
      for (String s : lines) { 
       String[] arr = s.split(" "); 
       nums = new ArrayList<Integer>(); 
       for (int i = 1; i < arr.length; ++i) 
        nums.add(Integer.parseInt(arr[i])); 
       // handleLine(...); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void method6(String testFile) { 
     List<Integer> nums = new LinkedList<Integer>(); 
     try (Stream<String> stream = Files.lines(Paths.get(testFile))) { 
      stream.forEach(line -> { 
       String[] split = line.split("\\b"); // split with blank seperator 
       Set<String> numbers = IntStream.range(1, split.length) 
         .mapToObj(index -> split[index]) 
         .filter(str -> str.matches("\\d+")) // filter numbers 
         .collect(Collectors.toSet()); 
       numbers.forEach((k) -> nums.add(Integer.parseInt(k))); 
       // handleLine(...); 
      }); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) throws Exception { 

     args = new String[] { "C:\\Users\\Nick\\Desktop\\test.txt" }; 

     Random r = new Random(); 

     System.out.println("warming up a little..."); 
     for (int i = 0; i < 100000; ++i) { 
      int x = r.nextInt(); 
     } 

     long s1 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method1(args[0]); 
     long e1 = System.currentTimeMillis(); 

     long s2 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method2(args[0]); 
     long e2 = System.currentTimeMillis(); 

     long s3 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method3(args[0]); 
     long e3 = System.currentTimeMillis(); 

     long s3_1 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method3_1(args[0]); 
     long e3_1 = System.currentTimeMillis(); 

     long s4 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method4(args[0]); 
     long e4 = System.currentTimeMillis(); 

     long s4_1 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method4_1(args[0]); 
     long e4_1 = System.currentTimeMillis(); 

     long s5 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method5(args[0]); 
     long e5 = System.currentTimeMillis(); 

     long s5_1 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method5_1(args[0]); 
     long e5_1 = System.currentTimeMillis(); 

     long s6 = System.currentTimeMillis(); 
     for (int i = 0; i < 10000; ++i) 
      method6(args[0]); 
     long e6 = System.currentTimeMillis(); 

     System.out.println("method 1 = " + (e1 - s1) + " ms"); 
     System.out.println("method 2 = " + (e2 - s2) + " ms"); 
     System.out.println("method 3 = " + (e3 - s3) + " ms"); 
     System.out.println("method 3_1 = " + (e3_1 - s3_1) + " ms"); 
     System.out.println("method 4 = " + (e4 - s4) + " ms"); 
     System.out.println("method 4_1 = " + (e4_1 - s4_1) + " ms"); 
     System.out.println("method 5 = " + (e5 - s5) + " ms"); 
     System.out.println("method 5_1 = " + (e5_1 - s5_1) + " ms"); 
     System.out.println("method 6 = " + (e6 - s6) + " ms"); 
    } 
} 
  • =のjava.versionで使用さ1.8.0_101(Oracle
  • のx64 OS /プロセッサ

結果出力:

warming up a little... 
method 1 = 1103 ms 
method 2 = 872 ms 
method 3 = 440 ms 
method 3_1 = 418 ms 
method 4 = 413 ms 
method 4_1 = 376 ms 
method 5 = 439 ms 
method 5_1 = 384 ms 
method 6 = 646 ms 

私が理解しているように、テストしたサンプルの中で最良のアプローチはFiles.readAllLines,s.split(" ")およびInteger.parseIntである。これらの3つの組み合わせは、私が作成してテストしたサンプルのうち、見かけ上最も速いを生成しました。少なくとも、幾分助けになるようにInteger.parseIntに変更してください。

注ソースを使用して、いくつかのアプローチを得て、この問題/例に適用しました。例えば。 this blog postthis tutorial、そしてこの素晴らしい人は@Peter-Lawreyです。また、さらに改善を行うことができます

また、test.txtというファイル:

my_name 15 00 29 101 1234 
cool_id 11 00 01 10 010101 
longer_id_name 1234 
dynamic_er 1 2 3 4 5 6 7 8 9 10 11 12 123 1456 15689 555555555 

は(注:パフォーマンスは大幅にファイルのサイズによって異なる場合があります)

+0

かなり便利なテスト、ありがとう! –

関連する問題