2011-12-21 7 views
1

ソートして出力ファイルにマージするソート済みのcsvファイルのリストがあります。複雑な比較を伴う複数ソートされたcsvファイルのマージ

私は、文字列の単純な比較をしたいが、私はすべての値を持っているタイプ、例えばのマップに応じて比較していない:行の

ワン:
1、15/12/2011、デビッドRaiven、ニューヨーク私はこれを持っている型マップで

:最初の列 - 長い間、2次日、三弦、...

は、コンパレータは、それに応じて値を比較する必要があります。

私はどのようにして効率を上げることができますか?
PriorityQueue? TreeMap?

サードパーティのライブラリやソーターを使用しないことをおすすめします。
入力ファイルが膨大です。

+0

各csvで同じ形式ですか?そして、あなたは一貫性を保つために各レコードを必要としますか、 'Name'カラムを' City'カラムとは別にソートする必要がありますか? – Sheriff

+0

はい各CSVの同じ形式。2番目の列に同じ値を持つ場合は最初の列を比較し、2番目の列に移動した場合は3番目の列に移動します。 列のペアを比較するたびに – omrid

答えて

1

各CSVファイルに1つのリーダ/入力ストリームの配列(または必要に応じてコレクション)を作成します。

@JustinKSUアイデアと同様に、キーがCSVファイルの1行であるTreeMapを作成します。カスタムComparator、long、Dateなどで並べ替えるカスタムimplを渡します。値は、配列/ Collection内のファイルのインデックス(おそらくInteger、コレクションがMapの場合はファイル名になります)です。

各ファイルから最初の行を読み取って、ツリーマップをシードします。

TreeMap.pollFirstEntry()を使用して一番下の行を削除し、キー(行)をWriter/OutputStreamに書き込みます。値を使用して、適切なファイルからもう1行を読み込み(EOFをチェック)、それをツリーマップに追加します。

TreeMapが空になるまで繰り返します。すべてを閉じます。編集

- 追加されたソースコード

ノート、これだけ作品以下の入力ファイルがすでにをソートされている場合は! (質問に指定されたとおり)

public void mergeSort(File[] inFiles, File outFile, Comparator<String> comparator) throws IOException { 

     try { 
     BufferedReader[] readers = new BufferedReader[inFiles.length]; 
     PrintWriter writer = new PrintWriter(outFile); 
     TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>(
       comparator); 

     // read first line of each file. We don't check for EOF here, probably should 
     for (int i = 0; i < inFiles.length; i++) { 
      readers[i] = new BufferedReader(new FileReader(inFiles[i])); 
      String line = readers[i].readLine(); 
      treeMap.put(line, Integer.valueOf(i)); 
     } 

     while (!treeMap.isEmpty()) { 
      Map.Entry<String, Integer> nextToGo = treeMap.pollFirstEntry(); 
      int fileIndex = nextToGo.getValue().intValue(); 
      writer.println(nextToGo.getKey()); 

      String line = readers[fileIndex].readLine(); 
      if (line != null) 
       treeMap.put(line, Integer.valueOf(fileIndex)); 
     } 
     } 
     finally { 
     // close everything here... 
     } 
    } 
0

メモリ内ですべてを実行したい場合は、ComparitorでTreeSetを渡すことをお勧めします。それが最も簡単な実装です。すべてをメモリに保存できない場合は、すべてのファイルにInputStreamを開き、 "最も低い"値を判断して新しいファイルに出力するまで、各ファイルをループすることができます。

+0

これは私がやりたいことです。なぜこの質問をしたのですか...そして、私はそれをメモリにロードすることができません。すべてのファイルの合計サイズは約4GBです。 – omrid

0

1つ、おそらく少し非正統的なオプションは、例えばHSQLDBのようなオンザフライのデータベースを使用することです。十分なスペースがあるtempディレクトリのどこかにデータベースを開き、必要なフィールドを持つテーブルを作成し、すべてのCSVファイルからすべてのレコードを挿入し、最後に適切な並べ替え順序を反映した適切なORDER BY節を持つすべてのレコードから選択します。結果はあなたが欲しいところです。もちろん、これには少しのディスク容量が必要ですが、それは私が過去に同様の問題に使用した解決策です。

+0

ありがとうございます。しかし、サードパーティのライブラリ – omrid

関連する問題