java --敏感詞彙過濾

每一個app的評論(或提問等)功能都會作敏感詞過濾。
#1.常規作法html

/**
	 * flag:0(不是敏感詞) 1(敏感詞)
	 */
	public int checkWord() {
		int flag = 0;		
		String content = "用戶評論的內容";
		java.util.List<String> list = new ArrayList<>();
		//從數據庫取出敏感詞彙列表
		list.add("習dd");
		list.add("彭mm");
		list.add("網絡流行語");
		
		for (int i = 0; i < list.size(); i++) {
			if (content.contains(list.get(i))) {
				flag = 1;
				break;
			}
		}
		return flag;
	}

當數據量很大的時候,如上的方法執行效率特別慢,所以須要找改進的方法,以下有一篇文章寫的不錯
http://www.cnblogs.com/chenssy/p/3751221.html#2966041
#2.改進方法
將敏感詞加入到HashMap中,構建DFA算法模型java

public class SensitiveWordInit {
	
	/**
	 * @Description: 初始化敏感詞庫,將敏感詞加入到HashMap中,構建DFA算法模型
	 * @param list:從數據庫獲取到的敏感詞彙列表
	 * @return 敏感詞彙HashMap
	 * 備註:原做者的入參是Set<String>,我改爲了List.
	 * 改完後才發現做者的用心,Set的效率比List高
	 */
	public HashMap getSensitiveWordToHashMap(List<String> list){
		
		//敏感詞彙map
		HashMap sensitiveWordMap = new HashMap<>();
		//關鍵字
		String key = "";
		//轉換map
		Map tempMap = null;
		//給臨時map賦值
		Map newMap = null;
		
		//迭代器
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			//取出關鍵詞
			key = it.next();
			//這裏給輸出map賦值
			tempMap = sensitiveWordMap;
			
			//拆分關鍵詞,存入map
			for (int i = 0; i < key.length(); i++) {
				//因爲key是字符串型,因此裏面存放的是字符型,所以存在以下取法
				//備註:其實這裏能夠將key轉成array,用array[i]取仍是同樣
				char keyChar = key.charAt(i);
				
				//從轉換map裏面取出單個"關鍵字",多個關鍵字組成關鍵詞
				//備註:這裏可使用String類型來接收
				Object tmpKey = tempMap.get(keyChar);
				//若是tmpKey裏面存在該key,直接賦值
				if (tmpKey != null) {
					tempMap = (Map)tmpKey;
				}else
				{
					/**
					 * 若是不存在該key,則添加進去
					 */
					//新構建一個map,將isEnd設值0,由於它不是最後一個
					newMap = new HashMap<>();
					//不是最後一個
					newMap.put("isEnd", 0);
					//將該key添加到tempMap,其實是添加到sensitiveWordMap中
					//這裏涉及到一個地址引用的知識點
					tempMap.put(keyChar, newMap);
					//從新使tempMap指向newMap
					tempMap = newMap;
				}
				//最後一個
				if(i == key.length() - 1){
					tempMap.put("isEnd", "1");    
				}
			}
		}
		
		//返回敏感詞彙map
		return sensitiveWordMap;
	}
}

敏感詞彙過濾類算法

/**
 * 敏感詞彙過濾類
 * 包含三個主要方法
 * 1.isContaintSensitiveWord,判斷輸入的內容是否是包含敏感詞彙
 * 2.getSensitiveWord,獲取輸入內容的敏感詞
 * 3.replaceSensitiveWord,替換敏感詞彙字符
 */
public class SensitiveWordFilter {
	
	//敏感詞彙map
	private HashMap sensitiveWordMap;
	//最小匹配規則
	//一旦匹配到,不繼續匹配,直接返回
	private static int minMatchTYpe = 1;
	//最大匹配規則
	//匹配全部的
	private static int maxMatchType = 2;
	//關鍵詞聚集合
	public List<String> list = new ArrayList<>();
	
	
	/**
	 * 構造函數,初始化敏感詞彙庫
	 * @param list
	 */
	public SensitiveWordFilter(List<String> list) {
		sensitiveWordMap = new SensitiveWordInit().getSensitiveWordToHashMap(list);
	}
	
