Ich habe ein Objekt, das mit Comparable <> eine 'natürliche Sortierreihenfolge' definiert. Diese werden in TreeSets gespeichert.
Gibt es neben dem Entfernen und erneuten Hinzufügen des Objekts eine andere Möglichkeit, die Sortierung zu aktualisieren, wenn die Elemente, die zum Definieren der Sortierreihenfolge verwendet werden, aktualisiert werden?
TreeSet
Anrufenupdate
in regelmäßigen Abständen entspricht, oder der Controller (Beobachtermuster) wird vom Modell ausgelöst, wenn sich ein Wert ändertAntworten:
Wie andere angemerkt haben, gibt es keinen eingebauten Weg. Sie können dieses TreeSet jedoch jederzeit mit den von Ihnen ausgewählten Konstruktoren unterklassifizieren und die erforderlichen Funktionen hinzufügen:
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; } } }
Von da an müssen Sie aufrufen
((UpdateableTreeSet)mySet).update(anElement, aValue)
, um den Sortierwert und die Sortierung selbst zu aktualisieren. Dazu müssen Sie eine zusätzlicheupdate()
Methode in Ihrem Datenobjekt implementieren .quelle
Ich hatte ein ähnliches Problem, fand diesen Thread und die Antwort von Tucuxi (danke!), Auf deren Grundlage ich meine eigene implementiert habe
UpdateableTreeSet
. Meine Version bietet Mittel dazuUpdateableTreeSet
verbirgt einen Großteil der Komplexität vor dem Benutzer. Zusätzlich zu den verzögerten Massenaktualisierungen / -entfernungen bleibt die von tucuxi gezeigte Einzelelementaktualisierung / -entfernung in der Klasse weiterhin verfügbar.Update 07.08.2012: Die Klasse ist in einem kleinen GitHub-Repository verfügbar, einschließlich einer einführenden README mit schematischem Beispielcode sowie Unit-Tests, die zeigen, wie (nicht) sie detaillierter verwendet werden kann.
quelle
Wenn Sie wirklich ein verwenden müssen
Set
, dann haben Sie Pech, denke ich.Ich werde jedoch einen Platzhalter einwerfen. Wenn Ihre Situation flexibel genug ist, um mit einem
List
statt mit einem zu arbeitenSet
, können SieCollections.sort()
dasList
bei Bedarf neu sortieren . Dies sollte performant sein, wenn dieList
Reihenfolge nicht stark geändert werden muss.quelle
List
praktische Anwendung zu ermöglichen .Nur eingebaut ist das Entfernen und erneute Hinzufügen.
quelle
Es ist hilfreich zu wissen, ob sich Ihre Objekte in kleinen oder großen Schritten ändern. Wenn jede Änderung sehr klein ist, tun Sie sehr gut daran, Ihre Daten in eine Liste aufzunehmen, die Sie sortiert halten. Dazu muss man
Aber Sie müssen sicherstellen, dass niemand das Element ändern kann, ohne "Sie" zu durchlaufen, um dies zu tun.
EDIT: Auch! Glazed Lists unterstützt genau dies:
http://publicobject.com/glazedlists/glazedlists-1.5.0/api/ca/odell/glazedlists/ObservableElementList.html
quelle
Ich habe dieses Problem nachgeschlagen, als ich versuchte, einen kinetischen Bildlaufbereich zu implementieren, der den Apple iPhone-Radschriftrollen ähnelt. Die Elemente in der
TreeSet
sind diese Klasse:/** * 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()); } }
Es
DoubleExpression
kann einen Moment dauern, bis eine runLater-Task der JavaFX-Plattform gebunden ist. Aus diesem Grund ist der Index in dieser Wrapper-Klasse enthalten.Da sich die
scrollOffset
Position basierend auf der Scrollposition des Benutzers am Scrollrad ständig ändert, benötigen wir eine Möglichkeit zum Aktualisieren. Normalerweise ist die Reihenfolge immer dieselbe, da der Versatz relativ zur Position des Artikelindex ist. Der Index ändert sich nie, aber der Versatz kann negativ oder positiv sein, abhängig von der relativen Entfernung der Elemente von der aktuellen vValue- oder hValue-Eigenschaft derScrollPane
.Befolgen Sie einfach die Anweisungen der obigen Antwort von Tucuxi, um bei Bedarf nur bei Bedarf zu aktualisieren .
Dabei ist vertikaleOffsets a
TreeSet<ItemOffset>
. Wenn Sie bei jedem Aufruf dieses Update-Snippets einen Ausdruck des Sets erstellen, werden Sie feststellen, dass es aktualisiert wird.quelle
Ich glaube nicht, dass es einen Out-of-the-Box-Weg gibt, dies zu tun.
Sie können ein Beobachtermuster verwenden, das das Baumset benachrichtigt, wenn Sie einen Wert innerhalb eines Elements ändern. Anschließend wird es entfernt und erneut eingefügt.
Auf diese Weise können Sie die Liste implizit sortieren, ohne sich darum kümmern zu müssen. Natürlich muss dieser Ansatz erweitert werden,
TreeSet
indem das Einfügeverhalten geändert wird (Festlegen der beobachteten / Benachrichtigungsmechanik für das gerade hinzugefügte Element).quelle