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

Posted

技术标签:

【中文标题】Java 的 Scanner vs String.split() vs StringTokenizer;我应该使用哪个?【英文标题】:Java's Scanner vs String.split() vs StringTokenizer; which should I use? 【发布时间】:2010-10-18 17:02:23 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

在单线程模型中围绕这些指标做了一些指标,这是我得到的结果。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ 分词器 | 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 不会。

【讨论】:

【参考方案2】:

对于处理行,您可以使用扫描仪,对于从每行获取令牌,您可以使用拆分。

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();

【讨论】:

【参考方案3】:

您可以使用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),则每次都会重新编译正则表达式。 (扫描器在第一次编译它们时会自动缓存所有正则表达式。)如果你这样做,我不希望看到性能上有太大差异。

【讨论】:

【参考方案4】:

我会说split() 是最快的,并且对于您正在做的事情可能已经足够了。虽然它不如scanner 灵活。 StringTokenizer 已弃用,仅用于向后兼容,因此请勿使用。

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

【讨论】:

我同意 StringTokenizer 可能已被弃用,但我没有在 j2se5 和 java6 的弃用类列表中找到它。为什么? 你是对的,它不是。但从 API 来看:StringTokenizer 是一个遗留类,出于兼容性原因而保留,尽管不鼓励在新代码中使用它。建议任何寻求此功能的人使用 String 的 split 方法或 java.util.regex 包。【参考方案5】:

您实际上并不需要正则表达式,因为您在固定字符串上进行拆分。 Apache StringUtils split 对纯字符串进行拆分。

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

Guava 也有一个拆分器,以更面向对象的方式实现,但我发现它比 StringUtils 大容量拆分慢得多。

【讨论】:

以上是关于Java 的 Scanner vs String.split() vs StringTokenizer;我应该使用哪个?的主要内容,如果未能解决你的问题,请参考以下文章

java - Scanner vs InputStreamReader - Stack Overflow

BufferedReader vs Console vs Scanner

13JAVA常见类(Scanner类String类)

在java 中,String cmd=scanner.nextLine();String help

Java基础12---String类

Java基础12---String类