我正在寻找一些java实现的排序算法。该文件可能是巨大的,比如20000 * 600 = 12,000,000行记录。该行以逗号分隔37个字段,我们使用5个字段作为键。是否有可能快速排序,比如30分钟?
如果你有其他方法而不是java,欢迎它可以很容易地集成到java系统中。例如,unix实用程序。
感谢。
编辑:需要排序的行分为600个文件,每个文件20000行,每个文件4mb。最后,我希望他们成为一个大的排序文件。
我正在尝试对unix进行排序,之后会对其进行更新。
编辑:
我将所有文件都附加到一个大文件中,并尝试了unix排序功能,这非常好。排序2gb文件的时间是12-13分钟。对于600个文件,追加操作需要4分钟。
sort -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r big.txt -o sorted.txt
答案 0 :(得分:2)
调用unix排序程序应为efficient。它会执行多次传递以确保它不是内存耗尽。你可以使用java的Runtime来分叉一个进程,但是进程的输出被重定向,所以你需要一些玩杂耍到get the redirect to work right:
public static void sortInUnix(File fileIn, File sortedFile)
throws IOException, InterruptedException {
String[] cmd = {
"cmd", "/c",
// above should be changed to "sh", "-c" if on Unix system
"sort " + fileIn.getAbsolutePath() + " > "
+ sortedFile.getAbsolutePath() };
Process sortProcess = Runtime.getRuntime().exec(cmd);
// capture error messages (if any)
BufferedReader reader = new BufferedReader(new InputStreamReader(
sortProcess.getErrorStream()));
String outputS = reader.readLine();
while (outputS != null) {
System.err.println(outputS);
outputS = reader.readLine();
}
sortProcess.waitFor();
}
答案 1 :(得分:1)
数据如何以CSV格式显示?它来自关系数据库吗?你可以这样做,无论进程创建什么文件都以正确的顺序写入它的条目,这样你就不必解决这个问题了。
如果你正在做一个简单的词典顺序,你可以尝试使用unix sort
,但我不确定它将如何对具有该大小的文件执行。
答案 2 :(得分:0)
Java Lists can be sorted,您可以尝试从那里开始。
答案 3 :(得分:0)
大型服务器上的Python。
import csv
def sort_key( aRow ):
return aRow['this'], aRow['that'], aRow['the other']
with open('some_file.csv','rb') as source:
rdr= csv.DictReader( source )
data = [ row for row in rdr ]
data.sort( key=sort_key )
fields= rdr.fieldnames
with open('some_file_sorted.csv', 'wb') as target:
wtr= csv.DictWriter( target, fields }
wtr.writerows( data )
这应该相当快。它非常灵活。
在小型机器上,将其分为三遍:装饰,排序,不装饰
装饰:
import csv
def sort_key( aRow ):
return aRow['this'], aRow['that'], aRow['the other']
with open('some_file.csv','rb') as source:
rdr= csv.DictReader( source )
with open('temp.txt','w') as target:
for row in rdr:
target.write( "|".join( map(str,sort_key(row)) ) + "|" + row )
第2部分是使用“|”的操作系统排序作为字段分隔符
去除装饰:
with open('sorted_temp.txt','r') as source:
with open('sorted.csv','w') as target:
for row in rdr:
keys, _, data = row.rpartition('|')
target.write( data )
答案 4 :(得分:0)
好吧,既然你在谈论巨大的数据集,这意味着你无论如何都需要一些外部排序算法。有一些用于java和几乎任何其他语言 - 因为结果必须存储在磁盘上,无论如何你正在使用哪种语言是非常无趣的。
答案 5 :(得分:0)
您没有提及平台,因此很难与指定的时间达成协议。 12x10 ^ 6记录并不多,但排序是一项非常密集的任务。让我们说37个字段,比如说100字节/字段是45GB?这对于大多数机器来说有点多,但如果记录平均为10bytes / field,那么服务器应该能够将整个文件放在RAM中,这是理想的。
我的建议:将文件分成可用RAM的1/2,对每个块进行排序,然后对生成的排序块进行合并排序。这使你可以在内存中进行所有排序,而不是点击交换,这是我怀疑导致任何减速。
Say(1G块,在你可以玩的目录中):
split --line-bytes=1000000000 original_file chunk
for each in chunk*
do
sort $each > $each.sorted
done
sort -m chunk*.sorted > original_file.sorted
答案 6 :(得分:0)
正如您所提到的,您的数据集非常庞大。根据您的机器,一次性对它进行排序将非常耗时(如果您尝试使用QuickSort)。 但是因为你希望它能在30分钟内完成。我建议你看看Map Reduce使用 Apache Hadoop作为您的应用程序服务器。
请记住,这不是一种简单的方法,但从长远来看,您可以根据数据大小轻松扩展。 我还指出了Hadoop setup
上的一个很好的链接通过单节点设置工作并移至Hadoop集群。 如果你被困在任何地方,我会很乐意帮助你。
答案 7 :(得分:0)
你确实需要确保你有适合工作的工具。 (今天,我希望得到一台带有24 GB内存的3.8 GHz电脑供家庭使用。我买了一个新玩具已经有一段时间了。)
但是,如果要对这些行进行排序并且没有足够的硬件,则不需要分解数据,因为它已经在600个文件中。
单独对每个文件进行排序,然后进行600次合并排序(您只需要在内存中保留600行)这不像一次完成所有这些简单,但您可以在手机上进行。 ;)
答案 8 :(得分:0)
由于您有600个较小的文件,因此同时对所有文件进行排序可能会更快。这将耗尽100%的CPU。这就是重点吗?
waitlist=
for f in ${SOURCE}/*
do
sort -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r -o ${f}.srt ${f} &
waitlist="$waitlist $!"
done
wait $waitlist
LIST=`echo $SOURCE/*.srt`
sort --merge -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r -o sorted.txt ${LIST}
这将同时对600个小文件进行排序,然后合并已排序的文件。它可能比尝试对单个大文件进行排序更快。
答案 9 :(得分:0)
使用Map / Reduce Hadoop进行排序..我推荐Spring Data Hadoop。 Java的。
答案 10 :(得分:0)
使用已发布到Maven Central的Java库big-sorter,它对commons-csv具有可选的依赖性,以进行CSV处理。它通过分割为中间文件,对中间文件进行排序并合并来处理任何大小的文件。
这是一个例子:
鉴于下面的CSV文件,我们将在第二列(“数字”列)上进行排序:
name,number,cost
WIPER BLADE,35,12.55
ALLEN KEY 5MM,27,3.80
Serializer<CSVRecord> serializer = Serializer.csv(
CSVFormat.DEFAULT
.withFirstRecordAsHeader()
.withRecordSeparator("\n"),
StandardCharsets.UTF_8);
Comparator<CSVRecord> comparator = (x, y) -> {
int a = Integer.parseInt(x.get("number"));
int b = Integer.parseInt(y.get("number"));
return Integer.compare(a, b);
};
Sorter
.serializer(serializer)
.comparator(comparator)
.input(inputFile)
.output(outputFile)
.sort();
结果是:
name,number,cost
ALLEN KEY 5MM,27,3.80
WIPER BLADE,35,12.55
我创建了一个1200万行37列的CSV文件,并在网格中填充了0到100,000之间的随机整数。然后,我使用 big-sorter 在第11列上对2.7GB文件进行了排序,花了 8分钟在具有SSD和最大堆设置为512m的i7上进行单线程处理(-Xmx512m
)。
有关更多详细信息,请参见项目README。