我目前正在使用split()
来扫描一个文件,其中每一行都有'~'
分隔的字符串数。我在某处读到Scanner
可以用一个长文件做得更好,性能方面,所以我想考虑一下。
我的问题是:我是否必须创建Scanner
的两个实例?也就是说,一个读取一行而另一个基于该行来获取分隔符的标记?如果我必须这样做,我怀疑我是否会从使用它中获得任何好处。也许我在这里错过了什么?
答案 0 :(得分:8)
在单线程模型中有一些关于这些的指标,这是我得到的结果。
~~~~~~~~~~~~~~~~~~Time Metrics~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ Tokenizer | String.Split() | while+SubString | Scanner | ScannerWithCompiledPattern ~ ~ 4.0 ms | 5.1 ms | 1.2 ms | 0.5 ms | 0.1 ms ~ ~ 4.4 ms | 4.8 ms | 1.1 ms | 0.1 ms | 0.1 ms ~ ~ 3.5 ms | 4.7 ms | 1.2 ms | 0.1 ms | 0.1 ms ~ ~ 3.5 ms | 4.7 ms | 1.1 ms | 0.1 ms | 0.1 ms ~ ~ 3.5 ms | 4.7 ms | 1.1 ms | 0.1 ms | 0.1 ms ~ ____________________________________________________________________________________________________________
出来的是Scanner提供了最佳性能,现在同样需要在多线程模式下进行评估!我的一位大四学生说Tokenizer给出CPU峰值而String.split没有。
答案 1 :(得分:6)
对于处理线,您可以使用扫描仪,并从每行获取令牌,您可以使用拆分。
Scanner scanner = new Scanner(new File(loc));
try {
while ( scanner.hasNextLine() ){
String[] tokens = scanner.nextLine().split("~");
// do the processing for tokens here
}
}
finally {
scanner.close();
}
答案 2 :(得分:5)
您可以使用useDelimiter("~")
方法让您使用hasNext()/next()
遍历每行上的令牌,同时仍然使用hasNextLine()/nextLine()
来迭代这些行。
编辑:如果你要进行性能比较,你应该在进行split()测试时预编译正则表达式:
Pattern splitRegex = Pattern.compile("~");
while ((line = bufferedReader.readLine()) != null)
{
String[] tokens = splitRegex.split(line);
// etc.
}
如果您使用String#split(String regex)
,则每次都会重新编译正则表达式。 (扫描程序在第一次编译它们时会自动缓存所有正则表达式。)如果你这样做,我不希望看到性能上有太大差异。
答案 3 :(得分:3)
我会说split()
速度最快,可能对你正在做的事情足够好。它的灵活性不如scanner
。 StringTokenizer
已弃用,仅可用于向后兼容,因此请勿使用它。
编辑:你总是可以测试两种实现,看看哪一种更快。如果scanner
可能比split()
更快,我很好奇。对于给定大小VS Scanner
,拆分可能会更快,但我无法确定。
答案 4 :(得分:2)
这里你实际上并不需要正则表达式,因为你正在分裂一个固定的字符串。 Apache StringUtils
split会在普通字符串上进行拆分。
对于高分割,分割是瓶颈,而不是说文件IO,我发现它比String.split()
快10倍。但是,我没有针对已编译的正则表达式进行测试。
Guava还有一个分离器,以更多的OO方式实现,但我发现它比StringUtils显着慢于高音量分割。