我目前正在使用split()
扫描一个文件,其中每行都有由 . 分隔的字符串数'~'
。我在某个地方读到了Scanner
可以更好地处理长文件的地方,性能方面,所以我想检查一下。
我的问题是:我是否必须创建两个实例Scanner
?也就是说,一个读取一行,另一个基于该行获取分隔符的标记?如果我必须这样做,我怀疑我是否会从使用它中获得任何好处。也许我在这里遗漏了一些东西?
我目前正在使用split()
扫描一个文件,其中每行都有由 . 分隔的字符串数'~'
。我在某个地方读到了Scanner
可以更好地处理长文件的地方,性能方面,所以我想检查一下。
我的问题是:我是否必须创建两个实例Scanner
?也就是说,一个读取一行,另一个基于该行获取分隔符的标记?如果我必须这样做,我怀疑我是否会从使用它中获得任何好处。也许我在这里遗漏了一些东西?
在单线程模型中围绕这些指标做了一些指标,这是我得到的结果。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ 分词器 | String.Split() | 而+子字符串 | 扫描仪 | ScannerWithCompiledPattern ~ ~ 4.0 毫秒 | 5.1 毫秒 | 1.2 毫秒 | 0.5 毫秒 | 0.1 毫秒 ~ ~ 4.4 毫秒 | 4.8 毫秒 | 1.1 毫秒 | 0.1 毫秒 | 0.1 毫秒 ~ ~ 3.5 毫秒 | 4.7 毫秒 | 1.2 毫秒 | 0.1 毫秒 | 0.1 毫秒 ~ ~ 3.5 毫秒 | 4.7 毫秒 | 1.1 毫秒 | 0.1 毫秒 | 0.1 毫秒 ~ ~ 3.5 毫秒 | 4.7 毫秒 | 1.1 毫秒 | 0.1 毫秒 | 0.1 毫秒 ~ ____________________________________________________________________________________________________________
结果是 Scanner 提供了最好的性能,现在需要在多线程模式下进行评估!我的一位资深人士说,Tokenizer 会产生 CPU 峰值,而 String.split 不会。
对于处理线,您可以使用扫描仪,对于从每条线获取令牌,您可以使用拆分。
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();
}
您可以使用该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)
,则每次都会重新编译正则表达式。(扫描器在第一次编译它们时会自动缓存所有正则表达式。)如果你这样做,我不希望看到性能上有太大差异。
我会说split()
是最快的,并且对于你正在做的事情可能已经足够好了。它没有那么灵活scanner
。StringTokenizer
已弃用,仅可用于向后兼容,因此请不要使用它。
编辑:您总是可以测试这两种实现,看看哪个更快。我很好奇自己是否scanner
可以比split()
. 对于给定的大小,拆分可能会更快 VS Scanner
,但我不能确定这一点。
您实际上并不需要正则表达式,因为您在固定字符串上进行拆分。Apache StringUtils
split对纯字符串进行拆分。
对于大容量拆分,拆分是瓶颈,而不是说文件 IO,我发现这比String.split()
. 但是,我没有针对已编译的正则表达式对其进行测试。
Guava 也有一个拆分器,以更面向对象的方式实现,但我发现它比 StringUtils 大容量拆分慢得多。