java DFA算法模型
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* 敏感词过滤器
*/
public class Sensitive {
/** 敏感词匹配规则 */
public final static int MINIMUM = 1; // 最小匹配规则
public final static int MAXIMUM = 2; // 最大匹配规则
private final Map<String, Object> sensitive; // 敏感词库
public Sensitive(Set<String> keywords) {
// 初始化敏感词容器,减少扩容操作
this.sensitive = new HashMap<>(keywords.size());
// 将敏感词加入到HashMap中,构建DFA算法模型
this.initialize(keywords);
}
/** 初始化敏感词库 */
@SuppressWarnings("unchecked")
private void initialize(final Set<String> keywords) {
for (String keyword : keywords) {
Map nowMap = this.sensitive;
for (int i = 0; i < keyword.length(); i++) {
char keyChar = keyword.charAt(i); // 转换成char型
Object wordMap = nowMap.get(keyChar);
if (wordMap != null) { // 存在该key则直接赋值
nowMap = (Map) wordMap;
} else { // 不存在则则构建一个map,同时将isEnd设置为0,因为他不是最后一个
Map<String, String> newWordMap = new HashMap<>((1));
newWordMap.put("isEnd", "0"); // 不是最后一个
nowMap.put(keyChar, newWordMap);
nowMap = newWordMap;
}
if (i == keyword.length() - 1) {
nowMap.put("isEnd", "1"); // 最后一个
}
}
}
}
/**
* 检查文字中是否包含敏感字符
* @param text 待检测的文本
* @param starting 开始位置
* @param match 匹配规则(1最小匹配规则;2最大匹配规则)
* @return 存在则返回敏感词字符的长度,不存在返回0
*/
private int checking(final String text, final int starting , final int match) {
boolean ending = false; // 敏感词结束标识位(用于敏感词只有1位的情况)
int matching = 0; // 匹配标识数默认为0
Map nowMap = this.sensitive;
for (int index = starting ; index < text.length(); index++) {
char word = text.charAt(index);
nowMap = (Map) nowMap.get(word); // 获取指定key
if (nowMap == null) break; // 不存在则直接返回
matching++; // 找到相应key,匹配标识+1
// 存在则判断是否为最后一个,是则结束循环,返回匹配标识数
if ("1".equals(nowMap.get("isEnd"))) {
ending = true; // 结束标志位为true
if (Sensitive.MINIMUM == match) {
break; // 最小规则,直接返回,最大规则还需继续查找
}
}
}
if (matching < 1 || !ending) { // 长度必须大于等于1
matching = 0;
}
return matching;
}
/**
* 获取文字中的敏感词
* @param text 待查找的字符串
* @param match 匹配规则(1最小匹配规则;2最大匹配规则)
*/
private Set<String> searching(final String text, final int match) {
final Set<String> sensitive = new HashSet<>(text.length());
for (int index = 0, length = text.length(); index < length ; index++) {
final int matching = this.checking(text, index, match); // 敏感字符检查
if (matching > 0) { // 存在则加入集合中
sensitive.add(text.substring(index, index + matching));
index = index + matching - 1; // 减1的原因是因为for会自增
}
}
return sensitive;
}
/**
* 判断文字是否包含敏感字符
* @param text 待检测的文本
* @param match 匹配规则(1最小匹配规则;2最大匹配规则)
*/
public final boolean contains(final String text, final int match) {
for (int index = 0, length = text.length(); index < length; index++) {
final int matching = this.checking(text, index, match);
if (matching > 0) {
return true; // 包含
}
}
return false; // 不包含
}
/**
* 使用“*”替换敏感字字符
* @param text 待替换的字符
* @param match 匹配规则(1最小匹配规则;2最大匹配规则)
*/
public final String replace(String text, int match) {
final String replace = "*";
return replace(text, match, replace);
}
/**
* 替换敏感字字符
* @param text 待替换的字符
* @param match 匹配规则(1最小匹配规则;2最大匹配规则)
* @param replace 替换字符,默认*
*/
public final String replace(final String text, final int match, final String replace) {
String result = text;
// 获取所有的敏感词
final Set<String> sensitive = this.searching(text, match);
// 替换同等长度的字符
for (String element : sensitive) {
final int length = element.length();
final String newing = this.newing(replace, length);
result = result.replaceAll(element, newing);
}
return result;
}
/**
* 获取替换字符串
* @param replace 替换字符
* @param length 替换长度
*/
private String newing(final String replace, final int length) {
final StringBuilder builder = new StringBuilder();
for (int index = 0; index < length; index++) {
builder.append(replace);
}
return builder.toString();
}
}
java 得dfa敏感词过滤算法!供大家参考!

浙公网安备 33010602011771号