一行检查 String 是否包含 bannedSubstrings

One line check if String contains bannedSubstrings

我有一个 String title 和一个 List<String> bannedSubstrings。现在我想执行一行检查 title 是否没有那些 bannedSubstrings.

我的做法:

if(bannedSubstrings.stream().filter(bannedSubstring -> title.contains(bannedSubstring)).isEmpty()){
    ...
}

不幸的是,没有 isEmpty() 流方法。那么你会如何解决这个问题呢?有一线解决方案吗?

听起来你想继续阅读 anyMatch:

if (bannedSubstrings.stream().anyMatch(title::contains)) {
    // bad words!
}

反过来,还有noneMatch:

if (bannedSubstrings.stream().noneMatch(title::contains)) {
    // no bad words :D
}

如果 title 是一个长字符串(但我想标题通常不应该很长),这不是很有效。

我想你正在寻找这样的东西:

if(bannedSubstrings.stream().anyMatch(title::contains)){

}

如果你想要一个有效的解决方案并且你有很多 bannedSubstrings,我想,像这样将它们加入单个正则表达式会更快:

Pattern badWords = Pattern.compile(bannedSubstrings.stream().map(Pattern::quote)
    .collect(Collectors.joining("|")));

然后像这样使用它:

if (badWords.matcher(title).find()) {
   ...
}

这应该从您的子字符串构建一个前缀树,因此扫描速度会明显加快。如果您不关心性能,请使用其他答案。

您选择的答案非常好,但为了获得真正的性能,您最好将错误词列表预编译到正则表达式中。

public class BannedWordChecker {
    public final Pattern bannedWords;

    public BannedWordChecker(Collection<String> bannedWords) {
        this.bannedWords =
            Pattern.compile(
                bannedWords.stream()
                    .map(Pattern::quote)
                    .collect(Collectors.joining("|")));
    }

    public boolean containsBannedWords(String string) {
        return bannedWords.matcher(string).find();
    }
}