Pregunta

Tengo un objeto que define un 'orden natural' usando Comparable <>. Estos se almacenan en TreeSets.

Aparte de quitar y volver a agregar el objeto, ¿hay otra manera de actualizar el tipo cuando los miembros que se utilizan para definir el orden de clasificación se actualizan?

¿Fue útil?

Solución

manera Como otros han señalado, no se construye en-no. Pero siempre se puede subclase que TreeSet, con su constructor (s) de elección, y añadir en la funcionalidad requerida:

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 entonces, se tendrá que ((UpdateableTreeSet)mySet).update(anElement, aValue) llamada a actualizar el valor de la clasificación y la clasificación en sí. Esto se requiere para poner en práctica un método update() adicional en su objeto de datos.

Otros consejos

Yo tenía un problema similar, encontrado este hilo y la respuesta de tucuxi (gracias!) En base a la cual he implementado mi propia UpdateableTreeSet. Mi versión proporciona medios para

  • iterar sobre un conjunto tal,
  • schedule (diferido) actualizaciones de elementos / traslado de dentro del bucle
  • sin tener que crear una copia temporal del conjunto y, finalmente,
  • hacer todas las actualizaciones / remociones como una operación mayor después del bucle ha finalizado.

UpdateableTreeSet esconde una gran parte de la complejidad al usuario. Además de las actualizaciones diferidos a granel / remociones, actualización de un solo elemento / retirada como se muestra por tucuxi todavía queda disponible en la clase.

Actualización 2012-08-07: La clase está disponible en una pequeña GitHub repositorio incluyendo un README introductoria con código de ejemplo esquemático, así como pruebas de unidad que muestra cómo (no) para utilizar con más detalle.

Si realmente necesita usar un Set, entonces estás de suerte, creo.

Me voy a tirar un comodín, sin embargo - si su situación es lo suficientemente flexible como para trabajar con un List en lugar de un Set, entonces usted puede utilizar Collections.sort() para reordenar la List bajo demanda. Esto debería ser performante, si la orden List no tiene que ser cambiado mucho.

Es muy útil saber si los objetos se van a cambiar por incrementos pequeños o grandes. Si cada cambio es muy pequeño, que haría muy bien en poner sus datos en una lista que usted guarda ordenada. Para ello, usted tiene que

  1. busquedaBinaria para encontrar el índice del elemento
  2. modificar el elemento
  3. mientras que el elemento es mayor que su vecino derecha, intercambio con su vecina derecha
  4. o si no fue así:., Mientras que el elemento es menor que su vecino izquierdo, intercambio con su vecino izquierdo

Pero hay que asegurarse de que nadie puede cambiar el elemento sin pasar por "usted" a hacerlo.

EDIT: también! Listas acristalamiento tiene una cierta ayuda para esto:

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

Busqué este problema cuando yo estaba tratando de implementar un panel de desplazamiento cinética similar a los rollos de la rueda el iPhone de Apple. Los elementos de la TreeSet esta clase son:

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

El DoubleExpression puede tomar un momento para ser atado en una tarea runLater de la plataforma JavaFX, es por esto que el índice se incluye en esta clase de contenedor.

Desde el scrollOffset siempre está cambiando basa en la posición de desplazamiento del usuario en la rueda de desplazamiento, necesitamos una forma de actualización. Por lo general, el orden es siempre la misma, ya que el desplazamiento es relativo a la posición de índice de elemento. El índice nunca cambia, pero el desplazamiento puede ser positivo o negativo dependiendo de los artículos distancia relativa de los actuales propiedad vValue o hValue del ScrollPane.

Para actualizar en la demanda sólo cuando sea necesario , sólo tiene que seguir la orientación de la respuesta anterior por Tucuxi.

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

donde verticalOffsets es una TreeSet<ItemOffset>. Si usted hace una copia impresa de la establecer cada vez que esta actualización se llama fragmento, se verá que éste se encuentre actualizado.

Sólo construida en forma de hacerlo es quitar y volver a agregar.

No creo que hay una manera fuera de la caja para hacerlo.

Se podría utilizar un patrón de observador que se notifica a los TreeSet cada vez que cambie un valor dentro de un elemento, entonces se elimina y vuelve a lo inserta.

De esta manera se puede mantener de forma implícita la lista ordenada y sin el cuidado de hacerlo a mano .. por supuesto, este enfoque tendrá que extender TreeSet modificando el comportamiento de inserción (ajuste de la observada / notificar a los mecánicos en el artículo apenas añadido)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top