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

JDA中遍历排序Map时异步方法致排行榜顺序错误的解决问询

问题原因

你代码里的retrieveUserById(userId).queue()是异步操作——每发起一个用户ID查询请求后,程序不会等Discord API返回结果就直接处理下一个条目。不同用户的查询响应速度不一样,回调函数的执行顺序完全和你预先排序好的sortedEntries顺序无关,这就导致最终拼接的排行榜内容顺序乱了。再加上rank.getAndIncrement()是在异步回调里执行的,排名的递增顺序跟着回调走,自然和预期的分数排序不匹配。

解决办法

推荐用CompletableFuture收集所有用户查询的结果,等全部请求完成后,再按照原排序顺序组装排行榜内容:

case "leaderboard":
    EmbedBuilder embedBuilder = new EmbedBuilder();
    embedBuilder.setTitle("Leaderboard");
    embedBuilder.setColor(Color.GREEN);

    List<Map.Entry<Long, Long>> sortedEntries = new ArrayList<>(LeaderBoardData.loadYamlFile("leaderboard.yml").entrySet());
    sortedEntries.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));
    // 只取前10条,减少不必要的API请求
    List<Map.Entry<Long, Long>> top10 = sortedEntries.stream().limit(10).collect(Collectors.toList());

    // 收集所有异步查询的结果Future
    List<CompletableFuture<String>> userNameFutures = new ArrayList<>();
    for (Map.Entry<Long, Long> entry : top10) {
        long userId = entry.getKey();
        // 提交异步查询,获取用户名的Future
        CompletableFuture<String> userNameFuture = TestBot.jda.retrieveUserById(userId)
                .submit()
                .thenApply(user -> user != null ? user.getEffectiveName() : "N/A")
                .exceptionally(error -> "N/A"); // 查询失败时返回默认值
        userNameFutures.add(userNameFuture);
    }

    // 等所有查询完成后组装消息
    CompletableFuture.allOf(userNameFutures.toArray(new CompletableFuture[0])).thenRun(() -> {
        StringBuilder leaderboardMessage = new StringBuilder();
        for (int i = 0; i < top10.size(); i++) {
            String userName = userNameFutures.get(i).join();
            long score = top10.get(i).getValue();
            // 用循环索引直接生成排名,保证顺序正确
            leaderboardMessage.append("**").append(i + 1).append("**. ")
                    .append(userName)
                    .append(": ")
                    .append(score)
                    .append("\n");
        }
        embedBuilder.setDescription(leaderboardMessage.toString());
        event.replyEmbeds(embedBuilder.build()).queue();
    });
    break;
关键改进点
  • 提前截取前10条数据,避免发起过多不必要的Discord API请求
  • 用CompletableFuture保存每个条目的查询结果,后续组装时严格对应原排序顺序
  • 直接用循环索引生成排名,彻底避免异步操作导致的排名混乱
  • 添加异常处理,单个用户查询失败不会影响整个排行榜生成

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:58:31