java实现敏感词过滤
例如敏感词为:日本人、日本鬼子、*
构建一种树形结构如下图:
这样我们就将敏感词库构建成了一个类似于一颗一颗的树,我们判断一个词是否为敏感词时就大大减少了检索的匹配范围。
比如我们要判断日本人,根据第一个字就可以确认需要检索的是哪棵树,然后再在这棵树中进行检索。
但是如何来判断一个敏感词已经结束了呢?利用标识位来判断。
所以实现这个功能,关键是如何来构建一棵棵这样的敏感词树。
static Map sensitiveWordMap = null;
/**
* 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br>
* 中 = {
* isEnd = 0
* 国 = {<br>
* isEnd = 1
* 人 = {isEnd = 0
* 民 = {isEnd = 1}
* }
* 男 = {
* isEnd = 0
* 人 = {
* isEnd = 1
* }
* }
* }
* }
* 五 = {
* isEnd = 0
* 星 = {
* isEnd = 0
* 红 = {
* isEnd = 0
* 旗 = {
* isEnd = 1
* }
* }
* }
* }
* @date 2016年4月7日 17:08:06
* @param keyWordSet 敏感词库
* @version 1.0
*/
private static void addSensitiveWordToHashMap(Set<String> keyWordSet) {
//初始化敏感词容器,减少扩容操作(100个敏感词可能构建了50颗树结构,可能用不了100size)
sensitiveWordMap = new HashMap(keyWordSet.size());
String key = null;
Map nowMap = null;
Map<String, String> newWordMap = null;
//迭代keyWordSet
Iterator<String> iterator = keyWordSet.iterator();
while(iterator.hasNext()){
key = iterator.next();//敏感词关键字
nowMap = sensitiveWordMap;//(内存分析)
for(int i=0; i<key.length(); i++){
char keyChar = key.charAt(i);//转换成char型(一个词一个词匹配)
Object wordMap = nowMap.get(keyChar);//获取
if(wordMap != null){ //如果存在该key,直接赋值
nowMap = (Map) wordMap;
}else{ //不存在,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
newWordMap = new HashMap<String, String>();
newWordMap.put("isEnd", "0"); //不是最后一个
nowMap.put(keyChar, newWordMap);
nowMap = newWordMap;
}
if(i == key.length()-1){
nowMap.put("isEnd", "1"); //最后一个
}
}
}
}
/** * 获取文字中的敏感词 * @date 2016年4月7日 17:08:06 * @param txt 需要过滤的文本 * @param matchType 匹配规则 1:最小匹配规则,2:最大匹配规则 * @return * @version 1.0 */public static Set<String> getSensitiveWord(String txt, int matchType){Set<String> sensitiveWordList = new HashSet<String>();for(int i=0; i<txt.length(); i++){int length = checkSensitiveWord(txt, i, matchType);//判断是否包含敏感字符,包含:返回敏感词长度if(length > 0){ //存在,加入Set中sensitiveWordList.add(txt.substring(i, i+length));i = i + length - 1; //减1的原因,是因为for会自增}}return sensitiveWordList;}
/** * 检查文字中是否包含敏感字符,检查规则如下:<br> * @date 2016年4月7日 17:08:06 * @param txt 需要过滤的文本 * @param beginIndex * @param matchType * @return,如果存在,则返回敏感词字符的长度,不存在返回0 * @version 1.0 */public static int checkSensitiveWord(String txt, int beginIndex, int matchType){boolean flag = false; //敏感词结束标识位:用于敏感词只有1位的情况int matchFlag = 0; //匹配标识数默认为0char word = 0;Map nowMap = sensitiveWordMap;for(int i=beginIndex; i<txt.length(); i++){word = txt.charAt(i);nowMap = (Map) nowMap.get(word);//获取指定keyif(nowMap != null){//存在,则判断是否为最后一个matchFlag ++; //找到相应key,匹配标识+1 if("1".equals(nowMap.get("isEnd"))){//如果为最后一个匹配规则,结束循环,返回匹配标识数flag = true; //结束标志位为true if(1 == matchType){//最小规则,直接返回,最大规则还需继续查找break;}}}else{//不存在,直接返回break;}}if(matchFlag < 2 || !flag){//长度必须大于等于1,为词 matchFlag = 0;}return matchFlag;}
/** * 替换敏感字字符 * @date 2016年4月7日 17:08:06 * @param txt 需要过滤的文本 * @param matchType * @param replaceChar 替换字符,默认* * @version 1.0 */public static String replaceSensitiveWord(String txt, int matchType, String replaceChar){//if(StringUtils.isBlank(txt)) return null;String resultTxt = txt;Set<String> set = getSensitiveWord(txt, matchType);//获取所有的敏感词Iterator<String> iterator = set.iterator();String word = null;String replaceString = null;while(iterator.hasNext()) {word = iterator.next();replaceString = getReplaceChars(replaceChar, word.length());resultTxt = resultTxt.replaceAll(word, replaceString);}return resultTxt;}
/** * 替换敏感字字符 * @date 2016年4月7日 17:08:06 * @param txt 需要过滤的文本 * @param matchType * @param replaceChar 替换字符,默认* * @version 1.0 */public static String replaceSensitiveWord(String txt, int matchType, String replaceChar){//if(StringUtils.isBlank(txt)) return null;String resultTxt = txt;Set<String> set = getSensitiveWord(txt, matchType);//获取所有的敏感词Iterator<String> iterator = set.iterator();String word = null;String replaceString = null;while(iterator.hasNext()) {word = iterator.next();replaceString = getReplaceChars(replaceChar, word.length());resultTxt = resultTxt.replaceAll(word, replaceString);}return resultTxt;}
/** * Test * @param args */public static void main(String[] args) {Set<String> keyWordSet = new HashSet<String>();keyWordSet.add("中国人");keyWordSet.add("中国");keyWordSet.add("中国共产");//keyWordSet敏感词可以从数据库或文件读取addSensitiveWordToHashMap(keyWordSet);System.out.println("敏感词的数量:" + keyWordSet.size());//===================================================String str = "aaa中国人中国bbb";System.out.println("待检测语句字数:" + str.length());System.out.println(getSensitiveWord(str, 1));System.out.println(replaceSensitiveWord(str, 1, "*"));//aaa**人**bbbSystem.out.println("***********************************");System.out.println(getSensitiveWord(str, 2));System.out.println(replaceSensitiveWord(str, 2, "*"));//aaa*****bbb}
原文:http://blog.csdn.net/chenssy/article/details/26961957