Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在对象更改值时维护树集排序_Java_Collections_Refresh_Treeset_Sortedset - Fatal编程技术网

Java 在对象更改值时维护树集排序

Java 在对象更改值时维护树集排序,java,collections,refresh,treeset,sortedset,Java,Collections,Refresh,Treeset,Sortedset,我有一个对象,它使用Comparable定义了“自然排序顺序”。 这些被储存在树丛中 除了删除和重新添加对象之外,当用于定义排序顺序的成员被更新时,还有其他方法更新排序吗?我认为没有现成的方法可以做到这一点 您可以使用观察者模式,当您更改元素内的值时,该模式会通知树集,然后它会删除并重新插入该值 通过这种方式,您可以隐式地对列表进行排序,而无需手动操作。。当然,这种方法需要通过修改插入行为(在刚添加的项目上设置观察/通知机制)来扩展树集。唯一的内置方式是删除和重新添加。如果您确实需要使用集,那么

我有一个对象,它使用Comparable定义了“自然排序顺序”。 这些被储存在树丛中


除了删除和重新添加对象之外,当用于定义排序顺序的成员被更新时,还有其他方法更新排序吗?

我认为没有现成的方法可以做到这一点

您可以使用观察者模式,当您更改元素内的值时,该模式会通知树集,然后它会删除并重新插入该值


通过这种方式,您可以隐式地对列表进行排序,而无需手动操作。。当然,这种方法需要通过修改插入行为(在刚添加的项目上设置观察/通知机制)来扩展树集。

唯一的内置方式是删除和重新添加。

如果您确实需要使用
集,那么我想您就不走运了


不过,我要加入一个通配符-如果您的情况足够灵活,可以使用
列表而不是
集合
,那么您可以使用
Collections.sort()
按需重新排序
列表
。如果
列表
顺序不需要太多更改,则应执行此操作。

正如其他人所指出的,没有内置方式。但您始终可以使用您选择的构造函数对该树集进行子类化,并添加所需的功能:

public class UpdateableTreeSet<T extends Updateable> extends TreeSet<T> {

    // definition of updateable
    interface Updateable{ void update(Object value); }

    // constructors here
    ...

    // 'update' method; returns false if removal fails or duplicate after update
    public boolean update(T e, Object value) {
       if (remove(e)) {
           e.update(value);
           return add(e);
       } else { 
           return false;
       }
    }
}
public类UpdateableTreeSet扩展TreeSet{
//可更新的定义
接口可更新{void update(对象值);}
//这里的构造器
...
//“update”方法;如果删除失败或更新后重复,则返回false
公共布尔更新(TE,对象值){
如果(删除(e)){
e、 更新(价值);
返回add(e);
}否则{
返回false;
}
}
}

从那时起,您必须调用
((updateabletreset)mySet).update(anElement,aValue)
来更新排序值和排序本身。这确实需要您在数据对象中实现一个附加的
update()
方法。

