Java-高效的集合管理



假设我有理由要求通过多种值类型快速查找类实例,为了便于解释,我将使用游戏服务器作为示例。

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

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

HashMap<Integer, Player>

然而,在处理网络时,很多时候我还需要将播放器与网络会话关联起来,或者一些人可能更熟悉的"套接字"。看起来是这样的:

HashMap<Connection, Player>

所以我想弄清楚的是,我应该走这条路吗:

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

或者我应该做一些更"粉碎在一起"的事情,比如:

HashMap<Object[], Player> playersOnline;

并将Object[0]作为Integer,将Object[1]作为Connection,然后在查找过程中使用所需的。

或者这两种方法都不有效和不正确,有没有更好/更快的方法可以通过Integer或Connection查找它们而不复制集合?

如有任何见解,我们将不胜感激。

edit:此外,有什么不利于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。我意识到您只是举了一个例子,但认为这是另一个良好封装的例子:您可以在根本不更改PlayerPopulation类的情况下更改为Long

所以,是的,我绝对建议不要把你的搜索键混在一起。

创建一个包装器对象并将这两个对象包含在其中。创建对象时不要忘记覆盖hashMap()和equals()方法,因为您计划将其用作Map中的键。基于两个对象hashCode计算hasCode,并基于包含的实例计算equals。请参阅以下答案:equals和hashcode

首先,我必须提到宝贵的What Collection应该使用流程图。


绝对使用两个HashMap/non-;粉碎的";两个独立映射的版本,然后将其抽象到一个更高级别的类中,该类可以随意粉碎,例如使用静态实用程序函数或更有用的";用法";对象

您的第二个("粉碎")版本正试图抽象掉这种双重查找但是您需要两个快速且独立的查找不要将您在应用程序级别需要/想要的抽象强加给数据级别。

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

重复收藏可能是好事,也可能是坏事。如果它使您的代码更加优雅和易于理解,那就很好了。

过早的优化是万恶之源。

此外,有什么反对拥有HashSet<gt;以及HashMap<gt;包含相同的类引用

我注意到HashSet<gt;在迭代方面比HashMap<gt;并且一直保留一个Map用于查找和一个Set用于迭代,这是不是一种糟糕的做法

做任何这些事情都没有错,只要它能让你的代码更优雅、更容易理解

最新更新