TreeSet 或 TreeMap 自动排序,当底层对象的字段值改变时

TreeSet or TreeMap auto sort, when the underlying object's field value changes

是否有任何内置集合,其中对象按排序顺序排序?并且在更改存储对象的字段(用于确定顺序)时,集合将其自身重新排列为排序顺序。

集合的底层对象是可变的

请参考下面的例子。

 Emp implements Comparable<Emp> {
      Integer id;
      Emp(int id) {
        this.id = id;
      }
      public Integer getId() {
        return id;
      }
      public void setId(Integer id) {
        this.id = id;
      }
      @Override
      public int compareTo(Emp o) {
        return this.id.compareTo(o.id);
      }
    }

    Emp e1 = new emp(1);
    Emp e2 = new emp(2);
    Emp e3 = new emp(3);
    Set<Emp> sortedSet = new TreeSet<Emp>();
    sortedSet.add(e1);
    sortedSet.add(e2);
    sortedSet.add(e3);
    // till now object is in sorted order
    e2.setId(10);
    // I need some method of the collection to make it sorted again.

我需要 sortedSet 再次按排序顺序(通过调用某种方法)并且在 e2 更改后顺序为 e1、e3、e2。

如果没有可用的内置 class,请给出一些提示,以最小的时间复杂度有效地解决问题。

不,您不能只改变映射或集合中的键;这会破坏 map/set.

中的未来查找

您应该为地图使用不可变的排序键,并且在更新对象时,先从地图中删除该项目,然后使用更新后的排序键将其放回地图中。

不存在这样的集合。但是你可以使用观察者模式在集合中的对象发生变化时自动 remove/replace 。最好在更新发生之前将其删除,然后再将其替换。

如果您以更改元素字段的方式改变元素,几乎所有 Set 的标准实现都将不起作用。例如,HashSet 使用 hashCode 将条目放入桶中,因此如果您在将元素放入 Set 后对其进行变异,将无法再找到它。类似地,TreeSet 使用 Comparator(通常在元素的字段上使用)将元素放置在树中,因此您会遇到类似的问题。

所以你尝试做的事情是行不通的。您可以做的是使用 ArrayList 来存储元素,并在需要顺序时简单地对 List 进行排序。当然,这不会始终保持元素有序。但是,无论如何这都是不可能的,因为集合不会收到元素更改的通知。

您可以从集合中删除对象,修改其值,然后在字段值更改后将其添加回集合。一旦您添加回对象,树集将再次对其进行排序。这是我在这个用例中能想到的最好的。