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
**丰**毛**怪
相关文章
相关标签/搜索