Java使用DFA算法實(shí)現(xiàn)過(guò)濾多家公司自定義敏感字功能詳解
本文實(shí)例講述了Java使用DFA算法實(shí)現(xiàn)過(guò)濾多家公司自定義敏感字功能。分享給大家供大家參考,具體如下:
背景
因?yàn)樽罱型ㄓ嵱袀€(gè)需求,說(shuō)需要讓多家客戶公司可以自定義敏感詞過(guò)濾掉他們自定義的規(guī)則,選擇了DFA算法來(lái)做,不過(guò)和以前傳統(tǒng)了DFA寫法不太一樣了
模式圖
直接上代碼
public class KeywordFilter { // private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public static Map<String, HashMap> currentMap = new ConcurrentHashMap<String, HashMap>(); public static Map nowhash = null; public static Object wordMap;// map子節(jié)點(diǎn) // 不建立對(duì)象 private KeywordFilter() { } private static String getKey(int companyId) { return "companyId" + companyId; } /* * <p>說(shuō)明:清掃內(nèi)容</p> * * @author:姚旭民 * * @data:2017-8-22 上午10:13:11 */ public static void clear() { try { currentMap.clear(); } catch (Exception e) { e.printStackTrace(); } finally { } } /* * <p>說(shuō)明:各個(gè)渠道的過(guò)濾字符</p> * * @author:姚旭民 * * @data:2017-8-20 下午2:55:06 */ public static void saveKeywords(int companyId, List<String> keywords) { try { Map tempAllMap = currentMap; String key = getKey(companyId); int l = keywords.size(); int il; Map tempMap; for (int i = 0; i < l; i++) { String key2 = keywords.get(i).trim();// 去掉空白 nowhash = currentMap; il = key2.length(); for (int j = 0; j < il; j++) { char word = key2.charAt(j); tempMap = (Map) nowhash.get(word); wordMap = nowhash.get(word); if (wordMap != null) {// 檢查數(shù)據(jù) if (!tempMap.containsKey(key)) { nowhash.put(key, 0); } nowhash = (HashMap) wordMap; } else { HashMap<String, String> newWordHash = new HashMap<String, String>(); newWordHash.put(key, "0"); nowhash.put(word, newWordHash); nowhash = newWordHash; } if (j == il - 1) { nowhash.put(key, "1"); } } } } catch (Exception e) { e.printStackTrace(); } finally { nowhash = null; wordMap = null; } } /* * <p>說(shuō)明:替換掉對(duì)應(yīng)的渠道規(guī)定掉敏感字</p> * * @author:姚旭民 * * @data:2017-8-20 上午11:41:47 */ public static List<String> repword(int companyId, String txt) { Map tempMap = currentMap; List<String> result = new ArrayList<String>(); String key = getKey(companyId); nowhash = currentMap; int l = txt.length(); char word; String keywordStr = ""; String keyStatu; StringBuilder keyword = new StringBuilder();// 敏感字 for (int i = 0; i < l; i++) { word = txt.charAt(i); wordMap = nowhash.get(word); if (wordMap != null) {// 找到類似敏感字的字體,開(kāi)始查詢 keyword.append(word); Object te = nowhash = (HashMap) wordMap; // 遍歷到這一步,就符合完整的關(guān)鍵字模板 if (nowhash.get(key) != null && nowhash.get(key).toString().equals("1")) {// 確定是敏感字,開(kāi)始替換 if (i < l - 1 && nowhash.get(txt.charAt(i + 1)) != null) {// 優(yōu)先過(guò)濾長(zhǎng)敏感詞,去掉就檳城了優(yōu)先過(guò)濾段敏感詞 continue; } txt = txt.replaceAll(keyword.toString(), "*"); nowhash = currentMap; keywordStr += keyword.toString() + ","; i = i - keyword.length() + 1; l = txt.length();// 重新獲取字符長(zhǎng)度 keyword.delete(0, keyword.length());// 清空數(shù)據(jù) } } else {// 這個(gè)字不是敏感字,直接排除 nowhash = currentMap; keyword.delete(0, keyword.length());// 清空數(shù)據(jù) continue; } } // 清除內(nèi)存指向 nowhash = null; wordMap = null; result.add(txt); result.add(keywordStr.length() - 1 > 0 ? keywordStr.substring(0, keywordStr.length() - 1) : keywordStr); return result; } /* * <p>說(shuō)明:檢查是否存在敏感字</p> * * @author:姚旭民 * * @data:2017-8-20 下午3:00:06 專門設(shè)計(jì)成私有的,如果沒(méi)有理由,別改動(dòng)他 */ private static int checkKeyWords(String txt, int companyId, int begin) { int result = 0; String key = getKey(companyId); try { nowhash = currentMap; int l = txt.length(); char word = 0; for (int i = begin; i < l; i++) { word = txt.charAt(i); wordMap = nowhash.get(word); if (wordMap != null) { result++; nowhash = (HashMap) wordMap; if (((String) nowhash.get(key)).equals("1")) { nowhash = null; wordMap = null; return result; } } else { result = 0; break; } } } catch (Exception e) { e.printStackTrace(); } finally { nowhash = null; wordMap = null; return result; } } /* * <p>說(shuō)明:返回檢查的文本中包含的敏感字</p> * * @author:姚旭民 * * @data:2017-8-20 下午3:32:53 */ public static String getTxtKeyWords(String txt, int companyId) { String result = null; StringBuilder temp = new StringBuilder(); String key; int l = txt.length(); for (int i = 0; i < l;) { int len = checkKeyWords(txt, companyId, i); if (len > 0) { key = (txt.substring(i, i + len));// 挑選出來(lái)的關(guān)鍵字 temp.append(key + ","); txt = txt.replaceAll(key, "");// 挑選出來(lái)的關(guān)鍵字替換成空白,加快挑選速度 l = txt.length(); } else { i++; } } if (temp.length() > 0) { result = temp.substring(0, temp.length() - 1); } return result; } /* * <p>說(shuō)明:判斷文中是否包含渠道規(guī)定的敏感字</p> * * @author:姚旭民 * * @data:2017-8-20 下午3:33:19 */ public boolean isKeyWords(String txt, int companyId) { for (int i = 0; i < txt.length(); i++) { int len = checkKeyWords(txt, companyId, i); if (len > 0) { return true; } } return false; } public static void main(String[] arg) { List<String> keywords = new ArrayList<String>(); keywords.add("傻×"); keywords.add("漢奸"); keywords.add("草"); keywords.add("草泥馬"); KeywordFilter.saveKeywords(1, keywords); String txt = "是傻×漢奸傻A(chǔ)傻B傻C傻D漢奸傻×草泥馬"; List<String> list = repword(1, txt); System.out.println("文中包含的敏感字為:" + list.get(1)); System.out.println("原文:" + txt); System.out.println("敏感字過(guò)濾后:" + list.get(0)); } }
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java字符與字符串操作技巧總結(jié)》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
淺談Java中Lock和Synchronized的區(qū)別
這篇文章主要介紹了Java中Lock和Synchronized的區(qū)別,Lock和Synchronized都是java中去用來(lái)解決線程安全問(wèn)題的一個(gè)工具,但是具體有什么區(qū)別呢?下面我們一起進(jìn)入文章了解具體詳細(xì)內(nèi)容吧,需要的朋友可以參考一下2022-04-04SpringBoot無(wú)法訪問(wèn)/static下靜態(tài)資源的解決
這篇文章主要介紹了SpringBoot無(wú)法訪問(wèn)/static下靜態(tài)資源的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09Spring security實(shí)現(xiàn)記住我下次自動(dòng)登錄功能過(guò)程詳解
這篇文章主要介紹了Spring security實(shí)現(xiàn)記住我下次自動(dòng)登錄功能過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java根據(jù)URL下載文件到本地的2種方式(大型文件與小型文件)
這篇文章主要給大家介紹了關(guān)于Java根據(jù)URL下載文件到本地的2種方式,分別是大型文件與小型文件,避免內(nèi)存溢出OOM,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01自己手寫Mybatis通用batchInsert問(wèn)題
這篇文章主要介紹了自己手寫Mybatis通用batchInsert問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11jdbc連SQL?server顯示1433端口連接失敗圖文解決方法
這篇文章主要給大家介紹了關(guān)于jdbc連SQL?server顯示1433端口連接失敗的圖文解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-06-06Java stringBuilder的使用方法及實(shí)例解析
這篇文章主要介紹了Java stringBuilder的使用方法及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09詳解Spring Data JPA系列之投影(Projection)的用法
本篇文章主要介紹了詳解Spring Data JPA系列之投影(Projection)的用法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07