Java 多字符串同时匹配文本,消耗 CPU 过高,如何优化?

查看 120|回复 8
作者:print1024   
本人遇到一个性能方法的问题,这是打标的场景,主要逻辑是三个循环,YYDTO 中有段文本,XXDTO 中有关键词列表,XXDTOList 量级大约 10 万条必须执行,判断关键词列表是否全部在文本中存在,如果存在则执行业务逻辑;
目前测试了 stream 、parallelStream 、正则和原生的 for 循环,发现下面 checkExistRule 是最快的,大约 50ms ,但是会一直消耗大量 CPU (串行下一直占用 100%)。之前还考虑使用 AC 自动机,但是因为单条匹配到还要处理业务逻辑,所以不太合适。
text 举例 :
"#DIESEL 大牌好友# @宋雨琦_G-I-DLE 演绎#DIESEL2023 秋冬系列# 牛仔坠饰 D-VINA 包袋。渐变丹宁渲染不羁格调,另类包型注解无畏想象"
keywordRule 中举例:
[鼎赛龙, 男士春夏, D-FINING, 深灰色, 锥形牛仔裤] string[]
[DIESEL, 男士春夏, DFINING, 深灰色, 锥形牛仔裤] string[]
上面这是关键词列表中的一个,总共 10 万个,也就是 10 万个 List 中每个 List 包含 N  个字符串数组
请问有什么方式进行优化?能不能做到时间复杂度 O(1) 或者 O(m + n)级别?
    for (YYDTO yydto : YYDTOList) { //2000
        String text = yydto.getText();
        for (XXDTO xxdto : XXDTOList) {//10w
          List keywordRule = xxdto.getKeywordRule();
            if (checkExistRule(keywordRule, text)) {
                // 处理业务逻辑
                // yydto.set(xxdto.getName());
            }
        }
    }
    private boolean checkExistRule(List keywordRule, String text) {
        try {
            for (String[] strings : keywordRule) {
                for (String string : strings) {
                    if (!text.contains(string)) {
                        return false;
                    }
                }
                return true;
            }
        } catch (Exception e) {
            
        }
        return false;
    }
   

string, yydto, xxdto, Text

liprais   
你想的太简单了
建议再想想
比如你这 10w 敏感词必须一个一个判断么?
有没有可能搞成前缀树?
BiChengfei   
试试 parallelStream ?
感觉现在还可以啊,不算慢,资源消耗也还可以,关键实现简单,好维护
print1024
OP
  
@liprais 这是一个打标的场景,如果关键词全部包含则打上这个标签,考虑过建树但是匹配完如何知道是哪个关键词规则命中呢
print1024
OP
  
@BiChengfei parallelStream CPU 测试消耗比较大,我们线上 CPU 就 2 核,直接就打满了
xtreme1   
ac + double array trie
alva0   
改下设计?先将所有关键字去重,放在一个有序集合中,XXDTOList 中的关键字列表存下标,每次 YYDTO 先判断关键字集合,取出包含的所有下标,再与 XXDTOList 比较下标是否存在?这样子试下呢
zizon   
YYDTOList.steram().flatmap((yydto)=>{
XXDTOList.stream().flatmap(::getKeywordRule()::stream()).flatmap((keyword)=>{
return Map.Entry(keyword,yydto)
})
}).filter((entry)=>{
return entry.values.contains(keyword)
}).foreach()
如果不改数据结构/算法本身的话.
zizon   
@zizon 哦,没有 early terminate.忽略.
您需要登录后才可以回帖 登录 | 立即注册

返回顶部