当前位置: 首页 > 知识库问答 >
问题:

Java-高效的集合管理[重复]

郎曜文
2023-03-14

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

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

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

HashMap<Integer, Player>

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

HashMap<Connection, Player>

所以我想知道的是,我应该走这条路吗

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

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

HashMap<Object[], Player> playersOnline;

并将对象[0]作为整数,将对象[1]作为连接,然后使用查找过程中需要的连接。

或者这两种方法都不完善且不正确,是否有更好/更快的方法通过整数或连接查找它们,而不复制集合?

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

编辑:还有,有什么反对HashSet的吗

共有3个答案

爱亮
2023-03-14

首先,我必须提到无价的我应该使用什么集合流程图。

对于两个独立的映射绝对使用两个HashMap/非“粉碎”版本,然后将其抽象到一个更高级别的类中,该类可以根据您的喜好进行粉碎——例如使用静态实用程序函数或更有帮助的“用法”对象。

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

或者这两种方法都是无效和不正确的,是否有更好/更快的方法通过整数或连接查找它们而不重复集合?

复制收藏可能是好事,也可能是坏事。如果它能让你的代码更加优雅易懂,那就好了。

过早优化是万恶之源。

还有,有什么反对HashSet的吗

我注意到哈希集

做任何这些事情都没有错,只要它使您的代码更加优雅和易于理解。

墨宜人
2023-03-14

创建一个包装器对象并将这两个对象包含在其中。创建对象时不要忘记重写hashMap()和equals()方法,因为您计划将其用作映射中的键。基于两个对象hashCode计算hasCode,并基于包含的实例计算equals。看这个答案:等于和哈希代码

鞠修雅
2023-03-14

我当然建议您为两种不同的搜索使用不同的地图。它们确实是完全不同和独立的需求。稍后您可能还需要添加新的方式来查找玩家(按名称、位置或游戏实例)。您不希望必须返回并不断更改现有的工作数据结构。

我的建议是将两个搜索映射封装在包含玩家或连接列表的类中。这样,它们就变成了这些类中的内部实现细节,而不是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);
    }
}

相同的模式将用于连接池(或连接容器的任何调用)。通过这种方式,你可以轻松添加搜索玩家的新方法,而无需任何其他类担心你正在使用的地图结构。您还可以轻松地转换为哈希集或任何其他内容,而不会影响一个类之外的任何内容。如果您试图使地图支持多个搜索路径,则无法做到这一点。

我还将ID更改为内部类,而不是假设整数。我意识到您只是举了一个例子,但认为这是另一个良好封装的例子:您可以更改为Long而无需更改Player人口类。

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

 类似资料:
  • 问题内容: 高度重复的代码通常是不好的事情,并且有些设计模式可以帮助最大程度地减少这种情况。但是,由于语言本身的限制,有时这是不可避免的。从以下示例: 上面的片段出现在源代码的8倍,具有非常小的变化中的文档/方法签名但 完全相同的方法体 ,一个用于每个根数组类型,,,,,,,和。 我相信,除非有人诉诸反思(本身是完全不同的主题),否则这种重复是不可避免的。我知道作为实用程序类,如此大量的重复Jav

  • 具体来说,我需要一个使用一个字段A进行访问和一个不同的字段(字段S)进行排序的集合,但是一个接受重复的排序集合就足够了。 我经常需要这个集合,而TreeMap不是一个选项,因为它不允许重复。所以现在是时候问这里了。正如在这里和这里的stackoverflow中指出的,有几个变通方法,即: PriorityQueue:缓慢更新(删除(对象)添加(对象)),基本键装箱 斐波那契堆:内存浪费(?)

  • 问题内容: 我有一系列相互配合的XSL 2.0样式表,即样式表A的输出提要B的提要C的提要。 最有效的方法是什么?改写的问题是:如何将一个转换的输出有效地路由到另一个转换。 这是我的第一次尝试: 如您所见,我正在使用DOM来进行转换之间的转换,尽管它很方便,但它并不是最佳的性能。 有没有简单的方法可以说,将SAXResult路由到SAXSource?StAX解决方案将是另一种选择。 我知道像XPr

  • 集合类专门用于数据存储和数据检索,并提供堆栈、队列、列表和哈希表的支持。目前,大多数集合类都实现了相同的接口。 集合类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等,这些类所创建的是 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。 各种集合类及其用法 下表为一些常用的以 System.Collection 为命名空间的集合类,点击相应链接,可查看

  • 问题内容: 这个问题的最高答案描述了一种在Java中实现有效的XSLT管道的技术: [Java中有效的XSLT管道(或将结果重定向到源)http://codingdict.com/questions/155853 不幸的是,尽管Transformer似乎公开了用于设置XSLT参数的API,但这似乎没有任何效果。例如,我有以下代码: 变形金刚 MyStylesheet1.xslt MyStylesh

  • 好的,所以我是新来的,我坚持想出一个解决这个问题的好方法。所以我正在使用slick2d在Java创建一个RPG自上而下的生存游戏。在游戏中生成物品时,我有一个问题。管理数百个物品的最佳方法是什么...一个例子;我有一个名为PickUpItems的物品子类。例如,当一棵树被玩家摧毁时,它会生成一个PickUpItem,它只是一个带有矩形框以进行碰撞的图像。选择要生成的物品而不必为每个互动物品(树、灌