在一些评论文章中经常需要过滤敏感词,下面是过滤敏感词的步骤。

1.通过敏感词创建一个字典树的类

2.把所有敏感词放入字典树中

3.判断文章中是否有敏感词

1).创建一个字典树,字典树根节点不存数据,定义一个字典树的类,可以定义如下方法1.设置当前节点终结点,2.添加节点,3.获取下一个节点,4.判断是否为终点,

 1 private class TrieNode {
 2         /**
 3          * true 关键词的终结 ; false 继续
 4          */
 5         private boolean end = false;
 6         /**
 7          * key下一个字符,value是对应的节点
 8          */
 9         private Map<Character, TrieNode> subNodes = new HashMap<>();
10         /**
11          * 向指定位置添加节点树
12          */
13         void addSubNode(Character key, TrieNode node) {
14             subNodes.put(key, node);
15         }
16         /**
17          * 获取下个节点
18          */
19         TrieNode getSubNode(Character key) {
20             return subNodes.get(key);
21         }
22         boolean isKeywordEnd() {
23             return end;
24         }
25         void setKeywordEnd(boolean end) {
26             this.end = end;
27         }
28         public int getSubNodeCount() {//得到当前节点所有数量 暂时没用
29             return subNodes.size();
30         }
31  }
   /**
     * 根节点
     */
    private TrieNode rootNode = new TrieNode();
  /**
     * 判断是否是一个符号
     */
    private boolean isSymbol(char c) {
        int ic = (int) c;
        // 0x2E80-0x9FFF 东亚文字范围
        return !CharUtils.isAsciiAlphanumeric(c) && (ic < 0x2E80 || ic > 0x9FFF);
    }

 2)把敏感词添加到字典树中

 1 private void addWord(String lineTxt) {
 2         TrieNode tempNode = rootNode;
 3         // 循环每个字节
 4         for (int i = 0; i < lineTxt.length(); ++i) {
 5             Character c = lineTxt.charAt(i);
 6             // 过滤空格 不是英文 不是东亚文字,则过滤
 7             if (isSymbol(c)) {
 8                 continue;
 9             }
10             TrieNode node = tempNode.getSubNode(c);
11 
12             if (node == null) { // 没初始化
13                 node = new TrieNode();
14                 tempNode.addSubNode(c, node);
15             }
16 
17             tempNode = node;
18
19             if (i == lineTxt.length() - 1) {
20                 // 关键词结束, 设置结束标志
21                 tempNode.setKeywordEnd(true);
22             }
23         }
24     }

3)对文章内容进行敏感词过滤       1. rootNode 是根节点,2.begin是每一次比较敏感词开始的节点,3.position 是当前正在比较的位置

 1 /**
 2      * 过滤敏感词
 3      */
 4     public String filter(String text) {
 5         if (StringUtils.isBlank(text)) {
 6             return text;
 7         }
 8         String replacement = "***";//用***代替敏感词
 9         StringBuilder result = new StringBuilder();   //如果不是敏感词则存放在result中
10 
11         TrieNode tempNode = rootNode;
12         int begin = 0; // 回滚数
13         int position = 0; // 当前比较的位置
14 
15         while (position < text.length()) {
16             char c = text.charAt(position);
17             // 空格直接跳过
18             if (isSymbol(c)) {
19                 if (tempNode == rootNode) {
20                     result.append(c);
21                     ++begin;
22                 }
23                 ++position;
24                 continue;
25             }
26 
27             tempNode = tempNode.getSubNode(c);
28 
29             // 当前位置的匹配结束
30             if (tempNode == null) {
31                 // 以begin开始的字符串不存在敏感词
32                 result.append(text.charAt(begin));
33                 // 跳到下一个字符开始测试
34                 position = begin + 1;
35                 begin = position;
36                 // 回到树初始节点
37                 tempNode = rootNode;
38             } else if (tempNode.isKeywordEnd()) {
39                 // 发现敏感词, 从begin到position的位置用replacement替换掉
40                 result.append(replacement);
41                 position = position + 1;
42                 begin = position;
43                 tempNode = rootNode;
44             } else {
45                 ++position;
46             }
47         }
48 
49         result.append(text.substring(begin));
50 
51         return result.toString();
52     }
rootNode