加载外部文件
publicvoidinit() { try ( InputStreamis=this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt"); BufferedReaderreader=newBufferedReader(newInputStreamReader(is));) { Stringkeyword; while ((keyword=reader.readLine()) !=null) { // 添加到前缀树this.addKeyword(keyword); } } catch (IOExceptione) { logger.error("加载敏感词文件失败: "+e.getMessage()); } }
定义 Trie
privateclassTrieNode { // 关键词结束标识privatebooleanisKeywordEnd=false; // 子节点(key是下级字符,value是下级节点)privateMap<Character, TrieNode>subNodes=newHashMap<>(); publicbooleanisKeywordEnd() { returnisKeywordEnd; } publicvoidsetKeywordEnd(booleankeywordEnd) { isKeywordEnd=keywordEnd; } // 添加子节点publicvoidaddSubNode(Characterc, TrieNodenode) { subNodes.put(c, node); } // 获取子节点publicTrieNodegetSubNode(Characterc) { returnsubNodes.get(c); } }
将一个敏感词添加到前缀树中
privatevoidaddKeyword(TrieNoderootNode, Stringkeyword) { TrieNodetempNode=rootNode; for (inti=0; i<keyword.length(); i++) { charc=keyword.charAt(i); TrieNodesubNode=tempNode.getSubNode(c); if (subNode==null) { // 初始化子节点subNode=newTrieNode(); tempNode.addSubNode(c, subNode); } // 指向子节点,进入下一轮循环tempNode=subNode; // 设置结束标识if (i==keyword.length() -1) { tempNode.setKeywordEnd(true); } } }
过滤敏感词
publicStringfilter(Stringtext) { if (StringUtils.isBlank(text)) { returnnull; } // 指针1TrieNodetempNode=rootNode; // 指针2intbegin=0; // 指针3intposition=0; // 结果StringBuildersb=newStringBuilder(); while (position<text.length()) { charc=text.charAt(position); // 跳过符号if (isSymbol(c)) { // 若指针1处于根节点,将此符号计入结果,让指针2向下走一步if (tempNode==rootNode) { sb.append(c); begin++; } // 无论符号在开头或中间,指针3都向下走一步position++; continue; } // 检查下级节点tempNode=tempNode.getSubNode(c); if (tempNode==null) { // 以begin开头的字符串不是敏感词sb.append(text.charAt(begin)); // 进入下一个位置position=++begin; // 重新指向根节点tempNode=rootNode; } elseif (tempNode.isKeywordEnd()) { // 发现敏感词,将begin~position字符串替换掉sb.append("****"); // 进入下一个位置begin=++position; // 重新指向根节点tempNode=rootNode; } else { // 检查下一个字符position++; } } // 将最后一批字符计入结果sb.append(text.substring(begin)); returnsb.toString(); }