Question

J'ai un objet qui définit un « ordre de tri naturel » à l'aide Comparable <>. Ceux-ci sont stockés dans TreeSets.

Autre que la suppression et l'ajout de nouveau l'objet, est-il une autre façon de mettre à jour le genre quand les membres qui sont utilisés pour définir l'ordre de tri sont mis à jour?

Était-ce utile?

La solution

Comme d'autres l'ont noté, il n'y a aucun moyen intégré. Mais vous pouvez toujours sous-classe qui TreeSet, avec votre constructeur (s) de choix, et ajouter la fonctionnalité requise:

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;
       }
    }
}

A partir de là, vous devrez appeler ((UpdateableTreeSet)mySet).update(anElement, aValue) mettre à jour la valeur de tri et le tri lui-même. Cela ne vous oblige à mettre en œuvre une méthode de update() supplémentaire dans votre objet de données.

Autres conseils

J'ai eu un problème similaire, trouvé ce fil et réponse tucuxi (thanks!) Basé sur lequel j'ai mis ma propre UpdateableTreeSet. Ma version fournit des moyens à

  • itérer sur un tel ensemble,
  • calendrier des mises à jour / absorptions d'élément (différé) à partir de l'intérieur de la boucle
  • sans avoir à créer une copie temporaire de l'ensemble et, enfin,
  • ne toutes les mises à jour / absorptions une opération majeure après la boucle est terminée.

UpdateableTreeSet cache beaucoup de la complexité de l'utilisateur. En plus des mises à jour / prélèvements massifs différés, mise à jour / suppression unique élément comme indiqué par tucuxi reste encore disponible dans la classe.

Mise à jour 2012-08-07: La classe est disponible dans un petit dépôt GitHub y compris une introduction README avec le code schématique de l'échantillon, ainsi que des tests unitaires montrant comment (non) pour l'utiliser de manière plus détaillée.

Si vous avez vraiment besoin d'utiliser un Set, alors vous êtes hors de la chance, je pense.

Je vais jeter un caractère générique, bien que - si votre situation est suffisamment souple pour travailler avec un List au lieu d'un Set, vous pouvez utiliser Collections.sort() pour retrier la List sur demande. Cela devrait être performant, si l'ordre de List ne doit pas être changé.

Il permet de savoir si vos objets vont changer par petits incréments ou grand. Si chaque changement est très faible, vous feriez bien de mettre vos données dans une liste que vous gardez triée. Pour ce faire, vous devez

  1. binarySearch pour trouver l'indice de l'élément
  2. modifier l'élément
  3. alors que l'élément est supérieur à son voisin de droite, échanger avec son voisin de droite
  4. ou si cela ne se produisait pas. Alors que l'élément est inférieur à son voisin gauche, échanger avec son voisin gauche

Mais vous devez vous assurer que personne ne peut changer l'élément sans passer par « vous » de le faire.

EDIT: aussi! Listes vitrés a un certain soutien pour ceci:

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

J'ai regardé ce problème quand je tentais de mettre en place un volet de défilement cinétique similaire aux rouleaux de roue Apple iPhone. Les éléments de la TreeSet sont cette classe:

/**
 * 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());
    }
}

Le DoubleExpression peut prendre un moment pour être lié à une tâche runLater de la plate-forme JavaFX, c'est la raison pour laquelle l'indice est compris dans cette classe d'emballage.

Depuis l'scrollOffset est toujours en évolution basée sur la position de défilement de l'utilisateur sur la molette de défilement, nous avons besoin d'un moyen de mettre à jour. En général, l'ordre est toujours le même, puisque le décalage est par rapport à la position d'index de l'élément. L'indice ne change jamais, mais le décalage peut être positif ou négatif en fonction des éléments distance relative de la propriété vValeur actuelle ou hvalue du ScrollPane.

Pour mettre à jour sur demande uniquement en cas de besoin , il suffit de suivre les conseils de la réponse ci-dessus par Tucuxi.

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

verticalOffsets est un TreeSet<ItemOffset>. Si vous faites une impression sur la mettre à chaque fois que cet extrait de mise à jour est appelée, vous verrez qu'il est mis à jour.

Seul construit moyen est de supprimer et ajouter.

Je ne pense pas qu'il y ait un moyen hors-the-box pour le faire.

Vous pouvez utiliser un modèle d'observateur qui informe l'TreeSet chaque fois que vous changez une valeur dans un élément, il supprime et re-insère.

De cette façon, vous pouvez garder implicitement la liste triée sans se soucier de le faire à la main .. Bien sûr, cette approche devra étendre TreeSet en modifiant le comportement d'insertion (réglage de la mécanique observées / notify sur l'élément venez d'ajouter)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top