最近想自己搞点事情,就看到了敏感词过滤,搜索网络上面的过滤方法,很多,虽然说有轮子了,但是还是想自己造一个,看看能不能把速度优化一下
我写的方法直接对敏感词进行替换,不包含查询文章中有的敏感词等其他方法,如果有想写的请自行书写,这个对于我来说就够用了
不多说了,直接上代码吧
package Util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 敏感词过滤 基于DFA算法,时间复杂度我不会算,最快只需要读一遍文章即可,最差相当于读两遍文章
* @ClassName: SensitiveFiltering
* @Description: TODO(敏感词过滤)
* @author toy
* @date 2017年1月5日 下午4:51:23
*
*/
public class SensitiveFiltering {
public HashMap SensitiveMap = null;
@SuppressWarnings({ "rawtypes", "unchecked" })
private void addSensitiveWordToHashMap(Set<String> keyWordSet) {
// 敏感词map集合
SensitiveMap = new HashMap(keyWordSet.size()); // 初始化敏感词容器,减少扩容操作
// 迭代keyWordSet
Iterator<String> iterator = keyWordSet.iterator();
while (iterator.hasNext()) {
//敏感词字符串
String key = iterator.next();
//生成敏感词节点的map,一直是最里面的节点
Map nowMap = SensitiveMap;
//开始分词
for (int i = 0; i < key.length(); i++) {
//取出对应字符
char keyChar = key.charAt(i);
//查找当前子map里面是否有存在的key
Object wordMap = nowMap.get(keyChar);
// 如果存在该key,直接赋值
if (wordMap != null) {
nowMap = (Map) wordMap;
} else {
// 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
Map<String, Boolean> newWorMap = new HashMap<String, Boolean>();
// 不是最后一个
newWorMap.put("isEnd", false);
// 把节点添加到子map中
nowMap.put(keyChar, newWorMap);
//因为要设置下一个节点,所以要把当前子节点设置的节点传递给即将生成节点的map
nowMap = newWorMap;
}
if (i == key.length() - 1) {
//如果是最后一个,根据map特性,直接用相同key替换掉
nowMap.put("isEnd", true);
}
}
}
}
/**
* 本方法想法来自网络,集合生成算法由网络中@author chenming 实现
* 替换算法是在网络上面看到的一个想法,自己想搞定
* 时间复杂度我也不知道是多少,最差情况是每个字读两次,最优情况则过一边文章即可
* 模拟过滤31114个字符完成全部替换需要50毫秒左右
* 暂时没有发现漏查情况
*
* @Title: checkSensitive
* @Description: TODO(检查并替换敏感词)
* @param @param param 需要检查的字符串
* @param @param replaceString 替换的字符
* @author toy
* @return String 返回类型
* @throws
*/
public String checkSensitive(String param, String replaceString) {
//敏感词子节点
Map nowMap = SensitiveMap;
//是否开始匹配敏感词标示
boolean startflag = false;
//敏感词匹配是否结束标示
boolean endflag =false;
//是否完成匹配标示
boolean flag = true;
//最终生成对象sb对象
StringBuffer sb = new StringBuffer();
//临时变量,用来存储可能是敏感词的字
StringBuffer temp1 = new StringBuffer();
//临时变量,用来存储可能是敏感词的字的替换符号
StringBuffer temp2 = new StringBuffer();
for(int i=0;i<param.length();i++){
//得到单个字
char p = param.charAt(i);
//查找是否在集合中
nowMap = (Map) nowMap.get(p);
//如果有敏感词开头,应该记录下来当前位置开始之后的数据,并且不能直接保存到sb对象中
if(nowMap != null){
//先把字和对应的替换符号记录下来
temp1.append(p);
temp2.append(replaceString);
//修改是否开始匹配状态为开始
if(!startflag){
startflag=true;
}
//是否完成匹配标示
flag = false;
//判断是否是敏感词
if((Boolean)nowMap.get("isEnd")){
//敏感词匹配结束
endflag = true;
//把敏感词map重新赋值
nowMap = SensitiveMap;
}
}else{
//记录不进入敏感词的单词
temp1.append(p);
//设置是否敏感词为false
endflag = false;
//设置是否完成匹配,因为都不是敏感词,所以是完成匹配
flag = true;
//把敏感词map重新赋值
nowMap = SensitiveMap;
}
//判断是否已经开始进行敏感词匹配了
if(startflag){
//有开始有结尾,那么这个是敏感词,追加成*号
if(endflag){
// System.out.println(temp2.toString()+"----2");
sb.append(temp2.toString());
startflag=false;
endflag =false;
temp1.delete(0, temp1.length());
temp2.delete(0, temp2.length());
}else{//否则的话在判断是否已经完成敏感词匹配,如果完成了那么证明不是敏感词,直接把词追加进sb对象中
if(flag){
// System.out.println(temp1.toString()+"----1");
sb.append(temp1.toString());
startflag=false;
endflag =false;
temp1.delete(0, temp1.length());
temp2.delete(0, temp2.length());
}else{//如果没有完成敏感词匹配,可能是单个字,需要判断是否能组成一个词
if(nowMap.get(param.charAt(i+1))==null){//不能组成那么就直接追加到sb对象,能则不处理,继续执行循环
sb.append(temp1.toString());
startflag=false;
endflag =false;
temp1.delete(0, temp1.length());
temp2.delete(0, temp2.length());
//把敏感词map重新赋值
nowMap = SensitiveMap;
}
}
}
}else{//如果都没有进入匹配敏感词,那么直接追加即可
// System.out.println(temp1.toString()+"----1");
sb.append(temp1.toString());
startflag=false;
endflag =false;
temp1.delete(0, temp1.length());
temp2.delete(0, temp2.length());
}
}
return sb.toString();
}
public Set<String> readSensitiveWordFile() throws Exception{
Set<String> set = null;
File file = new File("D:\\222.txt"); //读取文件
InputStreamReader read = new InputStreamReader(new FileInputStream(file),"GBK");
try {
if(file.isFile() && file.exists()){ //文件流是否存在
set = new HashSet<String>();
BufferedReader bufferedReader = new BufferedReader(read);
String txt = null;
while((txt = bufferedReader.readLine()) != null){ //读取文件,将文件内容放入到set中
set.add(txt);
}
}
else{ //不存在抛出异常信息
throw new Exception("敏感词库文件不存在");
}
} catch (Exception e) {
throw e;
}finally{
read.close(); //关闭文件流
}
return set;
}
public String readSensitiveWordFiles() throws Exception{
StringBuffer sb = new StringBuffer();
File file = new File("D:\\ceshi.txt"); //读取文件
InputStreamReader read = new InputStreamReader(new FileInputStream(file),"GBK");
try {
if(file.isFile() && file.exists()){ //文件流是否存在
BufferedReader bufferedReader = new BufferedReader(read);
String txt = null;
while((txt = bufferedReader.readLine()) != null){ //读取文件,将文件内容放入到set中
sb.append(txt);
}
}
else{ //不存在抛出异常信息
throw new Exception("敏感词库文件不存在");
}
} catch (Exception e) {
throw e;
}finally{
read.close(); //关闭文件流
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
//Set<String> str = new HashSet<String>();
//str.add("嘻嘻");
SensitiveFiltering s = new SensitiveFiltering();
Set<String> str = s.readSensitiveWordFile();
s.addSensitiveWordToHashMap(str);
//System.out.println(s.SensitiveMap.toString());
String temp = s.readSensitiveWordFiles();
System.out.println(temp.length());
long start = System.currentTimeMillis();
String txt = s.checkSensitive(temp,"*");
System.out.println(txt);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}