这有助于了解对象将以小增量还是大增量进行更改。如果每个更改都很小,那么最好将数据放在一个列表中并保持排序。要做到这一点,你必须

  • binarySearch查找元素的索引
  • 修改元素
  • 当元素大于其右侧邻居时,将其与其右侧邻居交换
  • 或者,如果没有发生这种情况:当元素小于其左侧邻居时,将其与其左侧邻居交换
  • 但是你必须确保没有人可以在不经过“你”的情况下更改元素

    编辑:还有!Glassed List对这一点有一定的支持:


    我也遇到了类似的问题,找到了这个线程和tucuxi的答案(谢谢!),在此基础上我实现了自己的
    UpdateableTreeSet
    。我的版本提供了

    • 在这样一个集合上迭代
    • 计划(延迟)循环内的元素更新/删除
    • 无需创建集合的临时副本
    • 循环结束后,作为批量操作执行所有更新/删除
    UpdateableTreeSet
    对用户隐藏了很多复杂性。除了延迟的批量更新/删除外,tucuxi所示的单元素更新/删除在类中仍然可用


    更新2012-08-07:该课程提供了一些介绍性自述,其中包括原理图示例代码以及单元测试,详细说明了如何(不)使用它。

    当我试图实现类似于苹果iPhone滚轮滚动的动态滚动窗格时,我发现了这个问题。
    树集合中的项目属于此类:

    /**
     * Data object that contains a {@code DoubleExpression} bound to an item's
     * relative distance away from the current {@link ScrollPane#vvalueProperty()} or
     * {@link ScrollPane#hvalueProperty()}. Also contains the item index of the
     * scrollable content.
     */
    private static final class ItemOffset implements Comparable<ItemOffset> {
    
        /**
         * Used for floor or ceiling searches into a navigable set. Used to find the
         * nearest {@code ItemOffset} to the current vValue or hValue of the scroll
         * pane using {@link NavigableSet#ceiling(Object)} or
         * {@link NavigableSet#floor(Object)}.
         */
        private static final ItemOffset ZERO = new ItemOffset(new SimpleDoubleProperty(0), -1);
    
        /**
         * The current offset of this item from the scroll vValue or hValue. This
         * offset is transformed into a real pixel length of the item distance from
         * the current scroll position.
         */
        private final DoubleExpression scrollOffset;
    
        /** The item index in the list of scrollable content. */
        private final int index;
    
        ItemOffset(DoubleExpression offset, int index) {
            this.scrollOffset = offset;
            this.index = index;
        }
    
        /** {@inheritDoc} */
        @Override
        public int compareTo(ItemOffset other) {
            double d1 = scrollOffset.get();
            double d2 = other.scrollOffset.get();
    
            if (d1 < d2) {
                return -1;
            }
            if (d1 > d2) {
                return 1;
            }
    
            // Double expression has yet to be bound
            // If we don't compare by index we will
            // have a lot of values ejected from the
            // navigable set since they will be equal.
            return Integer.compare(index, other.index);
        }
    
        /** {@inheritDoc} */
        @Override
        public String toString() {
            return index + "=" + String.format("%#.4f", scrollOffset.get());
        }
    }
    
    其中垂直偏移是一个
    树集
    。如果你打印出
    设置每次调用此更新代码段时,您都会看到它被更新。

    这样做没有多大好处-设置可以保证快速查找、插入和删除,而列表则需要先使用Collections.binarySearch来定位元素。我意识到这一点,这就是为什么我说“如果你的情况足够灵活的话”。性能要求可能不够宽松,因此允许使用
    列表
    。@tucuxi列表中的二进制搜索为O(logn)。在树集中查找?还有O(log n)。@Kevin但是您必须完成实现add()、remove()和contains()版本的过程,这些版本在内部执行二进制搜索。本质上,您是在重新实现TreeSet,其中包含一个排序列表。这就是为什么我写道,移除和重新插入似乎更容易。不是因为性能,而是因为编码时间。我喜欢这样的想法,如果集合可以就地排序,而不是创建一个新实例。我认为这行不通。如果元素的值以影响排序顺序的方式更改,则很可能无法在树中找到或删除它。这只是病态的好奇,还是您在寻找特定的好处,比如说性能或代码的简单性?我在寻找一种简单的非侵入性方法,在事件更新集合中的对象时维护集合的排序顺序。更改成员资格会对收藏的其他消费者产生副作用。在我看来,触发元素调用似乎是排序集合的基本功能。GUI也有同样的问题,MVC就是解决方案。与
    TreeSet
    相对应的GUI会定期调用
    update
    ,或者,如果某个值发生了变化,那么控制器(观察者模式)就会被模型触发,而体系结构非常准确地指出了这一点。TreeSet是我的DOTs模型,它监听websocket jms事件,然后通过presenter/controller中继模型更新
    ItemOffset first = verticalOffsets.first();
    verticalOffsets.remove(first);
    verticalOffsets.add(first);