Java中如何用List<String>匹配字符串敏感词?现有代码优化
Let's work through this — your current code has a couple of critical logic issues that are keeping it from detecting target words like "apple" and "hi". Let's break down what's wrong and build a working solution.
What's Wrong With the Current Code?
- Incorrect Stream Usage: You're calling
words.stream()on a singleStringvariable, which creates a stream of individual characters, not the words in your content. That's not what you want for word matching. - Misplaced Equality Check:
anyMatch(badWordsList::equals)is checking if each character in your content equals the entire list of bad words — that's never going to be true, and it's not the match logic you need.
Solution 1: Basic Substring Matching (Case-Insensitive)
If you just need to detect if the sensitive word appears anywhere in the content (even as part of a longer word, like "apple" in "pineapple"), use this straightforward approach:
import java.util.List; import java.util.stream.Collectors; private boolean checkWildcardFilter(String contentStripped, GuildTransformer guild) { // Convert content to lowercase for case-insensitive matching String lowerCaseContent = contentStripped.toLowerCase(); // Get your bad words list and convert all to lowercase too List<String> badWordsList = replace(guild.getBadWordsWildcard()); List<String> lowerCaseBadWords = badWordsList.stream() .map(String::toLowerCase) .collect(Collectors.toList()); // Check if the content contains ANY of the bad words return lowerCaseBadWords.stream() .anyMatch(lowerCaseContent::contains); }
Solution 2: Exact Word Matching (Avoid Partial Hits)
If you want to only match full words (so "apple" doesn't trigger on "pineapple", and "hi" doesn't trigger on "hiring"), use regular expressions with word boundaries:
import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; private boolean checkWildcardFilter(String contentStripped, GuildTransformer guild) { String lowerCaseContent = contentStripped.toLowerCase(); List<String> badWordsList = replace(guild.getBadWordsWildcard()); // Preprocess bad words: lowercase + escape regex special chars (like *, ., ?) List<Pattern> badWordPatterns = badWordsList.stream() .map(String::toLowerCase) .map(badWord -> { // Escape any regex-specific characters in the bad word String escapedWord = Pattern.quote(badWord); // Use \b to match full word boundaries return Pattern.compile("\\b" + escapedWord + "\\b"); }) .collect(Collectors.toList()); // Check if any pattern matches the content return badWordPatterns.stream() .anyMatch(pattern -> pattern.matcher(lowerCaseContent).find()); }
Key Notes for Your Use Case
- Case Insensitivity: Converting both the content and sensitive words to lowercase ensures matches regardless of how the words are capitalized (e.g., "Apple", "APPLE", "apple" all get caught).
- Regex Escaping:
Pattern.quote()is crucial if your database has sensitive words with special characters (like "*" or "."), since those would otherwise be interpreted as regex syntax instead of literal characters. - Performance Tip: If a guild's bad words don't change often, cache the compiled
Patternlist for that guild instead of rebuilding it every time the method runs — this will speed up repeated checks.
Testing this with your sample sentence: "I will go and eat a grand apple with my new hi re." will correctly detect both "apple" and "hi" no matter where they appear, returning true to trigger your filtering.
内容的提问来源于stack exchange,提问作者Codixer

