Java的Scanner vs String.split()vs StringTokenizer;我该用哪个?

时间:2009-04-10 03:49:47

标签: java regex split java.util.scanner

我目前正在使用split()来扫描一个文件,其中每一行都有'~'分隔的字符串数。我在某处读到Scanner可以用一个长文件做得更好,性能方面,所以我想考虑一下。

我的问题是:我是否必须创建Scanner的两个实例?也就是说,一个读取一行而另一个基于该行来获取分隔符的标记?如果我必须这样做,我怀疑我是否会从使用它中获得任何好处。也许我在这里错过了什么?

5 个答案:

答案 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()速度最快,可能对你正在做的事情足够好。它的灵活性不如scannerStringTokenizer已弃用,仅可用于向后兼容,因此请勿使用它。

编辑:你总是可以测试两种实现,看看哪一种更快。如果scanner可能比split()更快,我很好奇。对于给定大小VS Scanner,拆分可能会更快,但我无法确定。

答案 4 :(得分:2)

这里你实际上并不需要正则表达式,因为你正在分裂一个固定的字符串。 Apache StringUtils split会在普通字符串上进行拆分。

对于高分割,分割是瓶颈,而不是说文件IO,我发现它比String.split()快10倍。但是,我没有针对已编译的正则表达式进行测试。

Guava还有一个分离器,以更多的OO方式实现,但我发现它比StringUtils显着慢于高音量分割。