Сохранение сортировки TreeSet как значения изменения объекта
У меня есть объект, который определяет "естественный порядок сортировки", используя Comparable < > .
Они хранятся в TreeSets.
Помимо удаления и повторного добавления объекта, существует ли другой способ обновления сортировки, когда обновляются члены, которые используются для определения порядка сортировки?
Ответы
Ответ 1
Как отмечали другие, нет встроенного способа. Но вы всегда можете подклассифицировать этот TreeSet с помощью вашего конструктора (ов) выбора и добавить необходимую функциональность:
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;
}
}
}
С этого момента вам нужно будет вызвать ((UpdateableTreeSet)mySet).update(anElement, aValue)
для обновления значения сортировки и самой сортировки. Это требует, чтобы вы реализовали дополнительный update()
метод в объекте данных.
Ответ 2
У меня была аналогичная проблема, я нашел эту ветку и ответ tucuxi (спасибо!), на основе которой я реализовал свой собственный UpdateableTreeSet
. Моя версия предоставляет средства для
- итерации по такому набору,
- расписание (отложенное) обновление/удаление элементов из цикла
- не создавая временную копию набора и, наконец,
- делать все обновления/удаления как объемную операцию после завершения цикла.
UpdateableTreeSet
скрывает большую часть сложности от пользователя. В дополнение к отложенным массовым обновлениям/абзацам одноэлементное обновление/удаление, как показано tucuxi, по-прежнему доступно в классе.
Обновление 2012-08-07: класс доступен в небольшом репозитории GitHub, включая вводный README со схематическим примером кода, а также блок тесты, показывающие, как (не) использовать его более подробно.
Ответ 3
Если вам действительно нужно использовать Set
, то вам не повезло, я думаю.
Я собираюсь использовать подстановочный знак, хотя, если ваша ситуация достаточно гибкая, чтобы работать с List
вместо Set
, вы можете использовать Collections.sort()
для повторной сортировки List
по требованию. Это должно быть выполнено, если порядок List
не должен сильно меняться.
Ответ 4
Это помогает узнать, будут ли ваши объекты изменяться небольшими приращениями или большими. Если каждое изменение очень мало, вы бы очень хорошо поместили свои данные в список, который вы сохранили. Для этого вам нужно
- binarySearch, чтобы найти индекс элемента
- изменить элемент
- в то время как элемент больше, чем его правый сосед, поменяйте его своим правым соседом
- или если этого не произошло: в то время как элемент меньше, чем его левый сосед, замените его своим левым соседом.
Но вы должны убедиться, что никто не может изменить элемент, не пройдя "вы", чтобы сделать это.
EDIT: Также! Глазированные списки имеют определенную поддержку только для этого:
http://publicobject.com/glazedlists/glazedlists-1.5.0/api/ca/odell/glazedlists/ObservableElementList.html
Ответ 5
Я искал эту проблему, когда пытался реализовать панель кинетической прокрутки, похожую на свитки для iPhone Apple. Элементы в TreeSet
относятся к этому классу:
/**
* 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());
}
}
DoubleExpression
может потребоваться некоторое время для выполнения задачи runLater платформы JavaFX, поэтому индекс включен в этот класс оболочки.
Так как scrollOffset
всегда изменяется в зависимости от положения прокрутки пользователя на колесе прокрутки, нам нужен способ обновления. Обычно порядок всегда один и тот же, поскольку смещение относительно позиции позиции элемента. Индекс никогда не изменяется, но смещение может быть отрицательным или положительным в зависимости от относительного расстояния элементов от текущего значения vValue или hValue объекта ScrollPane
.
Чтобы обновить по требованию только при необходимости, просто следуйте указаниям вышеупомянутого ответа Tucuxi.
ItemOffset first = verticalOffsets.first();
verticalOffsets.remove(first);
verticalOffsets.add(first);
где verticalOffsets - это TreeSet<ItemOffset>
. Если вы распечатываете
каждый раз, когда вызывается этот фрагмент обновления, вы увидите, что он обновлен.
Ответ 6
Только встроенный способ заключается в удалении и повторном добавлении.
Ответ 7
Я не думаю, что есть готовый способ сделать это.
Вы можете использовать шаблон наблюдателя, который уведомляет деревья, когда вы меняете значение внутри элемента, затем удаляет и повторно вставляет его.
Таким образом, вы можете неявно сохранить список отсортированным, не заботясь об этом вручную. Конечно, этот подход должен будет расширить TreeSet
, изменив поведение вставки (установив наблюдаемую/уведомляющую механику только что добавленную пункт)