Frage

Ich habe ein Objekt bekommt, die eine ‚natürliche Sortierreihenfolge‘ mit Vergleichbare definiert <>. Diese werden in TreeSets gespeichert.

Anders als das Entfernen und Wieder Hinzufügen des Objekts gibt es eine andere Möglichkeit, die Art zu aktualisieren, wenn sich die Mitglieder, die die Sortierreihenfolge aktualisiert werden verwendet, um zu definieren?

War es hilfreich?

Lösung

Wie andere haben festgestellt, gibt es keine in-integrierte Art und Weise. Aber man kann immer Unterklasse, dass TreeSet, mit Ihrem Konstruktor (n) der Wahl, und fügen Sie in der gewünschten Funktionalität:

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 nun an werden Sie zu Anruf ((UpdateableTreeSet)mySet).update(anElement, aValue) haben den Sortierwert zu aktualisieren und die Sortierung selbst. Dies bedeuten Sie benötigt eine zusätzliche update() Methode in Ihrem Datenobjekt zu implementieren.

Andere Tipps

Ich hatte ein ähnliches Problem, fand diesen Thread und tucuxi Antwort (danke!), Basierend auf dem ich meine eigenen UpdateableTreeSet umgesetzt. Meine Version stellt Mittel bereit, um

  • iterate über eine solche Menge,
  • Zeitplan (latent) Element Updates / Entnahmen aus innerhalb der Schleife
  • ohne eine temporäre Kopie des Satzes erstellen zu müssen und schließlich
  • Werden alle Updates / Umzüge als Massenbetrieb, nachdem die Schleife beendet ist.

UpdateableTreeSet verbirgt sich ein großer Teil der Komplexität vom Benutzer. Neben dem latenten bulk updates / Umzüge, einelementige Aktualisierung / Entfernen wie von tucuxi gezeigt bleibt in der Klasse zur Verfügung.

Update 2012-08-07: Die Klasse ist in einem kleinen verfügbar GitHub-Repository eine Einführungs README mit schematischem Beispielcode sowie Unit-Tests zeigen, wie (nicht) es näher zu verwenden.

Wenn Sie wirklich eine Set verwenden müssen, dann bist du kein Glück, denke ich.

Ich werde in einem Platzhalter werfen, obwohl - wenn Ihre Situation zu Arbeit mit einem List anstelle einem Set flexibel genug ist, dann kann man Collections.sort() umsortieren des List auf Anfrage nutzen. Dies sollte performant sein, wenn die List um sich nicht viel geändert hat werden.

Es hilft wissen, ob Ihre Objekte in kleinen Schritten oder große Veränderung werden. Wenn jede Änderung sehr klein ist, würden Sie sehr gut Ihre Daten in einer Liste zu setzen, dass Sie sortiert halten. Um dies zu tun, müssen Sie

  1. binarysearch den Index des Elements
  2. finden
  3. ändern Sie das Element
  4. , während das Element größer ist als sein rechter Nachbar, tauscht sie mit ihrem rechten Nachbarn
  5. oder, falls dies nicht geschehen:., Während das Element kleiner ist als sein linker Nachbar, tauschen sie mit ihrem linken Nachbarn

Aber Sie müssen sicher nicht machen kann man das Element ändern, ohne durch „Sie“ es zu tun.

EDIT: Auch! Verglaste Listen haben eine gewisse Unterstützung für eben diese:

http://publicobject.com /glazedlists/glazedlists-1.5.0/api/ca/odell/glazedlists/ObservableElementList.html

sah ich dieses Problem, als ich versuchte, eine kinetische Scroll-Scheibe ähnlich wie das Apple iPhone Rad scrollt zu implementieren. 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());
    }
}

Die DoubleExpression kann einen Moment dauert in einer runLater Aufgabe der JavaFX-Plattform gebunden zu sein, das ist, warum der Index in dieser Wrapper-Klasse enthalten ist.

Da die scrollOffset immer auf die Position auf dem Scroll-Rad Scroll-Benutzer basiert ändern, müssen wir einen Weg, um zu aktualisieren. Normalerweise ist die Reihenfolge immer gleich, da der Abstand ist relativ zu der Position der Indexposition. Der Index ändert sich nie, aber das könnte positiv oder negativ auf die Elemente aus dem aktuellen vValue oder hlimit Eigenschaft des ScrollPane relativen Abstand in Abhängigkeit versetzt sein.

Um update bei Bedarf nur bei Bedarf , folgen Sie einfach der Führung der obigen Antwort von Tucuxi.

ItemOffset first = verticalOffsets.first();
verticalOffsets.remove(first);
verticalOffsets.add(first);

Dabei steht verticalOffsets ein TreeSet<ItemOffset> ist. Wenn Sie einen Druck aus dem setzt jedes Mal dieses Update Schnipsel genannt wird, sehen Sie, dass es aktualisiert wird.

Nur in Art und Weise aufgebaut ist zu entfernen und wieder hinzuzufügen.

Ich glaube nicht, gibt es eine out-of-the-Box-Art und Weise, es zu tun.

Sie könnten ein Beobachter-Muster verwenden , dass Teilt der TreeSet, wenn Sie einen Wert innerhalb eines Elements ändern, dann entfernt sie und wieder Einsätze es.

Auf diese Weise können Sie implizit die Liste halten können sortiert ohne Interessieren es von Hand zu tun .. natürlich dieses Ansatzes benötigt TreeSet zu erweitern, indem das Verhalten des Einsetzens zu modifizieren (Einstellung der beobachtete / notify Mechanik auf der gerade hinzugefügte Artikel)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top