为了账号安全,请及时绑定邮箱和手机立即绑定

Java 中怎样实现一种即使元素改变依然有序的集合?

Java 中怎样实现一种即使元素改变依然有序的集合?

精慕HU 2019-03-21 18:14:02
一个游戏项目,服务器需要维护一个玩家的有序集合(排行榜),玩家的一些动作会改变自身的状态,比如等级改变。我希望在不使用 Collections.sort() 方法的情况下维持这个集合的有序状态。我尝试了继承了 TreeSet 然后实现一个重新排序的回调 ReorderCallback,在任何玩家经验值改变的时候调用回调的方法 reorder() 来使集合(排行榜)保持有序,代码如下interface ReorderCallback<T> {    void reorder(T element);}class AlwaysOrderedSet<T> extends TreeSet<T> implements ReorderCallback<T> {    // ...    @Override    public void reorder(T element) {        remove(element);        add(element);    }}然后调用 AlwaysOrderedSetAlwaysOrderedSet<Player> set = new AlwaysOrderedSet<>();player.setExp(xxxxx);set.reorder(player);然而,每次玩家状态改变后调用 reorder() 并不能保持原集合的有序,反而会重复添加 player。因为 TreeSet 无法追踪元素的变化,就像以下的演示一样,public class Sorter {    public static void main(String[] args) {        class Student implements Comparable<Student> {            int id;            String name;            int age;            Student(int id, String name, int age) {                this.id = id;                this.name = name;                this.age = age;            }            @Override            public String toString() {                return String.format("id=%d, name=%s, age=%d", id, name, age);            }            @Override            public int compareTo(Student o) {                return o.age - this.age;            }        }        Set<Student> alwaysOrdered = new TreeSet<>();        Student a = new Student(1, "Amy", 50);        Student b = new Student(2, "Bob", 30);        Student c = new Student(3, "Chris", 40);结果是-- before --id=1, name=Amy, age=50id=3, name=Chris, age=40id=2, name=Bob, age=30-- after --id=1, name=Amy, age=50id=3, name=Chris, age=40id=2, name=Bob, age=100-- after remove and add --id=2, name=Bob, age=100id=1, name=Amy, age=50id=3, name=Chris, age=40id=2, name=Bob, age=100对 b 的更改并没有改变其在集合中的位置。移除 b 再添加 b 后反而元素变多了,即一开始就移除失败了。所以我想问一下,有没有一种模式或者类能提供一种结构使得集合中元素值变化后,通过某种回调来使集合依旧有序?
查看完整描述

2 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

先不管用数组还是链表的细节。
一个数组int[] a=[10,6,2,0],当a[3]这个元素的值从0变成7的时候。
做法可以如下:保持其它元素的相对位置不变(也就是不使用Collections.sort()),将a[3]这个元素放到a[0]后,然后将a[0]后的元素整体后移一位。

看上不不错,但是考虑到这个是排名,比如说1000个用户,那么上面的操作的次数就要乘以1000。
这里是并发,肯定得涉及到加锁,所以性能可能并不乐观。

再想想我们自己玩游戏的体验,排行榜并不是实时刷新的。
那我们还是通过Collections.sort()来实现,每5分钟一次,而不是每次用户信息状态改变后都去修改。


查看完整回答
反对 回复 2019-04-17
  • 2 回答
  • 0 关注
  • 486 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号