欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼

 更新時(shí)間:2023年03月24日 10:56:57   作者:吳名氏  
很多項(xiàng)目中都會(huì)有一個(gè)敏感詞管理模塊,本文主要介紹了Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 前言

敏感詞過(guò)濾就是你在項(xiàng)目中輸入某些字(比如輸入xxoo相關(guān)的文字時(shí))時(shí)要能檢測(cè)出來(lái),很多項(xiàng)目中都會(huì)有一個(gè)敏感詞管理模塊,在敏感詞管理模塊中你可以加入敏感詞,然后根據(jù)加入的敏感詞去過(guò)濾輸入內(nèi)容中的敏感詞并進(jìn)行相應(yīng)的處理,要么提示,要么高亮顯示,要么直接替換成其它的文字或者符號(hào)代替。

敏感詞過(guò)濾的做法有很多,其中有比較常用的如下幾種:

1.查詢數(shù)據(jù)庫(kù)當(dāng)中的敏感詞,循環(huán)每一個(gè)敏感詞,然后去輸入的文本中從頭到尾搜索一遍,看是否存在此敏感詞,有則做相應(yīng)的處理,這種方式講白了就是找到一個(gè)處理一個(gè)。

優(yōu)點(diǎn):so easy。用java代碼實(shí)現(xiàn)基本沒(méi)什么難度。

缺點(diǎn):這效率是非常低的,如果是英文時(shí)你會(huì)發(fā)現(xiàn)一個(gè)很無(wú)語(yǔ)的事情,比如英文a是敏感詞,那我如果是一篇英文文檔,那程序它得處理多少次敏感詞?誰(shuí)能告訴我?

2.傳說(shuō)中的DFA算法(有限狀態(tài)機(jī)),也正是我要給大家分享的,畢竟感覺(jué)比較通用,算法的原理希望大家能夠自己去網(wǎng)上查查

資料,這里就不詳細(xì)說(shuō)明了。

優(yōu)點(diǎn):至少比上面那sb效率高點(diǎn)。

缺點(diǎn):對(duì)于學(xué)過(guò)算法的應(yīng)該不難,對(duì)于沒(méi)學(xué)過(guò)算法的用起來(lái)也不難,就是理解起來(lái)有點(diǎn)gg疼,匹配效率也不高,比較耗費(fèi)內(nèi)存,

敏感詞越多,內(nèi)存占用的就越大。

2 代碼實(shí)現(xiàn)

2.1 敏感詞庫(kù)初始化

在項(xiàng)目啟動(dòng)前讀取數(shù)據(jù),將敏感詞加載到Map中,具體實(shí)現(xiàn)如下:

建表語(yǔ)句:

CREATE TABLE `sensitive_word` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `content` varchar(50) NOT NULL COMMENT '關(guān)鍵詞',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
 
INSERT INTO `fuying`.`sensitive_word` (`id`, `content`, `create_time`, `update_time`) VALUES (1, '吳名氏', '2023-03-02 14:21:36', '2023-03-02 14:21:36');

實(shí)體類SensitiveWord.java:

package com.wkf.workrecord.tools.dfa.entity;
 
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
 
import java.io.Serializable;
import java.util.Date;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:48:58
 */
@Data
@TableName("sensitive_word")
public class SensitiveWord implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
 
    private String content;
 
    private Date createTime;
 
    private Date updateTime;
 
}

數(shù)據(jù)庫(kù)持久類SensitiveWordMapper.java:

package com.wkf.workrecord.tools.dfa.mapper;
 
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:50:16
 */
public interface SensitiveWordMapper extends BaseMapper<SensitiveWord> {
}

service類SensitiveWordService.java和SensitiveWordServiceImpl.java:

package com.wkf.workrecord.tools.dfa.service;
 
import com.baomidou.mybatisplus.extension.service.IService;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
 
import java.util.Set;
 
/**
 * 敏感詞過(guò)濾服務(wù)類
 * @author wuKeFan
 * @date 2023-03-02 13:47:04
 */
public interface SensitiveWordService extends IService<SensitiveWord> {
 
    Set<String> sensitiveWordFiltering(String text);
 
}
package com.wkf.workrecord.tools.dfa.service;
 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wkf.workrecord.tools.dfa.mapper.SensitiveWordMapper;
import com.wkf.workrecord.tools.dfa.SensitiveWordUtils;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
import org.springframework.stereotype.Service;
import java.util.Set;
 
/**
 * @author wuKeFan
 * @date 2023-03-02 13:48:04
 */
@Service
public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, SensitiveWord> implements SensitiveWordService{
 
    @Override
    public Set<String> sensitiveWordFiltering(String text) {
        // 得到敏感詞有哪些,傳入2表示獲取所有敏感詞
        return SensitiveWordUtils.getSensitiveWord(text, 2);
    }
}

敏感詞過(guò)濾工具類SensitiveWordUtils:

package com.wkf.workrecord.tools.dfa;
 
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
import lombok.extern.slf4j.Slf4j;
 
import java.util.*;
 
/**
 * 敏感詞過(guò)濾工具類
 * @author wuKeFan
 * @date 2023-03-02 13:45:19
 */
