Java 单行检查字符串是否包含横幅子字符串

Java 单行检查字符串是否包含横幅子字符串,java,string,lambda,java-8,java-stream,Java,String,Lambda,Java 8,Java Stream,我有一个字符串标题和一个列表横幅子字符串。现在,我想执行一行检查title是否没有那些横幅子字符串 我的做法: if(bannedSubstrings.stream().filter(bannedSubstring -> title.contains(bannedSubstring)).isEmpty()){ ... } 不幸的是,流没有isEmpty()方法。那么你将如何解决这个问题呢?是否有一种单线解决方案?听起来您想了解一下: 相反,还有: 如果title是一个长字符串(但

我有一个
字符串标题
和一个
列表横幅子字符串
。现在,我想执行一行检查
title
是否没有那些
横幅子字符串

我的做法:

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

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

听起来您想了解一下:

相反,还有:


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

我想您正在寻找这样的内容:

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

}
Pattern badWords = Pattern.compile(bannedSubstrings.stream().map(Pattern::quote)
    .collect(Collectors.joining("|")));
if (badWords.matcher(title).find()) {
   ...
}

如果您想要一个高效的解决方案,并且您有许多
横幅子字符串
,我想,将它们合并到单个regexp中会更快,如下所示:

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

}
Pattern badWords = Pattern.compile(bannedSubstrings.stream().map(Pattern::quote)
    .collect(Collectors.joining("|")));
if (badWords.matcher(title).find()) {
   ...
}
然后像这样使用它:

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

}
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();
    }
}
公共类BannedWordChecker{
公共最终模式横幅词;
公共横幅文字检查器(收集横幅文字){
这是我的名字=
Pattern.compile(
bannedWords.stream()
.map(模式::引号)
.collect(收集器.连接(“|”);
}
公共布尔值包含BannedWord(字符串){
返回bannedWords.matcher(string.find();
}
}

我认为最好在这里使用
noneMatch
。@mkrakhin我想这取决于函数的总体布局,但这是一个很好的建议,我会将其添加到我的答案中。当然。我刚才提到了它,因为OP在他的
if
:)中检查了空值,而且
noneMatch
anyMatch
不需要检查整个流,所以有必要保持
bandensubstrings
排序,以降低在
title
中出现的概率。或者,从
横幅子串
长度的某个点开始,创建
并行流
而不是
@principal理想域是有意义的,regexp方法渐进地更好,因为不管你有多少个被禁止的单词,它应该最多需要一次通过
title
的迭代,而我的建议是在最坏的情况下,每个被禁止的单词都需要一次通过
title
的迭代(这是字符串正常的情况!)。长话短说,我仍然认为我上面的解决方案对于任何正常用例来说都是最好的,但是如果你有一个大的(固定的)禁词集和一个长标题,regexp方法是聪明的,而且性能相对更好。@nikis:这样做会额外发现所有在这种情况下不必要的坏词。@TagirValeev同意,这是我最初想到的第一个解决方案,已经发布了另一个解决方案。您在解决方案中假设BannedSubstring不包含对正则表达式具有特殊意义的字符。是的。即使不是这样,也可以很容易地修复。编辑。