Java';s Scanner vs String.split()vs StringTokenizer;我应该用哪一种?

Java';s Scanner vs String.split()vs StringTokenizer;我应该用哪一种?,java,regex,split,java.util.scanner,Java,Regex,Split,Java.util.scanner,我目前正在使用split()扫描一个文件,其中每行都有由“~”分隔的字符串数。我在某个地方读到,Scanner可以更好地处理一个长文件,从性能角度来看,所以我考虑签出它 我的问题是:我是否必须创建两个扫描仪的实例?也就是说,一个读取一行,另一个基于该行获取分隔符的标记?如果我必须这样做,我怀疑我是否会从使用它中获得任何好处。也许我在这里遗漏了什么?我想说split()是最快的,而且对于您正在做的事情来说可能已经足够好了。但它不如扫描仪灵活StringTokenizer已被弃用,仅用于向后兼容,因

我目前正在使用
split()
扫描一个文件,其中每行都有由
“~”分隔的字符串数。我在某个地方读到,
Scanner
可以更好地处理一个长文件,从性能角度来看,所以我考虑签出它

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

我想说
split()
是最快的,而且对于您正在做的事情来说可能已经足够好了。但它不如
扫描仪
灵活
StringTokenizer
已被弃用,仅用于向后兼容,因此不要使用它


编辑:您总是可以测试这两种实现,看看哪一种更快。我自己也很好奇,
扫描器
是否能比
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()测试时应预编译正则表达式:


如果使用
String#split(String regex)
,每次都会重新编译regex。(Scanner在第一次编译时会自动缓存所有正则表达式。)如果这样做,我不希望在性能上看到太大的差异。

这里实际上不需要正则表达式,因为您是在固定字符串上拆分的。Apache
StringUtils
对普通字符串进行拆分

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


Guava还有一个拆分器,它是以一种更面向对象的方式实现的,但是我发现对于高容量拆分,它比StringUtils要慢得多

在一个单线程模型中围绕这些问题做了一些度量,下面是我得到的结果

~~~~~~~~~~~~~~~~~~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 ~ ____________________________________________________________________________________________________________ ~~~~~~~~~~~~~~~~~~~~~~~~时间度量~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~Tokenizer | String.Split()| while+SubString | Scanner | 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毫秒~ ____________________________________________________________________________________________________________
结果是扫描仪提供了最好的性能,现在同样需要在多线程模式下进行评估!我的一位大四学生说,标记器给出了CPU峰值,而String.split没有。

我同意StringTokenizer可能已弃用,但我在j2se5和java6的弃用类列表中没有找到它。为什么?你是对的,不是。但是从API来看:StringTokenizer是一个遗留类,尽管新代码中不鼓励使用它,但出于兼容性原因保留了它。建议任何寻求此功能的人改用String的split方法或java.util.regex包。 ~~~~~~~~~~~~~~~~~~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 ~ ____________________________________________________________________________________________________________