场景:敏感词存在数据库中,也缓存到redis中,判断评论信息是否包含敏感词。
方案一:用字符串charAt对比。
方案二:DFA算法
由于需求是只要存在敏感词就直接返回是否包含敏感词结果。所以用charAt方法速度快,占用内存小,所以方案一比较适合。
方案二适合,找到包含的所有敏感词,然后将敏感词输出,并替代。效率高。但是敏感词数量与所占内存成正比。
方案一代码:
思路:其实就是一段文字字符串,是否包含敏感词。
/**
*
* Desc:(敏感词校验)container是否包含child
* @author wangdeqiu
* @date 2018年10月18日 下午4:28:41
* @param text :要判断的文字信息
* @return childWord:敏感词
*/
public static boolean str1ContainsStr2(String text, String childWord) {
if (text.length() < childWord.length()) {
return false;
}
int maxLength = text.length();
char first = childWord.charAt(0);
int i = -1;
while (++i < maxLength) {
// 第一个是否能找到
if (first == text.charAt(i)) {
// 如果找到匹配之后的元素
if (mathStr(text.substring(i), childWord)) {
return true;
}
}
}
return false;
}
private static boolean mathStr(String max, String min) {
if (max.length() < min.length()) {
return false;
}
int i = -1;
int minLength = min.length();
while (++i < minLength) {
if (min.charAt(i) != max.charAt(i)) {
return false;
}
}
return true;
}
方案二代码:
1.敏感词库初始化(将敏感词用DFA算法的原理封装到敏感词库中,敏感词库采用HashMap保存),代码如下:
package com.haidaipuhui.service.SensitiveWord;
import java.util.*;
/**
* @author wangdeqiu
* @date 2018/11/6
* @Dsecription: 敏感词库初始化
*/
@SuppressWarnings("rawtypes")
public class SensitiveWordInit {
//敏感词库
public Map sensitiveWordMap;
/**
*@describe: 初始化敏感词
*@author wangdeqiu
*@date 2018/11/6 下午1:46
*@param sensitiveWords:redis/数据库中获取的敏感词
*
*/
public Map initKeyWord(List sensitiveWords){
try{
// 从敏感词集合对象中取出敏感词并封装到Set集合中
Set keyWordSet = new HashSet();
for(String s:sensitiveWords){
keyWordSet.add(s.trim());
}
//将词库放到hashmap中
addSensitiveWordToHashMap(keyWordSet);
}catch(Exception e){
e.printStackTrace();
}
return sensitiveWordMap;
}
/**
*@describe: 封装敏感词库
*@author wangdeqiu
*@date 2018/11/6 下午1:47
*@param keyWordSet :初始后的敏感词
*
*/
@SuppressWarnings("unchecked")
public void addSensitiveWordToHashMap(Set keyWordSet){
// 初始化HashMap对象并控制容器的大小
sensitiveWordMap = new HashMap(keyWordSet.size());
// 敏感词
String key = null;
// 用来按照相应的格式保存敏感词库数据
Map nowMap = null;
// 用来辅助构建敏感词库
Map newWorMap = null;
// 使用一个迭代器来循环敏感词集合
Iterator iterator = keyWordSet.iterator();
while (iterator.hasNext()){
key = iterator.next();
// 等于敏感词库,HashMap对象在内存中占用的是同一个地址,所以此nowMap对象的变化,sensitiveWordMap对象也会跟着改变
nowMap = sensitiveWordMap;
for(int i=0;i();
newWorMap.put("isEnd", "0");
nowMap.put(keyChar, newWorMap);
nowMap = newWorMap;
}
// 如果该字是当前敏感词的最后一个字,则标识为结尾字
if (i == key.length() - 1){
nowMap.put("isEnd", "1");
}
System.out.println("封装敏感词库过程:"+sensitiveWordMap);
}
System.out.println("查看敏感词库数据:" + sensitiveWordMap);
}
}
}
2.写一个敏感词过滤工具类,里面可以写上自己需要的方法,代码如下
package com.haidaipuhui.service.SensitiveWord;
import java.util.*;
import org.springframework.stereotype.Component;
import com.haidaipuhui.util.SystemUtil;
/**
* @author wangdeqiu
* @date 2018/11/6
* @Dsecription: 敏感词过滤类
*/
@SuppressWarnings("rawtypes")
@Component
public class SensitivewordTool {
//敏感词库
public static Map sensitiveWordMap;
//只过滤最小敏感词 //最小匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国]人
public static int minMatchTYpe = 1;
//过滤所有敏感词 //最大匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国人]
public static int maxMatchTYpe = 2;
/**
*@describe: 敏感词库敏感词的数量
*@author wangdeqiu
*@date 2018/11/6 下午2:02
*@param
*
*/
public static int getWordSize(){
if(SensitivewordTool.sensitiveWordMap==null){
return 0;
}
return SensitivewordTool.sensitiveWordMap.size();
}
/**
*@describe: 是否包含敏感词
*@author wangdeqiu
*@date 2018/11/6 下午2:04
*@param
*
*/
public static boolean isContaintSensitiveWord(String txt,int matchType){
boolean flag = false;
for(int i=0;i0){
return true;
}
}
return flag;
}
/**
*@describe: 获取敏感词内容
*@author wangdeqiu
*@date 2018/11/6 下午2:07
*@param
*
*/
public static Set getSensitiveWord(String txt,int matchType){
Set sensitiveWordList = new HashSet();
for (int i = 0; i < txt.length(); i++)
{
int length = checkSensitiveWord(txt, i, matchType);
if (length > 0)
{
// 将检测出的敏感词保存到集合中
sensitiveWordList.add(txt.substring(i, i + length));
i = i + length - 1;
}
}
return sensitiveWordList;
}
/**
*@describe: 替换敏感词
*@author wangdeqiu
*@date 2018/11/6 下午2:37
*@param
*
*/
public static String replaceSensitiveWord(String txt, int matchType, String replaceChar)
{
String resultTxt = txt;
Set set = getSensitiveWord(txt, matchType);
Iterator 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;
}
/**
*@describe: 替换敏感词内容
*@author wangdeqiu
*@date 2018/11/6 下午2:11
*@param
*
*/
private static String getReplaceChars(String replaceChar, int length)
{
String resultReplace = replaceChar;
for (int i = 1; i < length; i++)
{
resultReplace += replaceChar;
}
return resultReplace;
}
/**
*@describe: 检查敏感词数量
*@author wangdeqiu
*@date 2018/11/6 下午2:11
*@param
*
*/
public static int checkSensitiveWord(String txt,int beginIndex,int matchType){
boolean flag = false;
// 记录敏感词数量
int matchFlag = 0;
char word = 0;
Map nowMap = SensitivewordTool.sensitiveWordMap;
for (int i = beginIndex; i < txt.length(); i++){
word = txt.charAt(i);
// 判断该字是否存在于敏感词库中
nowMap = (Map) nowMap.get(word);
if (nowMap != null){
matchFlag++;
// 判断是否是敏感词的结尾字,如果是结尾字则判断是否继续检测
if ("1".equals(nowMap.get("isEnd")))
{
flag = true;
// 判断过滤类型,如果是小过滤则跳出循环,否则继续循环
if (SensitivewordTool.minMatchTYpe == matchType)
{
break;
}
}
}else
{
break;
}
}
if (!flag)
{
matchFlag = 0;
}
return matchFlag;
}
/**
*
* Desc:敏感词过滤
* @author wangdeqiu
* @date 2018年11月7日 下午2:24:25
* @param
* @return
*/
public static Set sensitiveWordFiltering(String text)
{
// 初始化敏感词库对象
SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
// 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)
List sensitiveWords =SystemUtil.getWordToRedis();
// 构建敏感词库
Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);
// 传入SensitivewordEngine类中的敏感词库
SensitivewordTool.sensitiveWordMap = sensitiveWordMap;
// 得到敏感词有哪些,传入2表示获取所有敏感词
Set set = SensitivewordTool.getSensitiveWord(text, 2);
return set;
}
/**
*
* Desc:判断是否存在敏感词
* @author wangdeqiu
* @date 2018年11月7日 下午2:24:38
* @param
* @return
*/
public static boolean isExitSensitiveWord(String text)
{
// 初始化敏感词库对象
SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();
// 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)
List sensitiveWords =SystemUtil.getWordToRedis();
// 构建敏感词库
Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);
// 传入SensitivewordEngine类中的敏感词库
SensitivewordTool.sensitiveWordMap = sensitiveWordMap;
// 得到敏感词有哪些,传入1表示获取所有敏感词
boolean isExit= SensitivewordTool.isContaintSensitiveWord(text, 1);
return isExit;
}
}
参考:https://www.jb51.net/article/116752.htm