java - 使用 Java 8 进行字数统计

标签 java java-8 java-stream

我正在尝试在 Java 8 中实现一个字数统计程序,但我无法让它工作。该方法必须以字符串作为参数并返回 Map<String,Integer>。 .

当我以旧的 Java 方式进行操作时,一切正常。但是当我尝试在 Java 8 中执行此操作时,它会返回一个映射,其中键为空且出现正确。

这是我的 java 8 风格的代码:

public Map<String, Integer> countJava8(String input){
       return Pattern.compile("(\\w+)").splitAsStream(input).collect(Collectors.groupingBy(e -> e.toLowerCase(), Collectors.reducing(0, e -> 1, Integer::sum)));
    }

这是我在正常情况下会使用的代码:

public Map<String, Integer> count(String input){
        Map<String, Integer> wordcount = new HashMap<>();
        Pattern compile = Pattern.compile("(\\w+)");
        Matcher matcher = compile.matcher(input);

        while(matcher.find()){
            String word = matcher.group().toLowerCase();
            if(wordcount.containsKey(word)){
                Integer count = wordcount.get(word);
                wordcount.put(word, ++count);
            } else {
                wordcount.put(word.toLowerCase(), 1);
            }
        }
        return wordcount;
 }

主程序:

public static void main(String[] args) {
       WordCount wordCount = new WordCount();
       Map<String, Integer> phrase = wordCount.countJava8("one fish two fish red fish blue fish");
       Map<String, Integer> count = wordCount.count("one fish two fish red fish blue fish");

        System.out.println(phrase);
        System.out.println();
        System.out.println(count);
    }

当我运行这个程序时,我得到的输出:

{ =7, =1}
{red=1, blue=1, one=1, fish=4, two=1}

我认为方法splitAsStream会将正则表达式中的匹配元素流式传输为 Stream .我该如何纠正?

最佳答案

问题似乎是你实际上是在 split 单词,即你正在流过所有不是单词的东西,或者在单词之间。不幸的是,似乎没有等效的方法来流式传输实际比赛结果(很难相信,但我没有找到任何方法;如果您知道,请随时发表评论)。

相反,您可以使用 \W 而不是 \w 来按非单词拆分。此外,如评论中所述,您可以通过使用 String::toLowerCase 而不是 lambda 和 Collectors.summingInt 使其更具可读性一点 .

public static Map<String, Integer> countJava8(String input) {
    return Pattern.compile("\\W+")
                  .splitAsStream(input)
                  .collect(Collectors.groupingBy(String::toLowerCase,
                                                 Collectors.summingInt(s -> 1)));
}

但是恕我直言,这仍然很难理解,不仅因为“反向”查找,而且也很难推广到其他更复杂的模式。就个人而言,我会选择“老派”解决方案,也许使用新的 getOrDefault 使其更紧凑一些。 .

public static Map<String, Integer> countOldschool(String input) {
    Map<String, Integer> wordcount = new HashMap<>();
    Matcher matcher = Pattern.compile("\\w+").matcher(input);
    while (matcher.find()) {
        String word = matcher.group().toLowerCase();
        wordcount.put(word, wordcount.getOrDefault(word, 0) + 1);
    }
    return wordcount;
}

两种情况下的结果似乎是一样的。

关于java - 使用 Java 8 进行字数统计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31190717/

相关文章:

java - 使用 gson 从对象列表中获取 JSON 字符串

java - JVM 可以在应用程序运行时(突然)杀死计时器/守护线程吗?

java - 在 Java 8 流上存储/重用中间结果

java - 您如何使用 java stream api 根据存储在对象内部的信息将对象列表转换为嵌套映射?

java - 使用 Streams 获取每个子部门和部门的员工,

java - 澄清一下这个链表的实现

java - 一封电子邮件可以包含多个消息 ID 吗?

java - 创建类和接口(interface)的数组列表

java-8 - Java 8 Stream 可以将数据分派(dispatch)给其他方法吗?

java - 在 Java 1.7 中可选? Gradle 忽略源/目标兼容性?