排序 - Java 中怎样实现一种即使元素改变依然有序的集合?
阿神
阿神 2017-04-17 17:40:57
0
2
684

一个游戏项目,服务器需要维护一个玩家的有序集合(排行榜),玩家的一些动作会改变自身的状态,比如等级改变。我希望在不使用 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);
    }
}

然后调用 AlwaysOrderedSet

AlwaysOrderedSet<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);

        alwaysOrdered.add(a);
        alwaysOrdered.add(b);
        alwaysOrdered.add(c);

        System.out.println("-- before --");
        alwaysOrdered.forEach(System.out::println);

        b.age = 100;

        System.out.println("-- after --");
        alwaysOrdered.forEach(System.out::println);

        alwaysOrdered.remove(b);
        alwaysOrdered.add(b);

        System.out.println("-- after remove and add --");
        alwaysOrdered.forEach(System.out::println);
    }
}

结果是

-- before --
id=1, name=Amy, age=50
id=3, name=Chris, age=40
id=2, name=Bob, age=30
-- after --
id=1, name=Amy, age=50
id=3, name=Chris, age=40
id=2, name=Bob, age=100
-- after remove and add --
id=2, name=Bob, age=100
id=1, name=Amy, age=50
id=3, name=Chris, age=40
id=2, name=Bob, age=100

对 b 的更改并没有改变其在集合中的位置。移除 b 再添加 b 后反而元素变多了,即一开始就移除失败了。

所以我想问一下,有没有一种模式或者类能提供一种结构使得集合中元素值变化后,通过某种回调来使集合依旧有序?

阿神
阿神

闭关修行中......

membalas semua(2)
Ty80

Anda boleh mengalih keluar elemen dahulu dan kemudian memasukkannya.
Kaedah equals dan hashCode kelas mungkin perlu dilaksanakan semula.

迷茫

Jangan risau tentang butiran penggunaan tatasusunan atau senarai terpaut.
Suatu tatasusunanint[] a=[10,6,2,0], apabila nilai unsur a[3] berubah daripada 0 kepada 7.
boleh dilakukan seperti berikut: pastikan kedudukan relatif elemen lain tidak berubah (iaitu, jangan gunakan Collections.sort()), letakkan elemen a[3] selepas a[0], dan kemudian letakkan keseluruhan elemen selepas a [0] Bergerak ke belakang satu kedudukan.

Nampak tidak bagus, tetapi memandangkan ini adalah ranking, contohnya, jika terdapat 1,000 pengguna, maka bilangan operasi di atas mesti didarabkan dengan 1,000.
Ini adalah konkurensi, yang pastinya melibatkan penguncian, jadi prestasi mungkin tidak optimistik.

Memikirkan pengalaman bermain permainan kami sendiri, kedudukan tidak dikemas kini dalam masa nyata.
Kemudian kami masih melaksanakannya melalui Collections.sort(), sekali setiap 5 minit, bukannya mengubah suai setiap kali status maklumat pengguna berubah.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan