想象一个java.io.File
对象的序列。该序列不按任何特定顺序排列,它在目录遍历后填充。文件的名称可以如下所示:
/some/file.bin
/some/other_file_x1.bin
/some/other_file_x2.bin
/some/other_file_x3.bin
/some/other_file_x4.bin
/some/other_file_x5.bin
...
/some/x_file_part1.bin
/some/x_file_part2.bin
/some/x_file_part3.bin
/some/x_file_part4.bin
/some/x_file_part5.bin
...
/some/x_file_part10.bin
基本上,我可以有 3 种类型的文件。第一种类型是简单的,它只有一个.bin
扩展名。第二种类型的文件是从_x1.bin
到_x5.bin
形成的文件。第三种类型的文件可以由 10 个较小的部分组成,从 _part1
到 _part10
.我知道命名可能很奇怪,但这是我必须处理的:)
我想将文件分组在一起(文件的所有部分应该一起处理),我正在考虑使用并行数组来执行此操作。我不确定的是我如何执行减少/累积部分,因为所有线程都将在同一个数组上工作。
val allBinFiles = allBins.toArray // array of java.io.File
我正在考虑处理这样的事情:
val mapAcumulator = java.util.Collections.synchronizedMap[String,ListBuffer[File]](new java.util.HashMap[String,ListBuffer[File]]())
allBinFiles.par.foreach { file =>
file match {
// for something like /some/x_file_x4.bin nameTillPart will be /some/x_file
case ComposedOf5Name(nameTillPart) => {
mapAcumulator.getOrElseUpdate(nameTillPart,new ListBuffer[File]()) += file
}
case ComposedOf10Name(nameTillPart) => {
mapAcumulator.getOrElseUpdate(nameTillPart,new ListBuffer[File]()) += file
}
// simple file, without any pieces
case _ => {
mapAcumulator.getOrElseUpdate(file.toString,new ListBuffer[File]()) += file
}
}
}
我正在考虑像上面的代码中所示的那样这样做。具有文件的提取器,并使用部分路径作为映射中的键。例如,/some/x_file
可以保存为/some/x_file_x1.bin
/some/x_file_x5.bin
的值。我也认为可能有更好的方法来解决这个问题。我会对你的意见感兴趣。
另一种方法是使用 groupBy
:
val mp = allBinFiles.par.groupBy {
case ComposedOf5Name(x) => x
case ComposedOf10Name(x) => x
case f => f.toString
}
这将返回文件并行数组的并行映射(ParMap[String, ParArray[File]]
)。如果要从这一点开始获得文件的顺序映射:
val sqmp = mp.map(_.seq).seq
为了确保并行性启动,请确保并行阵列 (10k+) 中有足够的元素。