使用字符串分词器获取不同行的输入

问题描述

我已经使用 Scanner(system.in) 很长时间了,但我现在正在过渡到使用 BufferedReader 和 StringTokenizer,因为我听说它运行得更快。我正在尝试使用 StringTokenizer 读取输入(如下所示)。我看过一些帖子,但没有看到任何可以解决这个特定问题的帖子。

5
2 3 2 2 3

这是我的代码

import java.util.*;
import java.io.*;
public class Finddistinct {

    public static void main(String[] args) throws IOException {
        
        BufferedReader r = new BufferedReader(new InputStreamReader(system.in));
        PrintWriter pw = new PrintWriter(System.out);
        StringTokenizer st = new StringTokenizer(r.readLine());
        int n = Integer.parseInt(st.nextToken());
        HashSet<Integer> set = new HashSet<Integer>();
        
        for (int i = 0; i < n; i++) {
            set.add(Integer.parseInt(st.nextToken()));
        }
        
        pw.println(set.size());
        pw.close();
        r.close();
        
    }

}

我得到的错误是:

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.StringTokenizer.nextToken(StringTokenizer.java:348)
    at Finddistinct.main(Finddistinct.java:16)

我认为发生错误是因为我正在读取多行输入。我该如何解决?顺便说一下,这是用于竞争性编程,所以我正在寻找可以快速运行的解决方案。提前致谢!

解决方法

来自 StringTokenizer 的 Javadoc:

  • {@code StringTokenizer} 是一个遗留类,出于兼容性原因保留,但不鼓励在新代码中使用它。建议任何寻求此功能的人使用 {@code String} 的 {@code split} 方法或 java.util.regex 包。

但您的问题是您只从缓冲读取器读取一行,因此您的标记生成器只有一个标记,但随后您尝试从中读取下一个 n 标记。

您需要阅读另一行并创建另一个 StringTokenizer。

我怀疑此方法与 Scanner 之间的任何性能差异是否重要。在竞争性编程问题中,找到有效的算法是关键。