This question already has answers here:
Which Java Collection should I use?
                                
                                    (7个答案)
                                
                        
                                4年前关闭。
            
                    
假设我有理由要求通过多个值类型快速查找类实例,出于解释的原因,我将以游戏服务器为例。

假设服务器使用静态标识号来处理用户。此号码用于与特定玩家交流和互动(即:私人聊天,交易请求,战斗,公会邀请等)。

根据我目前的经验,这需要经常使用按其标识号查找玩家的方法,最好的方法是这样的:(如果我错了,请纠正我。)

HashMap<Integer, Player>


但是,在处理网络时,很多时候我还需要让播放器与网络会话或某些人可能更熟悉的“套接字”相关联。看起来像这样:

HashMap<Connection, Player>


所以我想找出的是,我应该走这条路线:

HashMap<Integer, Player> playersById;
HashMap<Connection, Player> playersByConnection;


还是我应该做一些“砸在一起”的事情,像这样:

HashMap<Object[], Player> playersOnline;


并以Object[0]作为整数,并以Object[1]作为连接,然后在查找过程中使用所需的那个。

还是这两种方法都是无效且不正确的,是否有更好/更快的方法可以通过Integer或Connection查找而不复制集合?

任何见识将不胜感激。

编辑:此外,有什么反对拥有相同的类引用的HashSet<>HashMap<>吗?我注意到HashSet<>的迭代效率远高于HashMap<>,并且一直保留Map进行查找和Set进行迭代,这是不好的做法吗?

最佳答案

我当然会建议您为两个不同的搜索使用单独的地图。它们确实是完全不同且独立的需求。以后您可能还需要添加新的方式来查找玩家(按名称,位置或游戏实例)。您不想回来并且继续更改现有的工作数据结构。

我的建议是将两个搜索地图都封装在包含播放器或连接列表的类中。这样,它们仅成为这些类中的内部实现细节,而无需Player类担心(例如)。

因此,例如:

class PlayerPopulation {
    private final List<Player> playerList = new ArrayList<>();
    private final Map<Player.ID, Player> playerByID = new HashMap<>();

    public void addPlayer(Player player) {
        playerList.add(player);
        playerByID.put(player.getID(), player);
    }

    public Player getPlayerByID(Player.ID id) {
        return playerByID.get(id);
    }
}


相同的模式将用于ConnectionPool(或任何称为连接容器的模式)。这样,您可以轻松地添加搜索玩家的新方法,而无需担心其他类所使用的地图结构。您还可以轻松转换为HashSet或其他任何内容,而不会在一个类之外受到任何影响。如果要使地图支持多个搜索路径,则无法执行此操作。

我也将ID更改为内部类,而不是假设Integer。我意识到您只是在举一个例子,但认为这是另一个很好封装的例子:您可以更改为Long而不用完全更改PlayerPopulation类。

因此,是的,我绝对不建议您将搜索键混在一起。

07-24 09:47
查看更多