java dfa 敏感词_java利用DFA算法实现敏感词过滤功能

本文介绍了使用DFA算法在Java中实现敏感词过滤的功能,包括敏感词库初始化、敏感词过滤工具类的编写,以及如何在实际项目中应用。通过DFA算法,提高了相对于逐个查询敏感词的效率,但内存占用较高。
摘要由CSDN通过智能技术生成

前言

敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检

测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输

入内容中的敏感词并进行相应的处理,要么提示,要么高亮显示,要么直接替换成其它的文字或者符号代替。

敏感词过滤的做法有很多,我简单描述我现在理解的几种:

①查询数据库当中的敏感词,循环每一个敏感词,然后去输入的文本中从头到尾搜索一遍,看是否存在此敏感词,有则做相

应的处理,这种方式讲白了就是找到一个处理一个。

优点:so easy。用java代码实现基本没什么难度。

缺点:这效率让我心中奔过十万匹草泥马,而且匹配的是不是有些蛋疼,如果是英文时你会发现一个很无语的事情,比如英文

a是敏感词,那我如果是一篇英文文档,那程序它妹的得处理多少次敏感词?谁能告诉我?

②传说中的DFA算法(有穷自动机),也正是我要给大家分享的,毕竟感觉比较通用,算法的原理希望大家能够自己去网上查查

资料,这里就不详细说明了。

优点:至少比上面那sb效率高点。

缺点:对于学过算法的应该不难,对于没学过算法的用起来也不难,就是理解起来有点gg疼,匹配效率也不高,比较耗费内存,

敏感词越多,内存占用的就越大。

③第三种在这里要特别说明一下,那就是你自己去写一个算法吧,或者在现有的算法的基础上去优化,这也是追求的至高境界之一。

那么,传说中的DFA算法是怎么实现的呢?

第一步:敏感词库初始化(将敏感词用DFA算法的原理封装到敏感词库中,敏感词库采用HashMap保存),代码如下:

package com.cfwx.rox.web.sysmgr.util;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

import com.cfwx.rox.web.common.model.entity.SensitiveWord;

/**

* 敏感词库初始化

*

* @author AlanLee

*

*/

public class SensitiveWordInit

{

/**

* 敏感词库

*/

public HashMap sensitiveWordMap;

/**

* 初始化敏感词

*

* @return

*/

public Map initKeyWord(List sensitiveWords)

{

try

{

// 从敏感词集合对象中取出敏感词并封装到Set集合中

Set keyWordSet = new HashSet();

for (SensitiveWord s : sensitiveWords)

{

keyWordSet.add(s.getContent().trim());

}

// 将敏感词库加入到HashMap中

addSensitiveWordToHashMap(keyWordSet);

}

catch (Exception e)

{

e.printStackTrace();

}

return sensitiveWordMap;

}

/**

* 封装敏感词库

*

* @param keyWordSet

*/

@SuppressWarnings("rawtypes")

private 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 < key.length(); i++)

{

// 截取敏感词当中的字,在敏感词库中字为HashMap对象的Key键值

char keyChar = key.charAt(i);

// 判断这个字是否存在于敏感词库中

Object wordMap = nowMap.get(keyChar);

if (wordMap != null)

{

nowMap = (Map) wordMap;

}

else

{

newWorMap = new HashMap();

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);

}

}

}

第二步:写一个敏感词过滤工具类,里面可以写上自己需要的方法,代码如下:

package com.cfwx.rox.web.sysmgr.util;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

/**

* 敏感词过滤工具类

*

* @author AlanLee

*

*/

public class SensitivewordEngine

{

/**

* 敏感词库

*/

public static Map sensitiveWordMap = null;

/**

* 只过滤最小敏感词

*/

public static int minMatchTYpe = 1;

/**

* 过滤所有敏感词

*/

public static int maxMatchType = 2;

/**

* 敏感词库敏感词数量

*

* @return

*/

public static int getWordSize()

{

if (SensitivewordEngine.sensitiveWordMap == null)

{

return 0;

}

return SensitivewordEngine.sensitiveWordMap.size();

}

/**

* 是否包含敏感词

*

* @param txt

* @param matchType

* @return

*/

public static boolean isContaintSensitiveWord(String txt, int matchType)

{

boolean flag = false;

for (int i = 0; i < txt.length(); i++)

{

int matchFlag = checkSensitiveWord(txt, i, matchType);

if (matchFlag > 0)

{

flag = true;

}

}

return flag;

}

/**

* 获取敏感词内容

*

* @param txt

* @param matchType

* @return 敏感词内容

*/

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;

}

/**

* 替换敏感词

*

* @param txt

* @param matchType

* @param replaceChar

* @return

*/

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;

}

/**

* 替换敏感词内容

*

* @param replaceChar

* @param length

* @return

*/

private static String getReplaceChars(String replaceChar, int length)

{

String resultReplace = replaceChar;

for (int i = 1; i < length; i++)

{

resultReplace += replaceChar;

}

return resultReplace;

}

/**

* 检查敏感词数量

*

* @param txt

* @param beginIndex

* @param matchType

* @return

*/

public static int checkSensitiveWord(String txt, int beginIndex, int matchType)

{

boolean flag = false;

// 记录敏感词数量

int matchFlag = 0;

char word = 0;

Map nowMap = SensitivewordEngine.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 (SensitivewordEngine.minMatchTYpe == matchType)

{

break;

}

}

}

else

{

break;

}

}

if (!flag)

{

matchFlag = 0;

}

return matchFlag;

}

}

第三步:一切都准备就绪,当然是查询好数据库当中的敏感词,并且开始过滤咯,代码如下:

@SuppressWarnings("rawtypes")

@Override

public Set sensitiveWordFiltering(String text)

{

// 初始化敏感词库对象

SensitiveWordInit sensitiveWordInit = new SensitiveWordInit();

// 从数据库中获取敏感词对象集合(调用的方法来自Dao层,此方法是service层的实现类)

List sensitiveWords = sensitiveWordDao.getSensitiveWordListAll();

// 构建敏感词库

Map sensitiveWordMap = sensitiveWordInit.initKeyWord(sensitiveWords);

// 传入SensitivewordEngine类中的敏感词库

SensitivewordEngine.sensitiveWordMap = sensitiveWordMap;

// 得到敏感词有哪些,传入2表示获取所有敏感词

Set set = SensitivewordEngine.getSensitiveWord(text, 2);

return set;

}

最后一步:在Controller层写一个方法给前端请求,前端获取到需要的数据并进行相应的处理,代码如下:

/**

* 敏感词过滤

*

* @param text

* @return

*/

@RequestMapping(value = "/word/filter")

@ResponseBody

public RespVo sensitiveWordFiltering(String text)

{

RespVo respVo = new RespVo();

try

{

Set set = sensitiveWordService.sensitiveWordFiltering(text);

respVo.setResult(set);

}

catch (Exception e)

{

throw new RoxException("过滤敏感词出错,请联系维护人员");

}

return respVo;

}

总结

以上就是这篇文章的全部内容了,代码中写了不少的注释,大家可以动动自己的脑筋好好的理解一下。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对聚米学院的支持。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值