2011-12-21 20 views
1

我有我想排序并合并到输出文件中的已排序的csv文件的列表。用复杂的比较合并多个已排序的csv文件

我不想做一个简单的字符串比较,但比较据此来的,我对每一个值类型,例如地图:

有一行:
1,15/12/2011年,大卫Raiven,纽约

在类型映射我有这样的:第一列 - 长,二线日期,三串,...

所以比较应该相应比较值。

我怎样才能以最高的效率做到这一点?
PriorityQueue? TreeMap的?

我不喜欢使用第三方库或分拣机。
输入文件是巨大的。

+0

它是每个csv中的相同格式吗?您是否需要保持每条记录的连贯性,还是应该将“名称”列独立于“城市”列进行排序? – Sheriff 2011-12-21 16:44:52

+0

是每个csv都是相同的格式。reagardin列的比较:比较第一列,如果它在第二行有相同的值移动到第二列,如果它相同再次移动到第三列,依此类推。 每次您比较列的对。 – omrid 2011-12-21 16:50:04

回答

1

为每个CSV文件创建一个Readers/InputStreams数组(或者,如果您愿意,还可以使用Collection)。

与@JustinKSU想法类似,创建一个TreeMap,其中的关键字是CSV文件中的一行。传递一个自定义比较器,你的自定义impl按long,sort等排序。值是数组/集合中哪个文件的索引(可能是一个Integer,可能是文件名,如果你的Collection是一个Map)。

通过读取每个文件的第一行来播种TreeMap。

使用TreeMap.pollFirstEntry()删除最下面一行,并将键(行)写入Writer/OutputStream。使用该值从适当的文件中读取更多行(检查EOF)并将其添加到TreeMap中。

重复直到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

如果您想在内存中完成所有操作,我会推荐一个TreeSet传入您的Comparitor。这将是最简单的实现。如果你不能将它全部存储在内存中,你可以打开InputStreams到所有的文件,并循环遍历每一个文件,直到你确定了“最低”值并输出到你的新文件。

+0

以及这是我想要做的,这就是为什么我问这个问题......我不能将它加载到内存中,所有文件的总大小约4GB – omrid 2011-12-21 17:03:36

0

其中一个可能有点不正统的选择是使用一个即时数据库,例如HSQLDB。在临时目录中的某个地方打开一个有足够空间的数据库,创建包含所需字段的表格,插入所有CSV文件中的所有记录,最后使用适当的ORDER BY子句从所有记录中进行选择,以反映所需的排序顺序并保存你想要的结果。当然,这需要一些磁盘空间,但这是我过去使用过的类似问题的可能解决方案。

+0

谢谢,但我要求不要使用任何第三方库 – omrid 2011-12-21 17:16:12