每一个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 **丰**毛**怪