我有一个ArrayList,每秒更新一次,进行一些基本检查,并维护当前满足一系列条件的玩家列表。
我想知道执行此操作的最佳方式是我有2个提议的解决方案。
public void update() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (!playersOnLadder.contains(player)) {
if (checkPlayerOnLadder(player)) {
playersOnLadder.add(player);
}
} else {
if (checkPlayerOnLadder(player)) {
playersOnLadder.remove(player);
}
}
}
}
public void update() {
playersOnLadder.clear();
for (Player player : Bukkit.getOnlinePlayers()) {
if (checkPlayerOnLadder(player)) {
playersOnLadder.add(player);
}
}
}
在任何给定时间,此阵列列表中通常会有大约75名玩家。 “在梯子方法上检查玩家看起来像这样:
private boolean checkPlayerOnLadder(Player player) {
int ladderAbsolute = this.getX()+this.getZ();
int playerAbsolute = (int) player.getLocation().getX()+ (int) player.getLocation().getZ();
//If the player is within 4 blocks (2 in each direction) of the ladder then return true.
if (ladderAbsolute == playerAbsolute || (ladderAbsolute-2 > playerAbsolute && ladderAbsolute+2 < playerAbsolute)) {
return true;
} else {
return false;
}
}
EDITED已转换为HashSet
答案 0 :(得分:3)
如果仅限于这两个选项,那么我会使用选项编号2作为性能更高的解决方案。
在选项1中,remove
中的ArrayList
操作为O(n),因为它必须找到玩家O(n)并在找到后移除玩家,将所有人向下移动在O(n)。以这种方式循环整个玩家列表是O(n ^ 2)。
选项2只需清除以O(n)开头的列表。 add
操作是O(1)(除非需要调整大小),因此将它们全部添加也是O(n)。选项2总体为O(n)。
将ArrayList
替换为HashSet
(并在hashCode
上实施equals
和Player
)可能是一种选择。散列操作是O(1),因此遍历所有玩家并执行这些操作也是O(n)。如果您需要稍后快速找到特定Player
,请使用HashSet
,因为contains
在HashSet
中为O(1),但在ArrayList
中为O(n) {{1}}。
答案 1 :(得分:1)
请使用字典类型的数据结构进行此类记账。 HashSet(确保正确实现hashCode!)很可能是你想要的。语义和性能明智。
但是,我不明白你的阶梯和附带的算法。答案 2 :(得分:1)
最好的方法可能是使用HashSet
,Player
doesn't override hashCode
,所以HashMap<int, Player>
可以使用播放器的entityId。
这样的事情:
HashMap<int, Player> playersOnLadder; /* make sure to initialize this */
public void update() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (checkPlayerOnLadder(player)) {
playersOnLadder.put(player.getEntityId(), player);
} else {
playersOnLadder.remove(player.getEntityId());
}
}
}
因为它是HashMap
,put
多次没问题,如果给定的obejct不在地图中,HashMap.remove
可以安全地调用(它将返回{{1}但是,在这种情况下没有必要检查它。)
更好的是将代码更改为使用events。看起来PlayerJoinEvent和PlayerQuitEvent可能对您有用,无论您的null
函数是什么,都可以在响应事件时完成。
答案 3 :(得分:0)
“75名玩家”+“每秒一次”=&gt;继续前进!
你可以每秒获得几纳秒的时间,这可能会使你的代码快一点0.0000001%......
现在更快的选择可能是这个(分配通常比清算便宜):
public void update() {
// pre sizing the list saves unnecessary resizing operations.
playersOnLadder = new ArrayList<>(Bukkit.getOnlinePlayers());
for (Player player : Bukkit.getOnlinePlayers()) {
if (checkPlayerOnLadder(player)) {
playersOnLadder.add(player);
}
}
}