java jda.retrieveUserById完成后将所有用户放入List

rjzwgtxy  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(101)

我正在通过Java Discord API设计一个Discord机器人。我得到了一个服务器点系统,当用户在频道中发言时记录点。服务器点存储在一个HashMap<String, Long> points中,它使用用户的ID作为键,点作为值。我想要一个命令/ranking来显示点的排名,下面是我的代码:

List<userAndBlocks> sorted = new ArrayList<>(points.size());
JDA jda = event.getJDA();
points.forEach((userID, blocks) ->
{
    User user = jda.getUserById(userID);
    if (user == null)
        jda.retrieveUserById(userID).queue(
                user1 -> sorted.add(new UserAndBlocks(user1, blocks)),
                throwable -> sorted.add(new UserAndBlocks(jda.getSelfUser(), 0L)));
    else
        sorted.add(new UserAndBlocks(user, blocks));
});
try
{
    Thread.sleep(1000L); //wait for retrieveUserById
}
catch (InterruptedException e)
{
    e.printStackTrace();
    System.out.print('\u0007');
    FileHandle.log(e);
    System.exit(1);
}
sorted.sort((user1, user2) ->
{
    return Long.compare(user2.blocks, user1.blocks);
});

对于UserAndBlocks,它是一个记录:

public record UserAndBlocks(User user, long blocks) {}

我知道getUserById只能获取缓存的用户,所以我请求ChatGPT,它告诉我使用retrieveUserById。如您所见,我遍历了整个Map,使用retrieveUserById从用户ID获取用户,并通过Thread.sleep(1000L)使主线程休眠。为retrieveUserById方法争取一些时间。但是列表仍然没有包括我在Map中确定的所有用户。我该怎么做呢?

ccrfmcuu

ccrfmcuu1#

JDA应该使用回调策略异步使用。
这意味着您不应该阻塞任何线程和等待,而是应该在事情完成后立即处理。
在您的例子中,我看到您执行了多个rest操作,要在所有这些操作完成后执行某个操作,请使用RestAction.allOf()获取一个RestAction,该操作在所有作业完成后执行。
此外,retrieveUserById实际上将首先检查缓存,只有在用户尚未缓存时才加载用户,而不是执行逻辑,首先从缓存中获取用户,然后检查是否加载了用户。

相关问题