@Slf4j
@SuppressWarnings("unused")
public class SensitiveWordUtils {
 
    /**
     * 敏感詞庫(kù)
     */
    public static final Map<Object, Object> sensitiveWordMap = new HashMap<>();
 
    /**
     * 只過(guò)濾最小敏感詞
     */
    public static int minMatchTYpe = 1;
 
    /**
     * 過(guò)濾所有敏感詞
     */
    public static int maxMatchType = 2;
 
    /**
     * 初始化敏感詞
     */
    public static void initKeyWord(List<SensitiveWord> sensitiveWords) {
        try {
            // 從敏感詞集合對(duì)象中取出敏感詞并封裝到Set集合中
            Set<String> keyWordSet = new HashSet<>();
            for (SensitiveWord s : sensitiveWords) {
                keyWordSet.add(s.getContent().trim());
            }
            // 將敏感詞庫(kù)加入到HashMap中
            addSensitiveWordToHashMap(keyWordSet);
        }
        catch (Exception e) {
            log.error("初始化敏感詞出錯(cuò),", e);
        }
    }
 
    /**
     * 封裝敏感詞庫(kù)
     *
     * @param keyWordSet 敏感詞庫(kù)列表
     */
    private static void addSensitiveWordToHashMap(Set<String> keyWordSet) {
        // 敏感詞
        String key;
        // 用來(lái)按照相應(yīng)的格式保存敏感詞庫(kù)數(shù)據(jù)
        Map<Object, Object> nowMap;
        // 用來(lái)輔助構(gòu)建敏感詞庫(kù)
        Map<Object, Object> newWorMap;
        // 使用一個(gè)迭代器來(lái)循環(huán)敏感詞集合
        for (String s : keyWordSet) {
            key = s;
            // 等于敏感詞庫(kù),HashMap對(duì)象在內(nèi)存中占用的是同一個(gè)地址,所以此nowMap對(duì)象的變化,sensitiveWordMap對(duì)象也會(huì)跟著改變
            nowMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++) {
                // 截取敏感詞當(dāng)中的字,在敏感詞庫(kù)中字為HashMap對(duì)象的Key鍵值
                char keyChar = key.charAt(i);
 
                // 判斷這個(gè)字是否存在于敏感詞庫(kù)中
                Object wordMap = nowMap.get(keyChar);
                if (wordMap != null) {
                    nowMap = (Map<Object, Object>) wordMap;
                } else {
                    newWorMap = new HashMap<>();
                    newWorMap.put("isEnd", "0");
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }
 
                // 如果該字是當(dāng)前敏感詞的最后一個(gè)字,則標(biāo)識(shí)為結(jié)尾字
                if (i == key.length() - 1) {
                    nowMap.put("isEnd", "1");
                }
                log.info("封裝敏感詞庫(kù)過(guò)程:" + sensitiveWordMap);
            }
            log.info("查看敏感詞庫(kù)數(shù)據(jù):" + sensitiveWordMap);
        }
    }
 
    /**
     * 敏感詞庫(kù)敏感詞數(shù)量
     *
     * @return 返回?cái)?shù)量
     */
    public static int getWordSize() {
        return SensitiveWordUtils.sensitiveWordMap.size();
    }
 
    /**
     * 是否包含敏感詞
     *
     * @param txt 敏感詞
     * @param matchType 匹配類型
     * @return 返回結(jié)果
     */
    public static boolean isContainSensitiveWord(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;
    }
 
    /**
     * 獲取敏感詞內(nèi)容
     *
     * @param txt 敏感詞
     * @param matchType 匹配類型
     * @return 敏感詞內(nèi)容
     */
    public static Set<String> getSensitiveWord(String txt, int matchType) {
        Set<String> sensitiveWordList = new HashSet<>();
 
        for (int i = 0; i < txt.length(); i++) {
            int length = checkSensitiveWord(txt, i, matchType);
            if (length > 0) {
                // 將檢測(cè)出的敏感詞保存到集合中
                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<String> set = getSensitiveWord(txt, matchType);
        Iterator<String> iterator = set.iterator();
        String word;
        String replaceString;
        while (iterator.hasNext()) {
            word = iterator.next();
            replaceString = getReplaceChars(replaceChar, word.length());
            resultTxt = resultTxt.replaceAll(word, replaceString);
        }
 
        return resultTxt;
    }
 
    /**
     * 替換敏感詞內(nèi)容
     *
     * @param replaceChar 需要替換的敏感詞
     * @param length 替換長(zhǎng)度
     * @return 返回結(jié)果
     */
    private static String getReplaceChars(String replaceChar, int length) {
        StringBuilder resultReplace = new StringBuilder(replaceChar);
        for (int i = 1; i < length; i++) {
            resultReplace.append(replaceChar);
        }
        return resultReplace.toString();
    }
 
    /**
     * 檢查敏感詞數(shù)量
     *
     * @param txt 敏感詞
     * @param beginIndex 開(kāi)始下標(biāo)
     * @param matchType 匹配類型
     * @return 返回?cái)?shù)量
     */
    public static int checkSensitiveWord(String txt, int beginIndex, int matchType) {
        boolean flag = false;
        // 記錄敏感詞數(shù)量
        int matchFlag = 0;
        char word;
        Map<Object, Object> nowMap = SensitiveWordUtils.sensitiveWordMap;
        for (int i = beginIndex; i < txt.length(); i++) {
            word = txt.charAt(i);
            // 判斷該字是否存在于敏感詞庫(kù)中
            nowMap = (Map<Object, Object>) nowMap.get(word);
            if (nowMap != null) {
                matchFlag++;
                // 判斷是否是敏感詞的結(jié)尾字,如果是結(jié)尾字則判斷是否繼續(xù)檢測(cè)
                if ("1".equals(nowMap.get("isEnd"))) {
                    flag = true;
                    // 判斷過(guò)濾類型,如果是小過(guò)濾則跳出循環(huán),否則繼續(xù)循環(huán)
                    if (SensitiveWordUtils.minMatchTYpe == matchType) {
                        break;
                    }
                }
            }
            else {
                break;
            }
        }
        if (!flag) {
            matchFlag = 0;
        }
        return matchFlag;
    }
 
}

項(xiàng)目啟動(dòng)完成后執(zhí)行初始化敏感關(guān)鍵字StartInit.java:

package com.wkf.workrecord.tools.dfa;
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wkf.workrecord.tools.dfa.entity.SensitiveWord;
import com.wkf.workrecord.tools.dfa.mapper.SensitiveWordMapper;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
 
/**
 * 初始化敏感關(guān)鍵字
 * @author wuKeFan
 * @date 2023-03-02 13:57:45
 */
@Component
public class StartInit {
 
    @Resource
    private SensitiveWordMapper sensitiveWordMapper;
 
    @PostConstruct
    public void init() {
        // 從數(shù)據(jù)庫(kù)中獲取敏感詞對(duì)象集合(調(diào)用的方法來(lái)自Dao層,此方法是service層的實(shí)現(xiàn)類)
        List<SensitiveWord> sensitiveWords = sensitiveWordMapper.selectList(new QueryWrapper<>());
        // 構(gòu)建敏感詞庫(kù)
        SensitiveWordUtils.initKeyWord(sensitiveWords);
    }
 
}

2.2 編寫測(cè)試類

編寫測(cè)試腳本測(cè)試效果.代碼如下:

    @Test
    public void sensitiveWordTest() {
        Set<String> set = sensitiveWordService.sensitiveWordFiltering("吳名氏到此一游");
        for (String string : set) {
            System.out.println(string);
        }
    }

執(zhí)行結(jié)果如下:

到此這篇關(guān)于Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼的文章就介紹到這了,更多相關(guān)Java DFA敏感詞過(guò)濾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA?2022最新激活碼注冊(cè)碼超詳細(xì)教程(親測(cè)激活有效)

    IDEA?2022最新激活碼注冊(cè)碼超詳細(xì)教程(親測(cè)激活有效)

    這篇文章主要介紹了IDEA?2022最新激活碼超詳細(xì)教程(親測(cè)激活至2099年),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • java編寫汽車租賃系統(tǒng)

    java編寫汽車租賃系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java編寫汽車租賃系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java面向?qū)ο蠡A(chǔ)知識(shí)之?dāng)?shù)組和鏈表

    Java面向?qū)ο蠡A(chǔ)知識(shí)之?dāng)?shù)組和鏈表

    這篇文章主要介紹了Java面向?qū)ο蟮闹當(dāng)?shù)組和鏈表,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-11-11
  • Windows10安裝IDEA 2020.1.2的方法步驟

    Windows10安裝IDEA 2020.1.2的方法步驟

    這篇文章主要介紹了Windows10安裝IDEA 2020.1.2的方法步驟,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的真正理解

    Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的真正理解

    這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java并發(fā)編程中的synchronized關(guān)鍵字詳細(xì)解讀

    Java并發(fā)編程中的synchronized關(guān)鍵字詳細(xì)解讀

    這篇文章主要介紹了Java并發(fā)編程中的synchronized關(guān)鍵字詳細(xì)解讀,在Java早期版本中,synchronized 屬于 重量級(jí)鎖,效率低下,這是因?yàn)楸O(jiān)視器鎖(monitor)是依賴于底層的操作系統(tǒng)的Mutex Lock來(lái)實(shí)現(xiàn)的,Java 的線程是映射到操作系統(tǒng)的原生線程之上的,需要的朋友可以參考下
    2023-12-12
  • 淺析java程序入口main()方法

    淺析java程序入口main()方法

    這篇文章主要介紹了淺析java程序入口main()方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • SpringBoot + Mybatis增刪改查實(shí)戰(zhàn)記錄

    SpringBoot + Mybatis增刪改查實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于SpringBoot + Mybatis增刪改查的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入

    使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入

    這篇文章主要介紹了使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • mybatis 如何利用resultMap復(fù)雜類型list映射

    mybatis 如何利用resultMap復(fù)雜類型list映射

    這篇文章主要介紹了mybatis 如何利用resultMap復(fù)雜類型list映射的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評(píng)論