You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中使用*与#通配符实现主题匹配的问题排查

修复井号(#)通配符的主题匹配逻辑

你的代码里#通配符失效的核心问题有两个:

  • 只对比了分段长度相同的主题,但#的设计目标是匹配当前层级及所有子层级,比如t1.#需要匹配t1.t3.t5这种更长的主题
  • 对#的处理逻辑不符合发布订阅主题的规则:#必须是主题的最后一个分段,且匹配到#后,后续所有层级都直接视为匹配

修改后的完整代码

public List<Topic> getMatchingTopics(Topic topic, List<Topic> currentTopics) {
    List<Topic> matchingTopics = new ArrayList<>();
    String topicString = topic.getName();
    String[] topicSegments = topicString.split("\\.");
    boolean hasHash = false;
    boolean hasStar = false;

    // 提前检查#的合法性:如果有#,必须是最后一个分段
    if (topicSegments.length > 0 && topicSegments[topicSegments.length - 1].equals("#")) {
        hasHash = true;
        // 如果#不是唯一的分段,前面不能有其他通配符(可选,根据业务规则调整)
        for (int i = 0; i < topicSegments.length - 1; i++) {
            if (topicSegments[i].equals("*") || topicSegments[i].equals("#")) {
                return matchingTopics; // 非法格式直接返回空
            }
        }
    } else {
        // 检查是否包含*通配符
        for (String seg : topicSegments) {
            if (seg.equals("*")) {
                hasStar = true;
                break;
            }
        }
    }

    for (Topic t : currentTopics) {
        String currentTopicString = t.getName();
        // 完全匹配的情况直接加入结果
        if (topicString.equals(currentTopicString)) {
            matchingTopics.add(t);
            continue;
        }

        String[] currentSegments = currentTopicString.split("\\.");

        if (hasHash) {
            // #的匹配逻辑:前缀分段完全匹配,且当前主题分段数不少于前缀长度
            int hashPrefixLength = topicSegments.length - 1;
            if (currentSegments.length < hashPrefixLength) {
                continue;
            }
            boolean match = true;
            for (int i = 0; i < hashPrefixLength; i++) {
                if (!topicSegments[i].equals(currentSegments[i])) {
                    match = false;
                    break;
                }
            }
            if (match) {
                matchingTopics.add(t);
            }
        } else if (hasStar) {
            // *的匹配逻辑:分段长度相等,每个分段要么是*要么完全匹配
            if (topicSegments.length != currentSegments.length) {
                continue;
            }
            boolean match = true;
            for (int i = 0; i < topicSegments.length; i++) {
                if (topicSegments[i].equals("*")) {
                    continue;
                }
                if (!topicSegments[i].equals(currentSegments[i])) {
                    match = false;
                    break;
                }
            }
            if (match) {
                matchingTopics.add(t);
            }
        }
    }

    return matchingTopics;
}

关键修改说明

  1. #合法性校验:提前判断#是否在主题末尾,避免t1.#.t2这类非法格式的主题干扰匹配(如果业务允许特殊格式可删除此校验)
  2. #专属匹配逻辑:
    • 提取#前面的前缀分段(比如t1.#的前缀是t1)
    • 只要待匹配主题的分段数不少于前缀长度,且前缀完全匹配,就视为匹配
    • 这样t1.t2(2段)、t1.t3.t5(3段)都会被t1.#命中
  3. 拆分通配符处理:把#和*的匹配逻辑分开,避免互相干扰,代码可读性更强
  4. 提前提取通配符信息:在循环外部先判断查询主题的通配符类型,避免每次循环重复拆分和判断

测试验证

运行你的测试方法后,t1.#会输出全部5个主题,t1.*会输出t1.t2、t1.t3、t1.t4三个主题,完全符合预期。

内容的提问来源于stack exchange,提问作者wazowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:45:59