【问题标题】:splitting a text into words using bufferReader使用 bufferReader 将文本拆分为单词
【发布时间】:2021-10-16 14:05:06
【问题描述】:

我有一个解决问题的问题。我必须使用 bufferedReader 仅将单词添加到树集中(并输出树集的大小),但问题是我无法通过编译器速度测试限制。文本仅包含字母和空格(可以是空行)。我必须找到一个新的解决方案,但似乎不是这样:

BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
Set<String> text = new TreeSet<String>();
String words[], line;
while ((line = read.readLine()) != null) {
    words = line.split("\\s+");
    for (int i = 0; i < words.length && words[0].length() > 0; i++) {
        text.add(words[i]);
    }
}
System.out.println(text.size());

有没有其他的“拆分”方法可以让编译器使用更少的“时间思考”?

【问题讨论】:

  • 你能用Scanner类代替BufferReader吗?
  • 不确定你是否想要循环保护中的“words[0].length() &gt; 0”条件,因为如果字符串以空格开头,即使后面有单词,这也会停止添加任何内容。将其作为条件放入循环中。 (并且只需使用一个 for 每个循环,无需使用数组索引)。

标签: java split bufferedreader


【解决方案1】:

排队

words = line.split("\\s+");

您按正则表达式进行拆分,这比按一个字符拆分要慢得多(在我的机器上是 5 次)。 Java split String performances

如果单词完全只用一个空格隔开,那么解决方法很简单

words = line.split(" ");

只需替换此行,您的代码就会运行得更快。

如果单词可以被几个空格隔开,那么在循环之后添加这样一行

text.remove("");

仍然用 1 个字符拆分替换您的正则表达式拆分。

public class Test {
    public static void main(String[] args) throws IOException {
        // string contains 1, 2 and two spaces between 1 and 2. text size should be 2
        String txt = "1  2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" +
            "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" +
            "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" +
            "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" +
            "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" +
            "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1";

        InputStream inpstr = new ByteArrayInputStream(txt.getBytes());

        BufferedReader read = new BufferedReader(new InputStreamReader(inpstr));
        Set<String> text = new TreeSet<>();
        String[] words;
        String line;
        long startTime = System.nanoTime();
        while ((line = read.readLine()) != null) {
            //words = line.split("\\s+"); -- runs 5 times slower
            words = line.split(" ");
            for (int i = 0; i < words.length; i++) {
                text.add(words[i]);
            }
        }
        text.remove("");  // add only if words can be separated with multiple spaces

        long endTime = System.nanoTime();
        System.out.println((endTime - startTime) + " " + text.size());
    }
}

你也可以用

替换你的for loop
text.addAll(Arrays.asList(words));

【讨论】:

    【解决方案2】:

    根据您提供的假设,我只需将所有内容添加到集合中,最后从中删除不需要的值。这有望减少检查条件的时间(实际上并不多)

    BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
    Set<String> text = new TreeSet<String>();
    String words[], line;
    while ((line = read.readLine()) != null) {
      words = line.split("\\s+");
      for(String value: words) {
        text.add(value);
      }
    }
    text.remove(" ");
    text.remove("");
    text.remove(null);
    System.out.println(text.size());
    

    【讨论】:

      【解决方案3】:

      您当然可以将您的BufferedReader 流式传输到您的TreeSet

      Collection<String> c = read.lines().flatMap(line -> Stream.of(line.split("\\s+")).filter(word -> word.length() > 0)).collect(Collectors.toCollection(TreeSet::new));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-13
        • 2020-12-15
        • 2016-09-16
        • 1970-01-01
        相关资源
        最近更新 更多