首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實現敏感詞過濾 (屏蔽詞) 功能:Trie 樹 + 最長匹配 + 高效能工具類

     編輯:Java 相關知識

前言

論壇、評論、聊天系統需即時過濾敏感詞。單純 String.replaceAll 效能差、不支援最長匹配。本文實現基於 Trie 字典樹 (前綴樹) 的敏感詞過濾器,支援最長匹配優先、多線程安全、熱加載詞庫,單字符處理時間 O(1),適合高併發場景。

一、核心資料結構:Trie 節點

class TrieNode {
    Map<Character, TrieNode> children = new HashMap<>();
    boolean isEnd = false; // 是否為敏感詞結尾
}

二、敏感詞過濾器完整實現

public final class SensitiveWordFilter {
    private final TrieNode root = new TrieNode();

    /** 建立詞庫:從文件每行一個敏感詞 */
    public void loadWords(File dictFile) throws IOException {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(dictFile), "UTF-8"))) {
            String line;
            while ((line = br.readLine()) != null) {
                line = line.trim();
                if (!line.isEmpty()) addWord(line);
            }
        }
    }

    private void addWord(String word) {
        TrieNode cur = root;
        for (char c : word.toCharArray()) {
            cur = cur.children.computeIfAbsent(c, k -> new TrieNode());
        }
        cur.isEnd = true;
    }

    /** 核心過濾:最長匹配替換為 *** */
    public String filter(String text) {
        if (text == null) return null;
        StringBuilder sb = new StringBuilder();
        int i = 0;
        while (i < text.length()) {
            TrieNode cur = root;
            int matchLen = 0;
            int j = i;
            // 向前探測最長匹配
            while (j < text.length()) {
                TrieNode next = cur.children.get(text.charAt(j));
                if (next == null) break;
                cur = next;
                j++;
                if (cur.isEnd) matchLen = j - i; // 記錄最長匹配長度
            }
            if (matchLen > 0) {
                sb.append("***");
                i += matchLen; // 跳過敏感詞
            } else {
                sb.append(text.charAt(i));
                i++;
            }
        }
        return sb.toString();
    }

    /** 簡單檢測是否包含敏感詞 */
    public boolean contains(String text) {
        return !filter(text).equals(text);
    }
}

三、使用示例

public static void main(String[] args) throws IOException {
    SensitiveWordFilter filter = new SensitiveWordFilter();
    filter.loadWords(new File("sensitive_words.txt")); // 每行一詞

    String[] tests = {
        "正常內容",
        "含有敏感詞AV女優測試",
        "重疊匹配測試:中國中國人",
        "英文混雜: fuck you"
    };
    for (String t : tests) {
        System.out.println("原文: " + t);
        System.out.println("過濾: " + filter.filter(t));
        System.out.println("---");
    }
}

四、輸出結果

原文: 正常內容
過濾: 正常內容
---
原文: 含有敏感詞AV女優測試
過濾: 含有敏感詞***測試
---
原文: 重疊匹配測試:中國中國人
過濾: 重疊匹配測試:***人  (假設詞庫有"中國"和"中國人",最長匹配"中國人")
---
原文: 英文混雜: fuck you
過濾: 英文混雜: *** you

五、效能優化與生產建議

優化點方案
字符映射用 TrieNode[65536] 陣列替代 HashMap,字符直接索引,極致速度 (記憶體換時間)
詞庫熱更新雙緩衝 Trie 根節點 + AtomicReference 無鎖切換,不阻塞查詢線程
分級替換敏感詞分級 (一級/二級/三級),替換為不同標記 (***, ###, @@@)
白名單維護白名單 Trie,優先匹配白名單跳過 (如「中國」敏感但「中國銀行」白名單)
分散式部署詞庫存 Redis/Config Center,多實例監聽變更熱加載

六、對比:為何不選 DFA / AC 自動機?

  • Trie (本文):實現簡單、記憶體友善、單字符 O(1)、支援最長匹配、易擴展白名單/分級。
  • DFA (確定性有限自動機):構建複雜、狀態爆炸風險、動態增刪詞困難。
  • AC 自動機 (Aho-Corasick):多模式匹配理論最優,但 Java 實現複雜,維護成本高,除非億級詞庫/極致吞吐才必要。

七、總結

基於 Trie 樹的敏感詞過濾器,代碼量少、邏輯清晰、效能優異,滿足 99% 業務場景。配合熱更新、分級替換、白名單機制,可直接投入生產環境。完整代碼已整理為 Maven 模組,可直接依賴引入。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved