ConcurrentSkipListMap排序:可以通过value的compareTo来完成吗?

发布于 2024-09-24 12:11:38 字数 482 浏览 6 评论 0原文

在游戏中,我试图保留用户列表并按分数排序,以便我可以在任何给定时间查询该列表并返回(例如)按分数排名前十的用户。该列表应该是线程安全的。我设想使用 userName 字符串作为键,值将是一个实现 Comparable 并具有 displayName 和 Score 等属性的 User 对象。因此,User 对象将具有一个compareTo 方法,该方法将比较分数属性以确定其位置。

我正在考虑使用 ConcurrentSkipListMap 来实现此目的,但据我所知,Map(而不是 Set)使用键进行排序。我希望按 User 对象的分数属性对列表进行排序,但仍然使用 Map,因为我需要能够访问任何给定的用户并从线程修改他们的分数属性。

使用我自己的比较器作为键似乎并不能解决我的问题,因为我怀疑我是否有权访问关联的值进行比较。我可以使用 ConcurrentSkipListSet,但访问列表来修改单个用户的分数将是(我认为)一项昂贵的操作(因为每次都需要迭代)。

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

In a game, I'm trying to keep a list of users and have it sorted by score, so that I could query the list at any given time and return (for example) the top ten users by score. This list should be thread-safe. I envision using the userName string as a key and the value would be a User object which implements Comparable and has properties such as displayName and score. The User object would therefore have a compareTo method which would compare the score attribute to determine its position.

I'm looking at using a ConcurrentSkipListMap for this, but as best I can tell, the Map (as opposed to the Set) uses the key to sort. I'd like to have the list sorted by the score property of the User object, but still use a Map because I need to be able access any given user and modify their score attribute from a thread.

It doesn't seem that using my own Comparator for the key would solve my problem, as I doubt I'd have access to the associated value for comparison. I could use a ConcurrentSkipListSet but accessing the list to modify an individual user's score would be (I would imagine) an expensive operation (due to the need to iterate every time).

Would anyone be able to suggest how to accomplish this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤单情人 2024-10-01 12:11:38

不,我认为你不能。用于排序的比较器与用于索引的比较器相同。您可能需要维护 2 个集合。一种用于保持用户分数的排序,一种用于按名称引用用户。

No, I don't think you can. The comparator used for ordering is the same one used for indexing. You will probably have to maintain 2 collections. One for keeping the ordering of user's scores the for referring to the users by name.

没有你我更好 2024-10-01 12:11:38

get(key) 取决于比较器(能够找到密钥)。您建议一个依赖于 get(key) 的比较器(访问键的映射值并基于该值进行比较)。这必然会导致无限递归和堆栈溢出(好的一面是,您在正确的网站上发帖!!)

get(key) depends on the comparator (to be able to locate the key). You propose a comparator that would depend on get(key) (to access the mapped value of a key an compare based on that). That necessarily leads to infinite recursion and stack overflow (on the bright side, you are posting at the right website!!)

笙痞 2024-10-01 12:11:38

迈克尔是对的,鱼和熊掌不可兼得;)

我认为你有 3 个选择:

  1. 使用地图,以便快速更新用户的分数,并且在排序以查找最高分时付出代价。
  2. 使用按分数排序的SortedSet,这样找到最高分数的速度很快,但是更新用户分数时必须付出代价
  3. 维护两个数据结构,这样就可以得到1和2中最好的。例如,你有你的真实分数集合中的数据按分数排序,但随后还维护用户名到集合或类似索引的映射。这样您就始终拥有排序后的分数,并且更新用户的分数只是查找,而不是搜索。您为此付出的代价是现在您在两个地方维护一些重复的信息,特别是考虑到并发访问,确保两个地方始终同步更新可能很棘手。

我不会假设 1 和 1 之间哪个更快。 2. 我会根据您的预期用法来尝试它们,并进行衡量,看看最糟糕的是什么。

如果您确实只对前 n 个分数感兴趣,那么可以单独维护该列表。因此,让你的用户名地图为每个人评分,但也要维护一小部分最高分(及其用户)。每次添加/更新某人的分数时,只需对照最高分数列表检查分数,如果它比那里最小的分数大,只需添加它并删除较低的分数即可。这与上面的建议 3 类似,但开销更少并且可能更容易维护。

Michael is right, you can't have your cake and eat it too ;)

I think you have 3 choices:

  1. Use a Map so that updates to a user's score are quick, and you pay the price when sorting to find the highest scores.
  2. Use a SortedSet that sorts by score so that finding the highest scores is fast, but you must pay the price when updating user's scores
  3. Maintain two data structures, so that you can have the best of 1 and 2. For example, you have your real data in a set sorted by score, but then also maintain a mapping of username to index into the set or similar. That way you always have the sorted scores, and updating a user's score is just a lookup, not a search. The price you pay for this is now you are maintaining some duplicate information in two places, and especially considering concurrent access, it can be tricky ensuring both places are always updated in synch.

I would not make assumptions about which is faster between 1 & 2. I would try them both out with your expected usage and measure to see what is worst.

If you are really only interested in the top n scores, then there is the possibility to just maintain that list separately. So have your map of username to score for everyone, but also maintain a small set of the top scores (and their users). Every time you add/update someone's score, just check the score against the top score list, and if it's bigger than the smallest one there, just add it and bump off the lower one. This is similar to suggestion 3 above, but is less overhead and perhaps easier to maintain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文