	/**
	 * 判斷輸入的內容是否是包含敏感詞彙
	 * @param content:輸入的內容
	 * @param matchType:匹配規則
	 * @return true or false
	 */
	public boolean isContaintSensitiveWord(String content,int matchType){
		boolean flag = false;
		
		for (int i = 0; i < content.length(); i++) {
			//循環匹配
			int matchFlag = CheckSensitiveWord(content, i, matchType);
			//大於0存在,返回true
			if(matchFlag > 0){    
				flag = true;
			}
		}
		
		return flag;
	}
	/**
	 * 獲取輸入內容的敏感詞
	 * @param content:輸入內容
	 * @param matchType:匹配類型
	 * @return 匹配到的敏感詞列表
	 */
	public List<String> getSensitiveWord(String content,int matchType){
		List<String> sensitiveWordList = new ArrayList<>();
		
		//判斷是否存在敏感詞彙,不存在爲0
		int length = 0;
		for (int i = 0; i < content.length(); i++) {
			//判斷是否包含敏感詞彙
			length = CheckSensitiveWord(content, i, matchType);
			//若是存在
			if (length > 0) {
				//截取輸入內容的i到i+length
				sensitiveWordList.add(content.substring(i, i+length));
				//減1的緣由,是由於for會自增
				/**
				 * 舉例:假設i從0開始,length=5,則匹配了0~4共5個字符
				 * 所以,下一次匹配時,i應該從5開始
				 * 注意:這一次匹配完了以後,會執行i++,所以i++的值應該是5
				 * 因此這裏須要將i的值設成0+5-1=4
				 * 這一次執行完了後,i的值變成5
				 */
				i = i + length - 1;
			}
		}
		return sensitiveWordList;
	}
	
	/**
	 * 替換敏感詞彙字符
	 * @param content:輸入的內容
	 * @param matchType:匹配規則
	 * @param replaceChar:替換字符,例如:*
	 * @return 輸入字符串,敏感詞彙被替換成*
	 */
	public String replaceSensitiveWord(String content,int matchType,String replaceChar){
		String resultTxt = content;
		//獲取全部的敏感詞彙
		List<String> replaceSensitiveWordList = getSensitiveWord(content, matchType);
		//臨時變量
		String word = null;
		//替換字符串
		String replaceString = null;
		//迭代器
		Iterator<String> it = replaceSensitiveWordList.iterator();
		while (it.hasNext()) {
			//敏感詞彙(多個字符,假設5個字符)
			word = it.next();
			//這是替換後的字符(假設5個)
			replaceString = getReplaceChars(replaceChar, word.length());
			//替換後的字符串
			resultTxt = resultTxt.replaceAll(word, replaceString);
		}
		
		return resultTxt;
	}
	
	/**
	 * 獲取替換字符串
	 * @param replaceChar:替換成什麼字符,例如:*
	 * @param length:須要將幾個字符替換成*
	 * @return 多少個*
	 */
	private String getReplaceChars(String replaceChar,int length){
		String resultReplace = replaceChar;
		for(int i = 1 ; i < length ; i++){
			resultReplace += replaceChar;
		}
		return resultReplace;
	}
	
	/**
	 * 檢查輸入內容是否包含敏感詞彙
	 * @param content:輸入內容
	 * @param beginIndex:匹配位置
	 * @param matchType:匹配規則
	 * @return true or false
	 */
	public int CheckSensitiveWord(String content,int beginIndex,int matchType){
		
		//敏感詞彙結束標識符,默認爲沒有匹配到
		boolean  flag = false;
		//匹配到敏感詞彙的次數
		int matchFlag = 0;
		//臨時變量
		char word = 0;
		Map tmpMap = sensitiveWordMap;
		for (int i = beginIndex; i < content.length(); i++) {
			//取出輸入內容的字符
			word = content.charAt(i);
			//獲取key
			tmpMap = (Map) tmpMap.get(word);
			//若是存在
			if (tmpMap != null) {
				//匹配標識加1
				matchFlag++;
				//匹配到了最後,結束循環,返回匹配數
				if ("1".equals(tmpMap.get("isEnd"))) {
					//結束標誌位爲true 
					flag = true;
					//最小規則,退出for循環;最大規則,繼續for循環
					if (SensitiveWordFilter.minMatchTYpe == matchType) {
						break;
					}
				}
			}else
			{
				//不存在,直接退出for循環
				break;
			}
		}
		//詞至少由兩個字符組成
		//1.僅僅匹配到單個字符,它不能構成詞,所以匹配失敗
		//2.flag=false,說明匹配失敗
		if (matchFlag < 2 || !flag) {
			matchFlag = 0;
		}
		return matchFlag;
	}
	
	//測試
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		list.add("張三");
		list.add("李四");
		list.add("王五");
		list.add("趙六");
		SensitiveWordFilter swf = new SensitiveWordFilter(list);
		System.out.println("敏感詞的數量:" + swf.sensitiveWordMap.size());
		//輸入字符串
		String content = "張三丰李四毛王五怪";
		//測試1:匹配輸出全部的關鍵詞(最小匹配規則)
		List<String> list2 = swf.getSensitiveWord(content, 1);
		System.out.println(list2);
		//測試2:isContaintSensitiveWord
		boolean exite = swf.isContaintSensitiveWord(content, 1);
		System.out.println(exite);
		//測試3:將敏感詞彙替換成*
		String replaceString = swf.replaceSensitiveWord(content, 1, "*");
		System.out.println(replaceString);
	}
}

測試結果數據庫

敏感詞的數量:4
[張三, 李四, 王五]
true
**豐**毛**怪
相關文章
相關標籤/搜索