在游戏中,我正在尝试保留用户列表并按得分进行排序,以便我可以在任何给定时间和返回(例如)按得分询问列表。此列表应为线程安全。我设想使用用户名字符串作为键,该值将是一个用户对象,可实现可比性并具有诸如DisplayName和Score之类的属性。因此,用户对象将具有一个比较方法,该方法将比较分数属性与确定其位置。

我正在考虑为此使用concurrentskiplistMap,但是我能确定的,地图(与集合相反)使用键进行排序。我想将列表按用户对象的分数属性排序,但是仍然使用地图,因为我需要能够访问任何给定的用户并从线程修改其得分属性。

似乎并没有将自己的比较器用于密钥会解决我的问题,因为我怀疑我是否可以访问相关的值进行比较。我可以使用ConcurrentsKiplistset,但是访问列表以修改单个用户的分数(我想)是一个昂贵的操作(由于每次需要迭代)。

有人会建议如何实现这一目标吗?

有帮助吗?

解决方案

不,我认为你不能。用于订购的比较器与用于索引的比较器相同。您可能必须维护2个收藏。一种用于保持用户的订购得分,以指代用户按名称。

其他提示

get(key) 取决于比较器(能够找到键)。您提出了一个依赖的比较器 get(key) (要访问基于该键比较的键的映射值)。这一定会导致无限的递归和 堆栈溢出 (在光明的一面,您正在正确的网站上发布!!)

迈克尔是对的,你不能吃蛋糕也吃;)

我认为您有3个选择:

  1. 使用地图使用户分数的更新很快,并且在排序时付出代价以找到最高的分数。
  2. 使用按分数对排序集进行排序集,以便找到最高分数很快,但是您必须在更新用户分数时付出代价
  3. 维护两个数据结构,以便您可以拥有最好的1和2。这样,您总是拥有分类的分数,并且更新用户的分数只是查找,而不是搜索。您为此付出的价格现在是您在两个地方维护一些重复的信息,尤其是考虑到并发访问,这可能会很棘手,确保两个地方始终同步更新。

我不会对1和2之间的速度更快地做出假设。我会尝试使用您的预期用法和测量以查看最坏情况。

如果您真的只对顶部N分数感兴趣,那么就有可能单独维护该列表。因此,请让您的用户名地图为每个人分数,但也要保持一小部分的最高分数(及其用户)。每次您添加/更新某人的分数时,只需检查对最高分数列表的分数,如果它比那里最小的分数大,只需添加并撞到较低的分数即可。这类似于上面的建议3,但开销较小,也许更容易维护。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top