文字列のリストにある特定の単語の出現をカウントするストリームフィルタでContainsIgnoreCase

マーティン:

私は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(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パターンは、検索文字列が実際に単語である場合にのみ意味がある単語の境界を意味します。また、単語が正規表現パターンと誤って解釈される可能性が文字が含まれていないことを保証し、そのための事前テストを、持っている上記の方法はそう。

results()この方法は、Java 9で導入されたこの回答: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;
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=314043&siteId=1