用Java存储和检索列表中最快的选项?

问题描述

我有一个多人游戏,服务器上有100-1000个玩家。

请考虑以下选项。哪个是存储和检索玩家的更快选择,并且这种区别有意义还是可以忽略不计?

选项1:

List<Player> players = new ArrayList<Player>();

选项2:

HashMap<String,Integer> usernamesToIds = new HashMap<String,Integer>();
List<Integer> availableIDs = new ArrayList<Integer>;
List<Integer> usedIDs = new ArrayList<Integer>();
Player[] players = new Player[1000];

对于选项1,任何时候您想按用户名获取玩家时,都必须遍历整个列表直到一个匹配,而对于选项2,您可以通过从HashMap中获取玩家的数组索引来立即获取该玩家。

要遍历第二个数组,我有包含所有非空索引的“ usedIDs”列表,您可以遍历该列表并从列表中访问数组索引。同样,使用选项1时,如果您从列表中删除一个玩家,则许多其他玩家的ID也会更改。

编辑:对不起,我添加了另一个列表,一个“ availableIDs”列表。每当添加玩家时,我都会从该列表中删除一个ID,并将其放入“ usedIDs”列表中(与删除玩家时相反),以继续为玩家分配免费ID。

解决方法

如果您期望列表中最多有1000个项目,并且搜索是偶然的(例如,由用户操作触发),而不是连续的(例如,运行游戏的每个“框架”),那么实际上就不需要做任何事情除了遍历列表之外。

players.stream().filter(p -> p.getName().equals(searchName)).findFirst();

使用映射的性能提升不值得额外的代码复杂性。将优化重点放在可以(通过探查器)看到实际性能瓶颈的区域上。

如果确实需要其他性能,请避免通过索引建议的间接访问。这非常容易出错(例如,如果您删除播放器,则需要为地图重新索引)。而是仅将玩家的名字映射到玩家对象。

Map<String,Player> players = new HashMap<>();

这可以作为玩家的主要收藏。您可以使用players.values()将其用作纯粹的玩家收藏。

如果要存储单独的玩家集合,则需要确保两个商店的完整性:确保同时添加和删除播放器。所以最好避免,除非您真的需要它。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...