繁体   English   中英

在流过滤器中包含ContainsIgnoreCase以计算字符串列表中一个特定单词的出现

[英]ContainsIgnoreCase in stream filter to count one particular word occurence in list of String

我想计算java中的字符串列表中单个单词的出现。 貌似这个任务很容易,但我遇到了一个问题,与由大写字母开头或者包含单词,. 这个词的末尾。 我的方法如下:

public static Long countWordOccurence(List<String> wordList, String word) {

    return wordList.stream()
        .filter(s -> word.contains(s))
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        .values()
        .stream()
        .findFirst()
        .orElse((long) -1);
  }

上面的代码在正常情况下可以正常工作,但对于像逗号这样的特殊情况,例如Test,或以大写字母开头的字符串的末尾,会出现问题。

我正在拆分我的字符串列表,如:

Arrays.asList(TEXT_TO_PARSE.split(" ")); 

如果可能的话,我将不胜感激,避免额外的依赖,但如果有必要,我不会轻视。

我将对如何修复流中的filter子句以正确计数字符串的建议表示感谢。

您的代码有几个基本问​​题。

  • .filter(s -> word.contains(s))执行子字符串搜索。 与您的问题的标题相反,它不会忽略大小写。 尽管如此,仍有一些内容可以通过过滤器的字符串

  • .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))根据字符串的实际内容创建组。 因此,当多个不同的字符串通过先前的过滤器时,可能存在多个组

  • .values().stream().findFirst() :由于groupingBy创建了具有未指定顺序的地图,因此它将选择一个任意组。 除此之外,仅要求count()是一种非常低效的方法

  • .orElse((long) -1)-1是一个非常奇怪的后备计数方式,因为当没有匹配项时,最自然的答案是“零”。

所以直接的解决方案是

public static long countWordOccurence(List<String> wordList, String word) {
    return Collections.frequency(wordList, word);
}

用于计算区分大小写的匹配项或

public static long countWordOccurence(List<String> wordList, String word) {
    return wordList.stream().filter(word::equalsIgnoreCase).count();
}

用于不区分大小写的计数。

但这还是一个xy问题

当您要计算字符串中单词的出现次数时,在执行实际搜索之前,无需将字符串拆分为单词并将数组转换为列表(顺便说一下,您可以直接在数组上流式传输 )。

您可以使用

public static long countWordOccurence(String sentence, String word) {
    if(!word.codePoints().allMatch(Character::isLetter))
        throw new IllegalArgumentException(word+" is not a word");
    Pattern p = Pattern.compile("\\b"+word+"\\b");
    return p.matcher(sentence).results().count();
}

区分大小写的匹配项和

public static long countWordOccurence(String sentence, String word) {
    if(!word.codePoints().allMatch(Character::isLetter))
        throw new IllegalArgumentException(word+" is not a word");
    Pattern p = Pattern.compile("\\b"+word+"\\b", Pattern.CASE_INSENSITIVE);
    return p.matcher(sentence).results().count();
}

不区分大小写的匹配。 \\b模式表示单词边界,仅当搜索字符串实际上是单词时才有意义。 因此,上述方法对此进行了预测试,这还可以确保该单词不包含可能被误解为正则表达式模式的字符。

在Java 9中引入了results()方法。 此答案显示了一种在Java 8下创建此类流的解决方案,但是,对于这样一个简单的任务,例如计算出现次数,可以选择在此处不使用流:

public static long countWordOccurence(String sentence, String word) {
    if(!word.codePoints().allMatch(Character::isLetter))
        throw new IllegalArgumentException(word+" is not a word");
    Pattern p = Pattern.compile("\\b"+word+"\\b", Pattern.CASE_INSENSITIVE);
    int count = 0;
    for(Matcher m = p.matcher(sentence); m.find(); count++) {}
    return count;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM