2012-06-27 9 views
5

Me interesa saber si existe algún marco que implemente una colección que tenga el siguiente comportamiento.Colección de Java para permitir agregar y eliminar al iterar


Supongamos que inicialmente contiene: [1, 2, 3]

  • I iterar (usando un iterador) y el elemento 2 alcance, ahora añado 4 hasta el final (la colección será ahora ser [1, 2, 3, 4]).
  • ahora crear un nuevo iterador e iterar la colección, lo que resulta en [1, 2, 3, 4]
  • sigo la iteración con el primer iterador y me dará sólo 3 y volver
  • ahora restablecer el primer iterador me dará [1, 2, 3, 4] (similar a crear uno nuevo).

Lo mismo debe aplicarse para la eliminación de elementos. Si elimino 3 en lugar de agregar, el segundo iterador debería darme [1, 2] mientras que el primero me dará 3 y el final.


Así que cuando llegue y iterador que yo quiero que me dé la colección que tenía cuando creé el iterador (incluso si iterar más tarde, en la I iterar un poco y continuar en otro momento), cuando se restablece la iterator, obtiene basura recolectada, se actualizará a las últimas versiones y debería poder tener múltiples instancias de iterador creadas en diferentes momentos que darán diferentes versiones dependiendo del contenido de la matriz cuando se creó el iterador.

Lo necesitaría para funcionar bien con múltiples hilos y preferible tener una implementación eficiente.

¿Alguien sabe de alguna implementación de dicha colección, o tengo que implementarla yo mismo?

Respuesta

6

Lo que describes se ve muy similar a cómo CopyOnWriteArrayList obras:

  • una vez que comience la iteración, se puede cambiar la colección (incluyendo desde otro hilo) sin afectar a la iteración
  • si crea un nuevo iterador que se basa en la colección en el momento de la creación
  • es seguro para subprocesos

ejemplo simple continuación con la siguiente Outpu t:

Iterator 1 - 1
4 se ha agregado
Iterator 2 - 1
Iterator 2 - 2
Iterator 2 - 3
Iterador de 2 - 4
Iterator 1 - 2
Iterator 1 - 3

public static void main(String[] args) throws InterruptedException { 
    final List<Integer> list = new CopyOnWriteArrayList<Integer>(); 
    list.addAll(Arrays.asList(1, 2, 3)); 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      for (Integer i : list) { 
       System.out.println("Iterator 1 - " + i); 
       try { 
        Thread.sleep(10); 
       } catch (InterruptedException e) {} 
      } 
     } 
    }).start(); 
    Thread.sleep(10); 
    list.add(4); 
    System.out.println("4 has been added"); 
    for (Integer i : list) { 
     System.out.println("Iterator 2 - " + i); 
    } 

} 
+0

¿Crea una nueva copia de la colección en cambio (internamente)? ¿O se implementa de una manera más eficiente? – Razvi

+1

Sí, tal como se describe en javadoc: "todas las operaciones mutativas (agregar, establecer, etc.) se implementan haciendo una copia nueva de la matriz subyacente". – assylias

+0

El comportamiento se parece a lo que necesito. Pero la colección tendrá bastantes elementos. Los iteradores se crean con frecuencia en él, pero creo que los cambios son más raros (por lo que las copias en el cambio pueden no generar demasiada pérdida de rendimiento). – Razvi

7

java.util.concurrent.CopyOnWriteArrayList se comportará así, excepto que ninguna colección Java tiene "reinicio" de iteradores, pero obtener un nuevo iterador en lugar de restablecer tiene el efecto que usted solicita aquí.

2

Puede usar el ImmutableCollections de la biblioteca de guayaba.

El ImmutableList devuelto es con frecuencia - no siempre, pero con frecuencia - una visión constante sobrecarga, en lugar de una copia explícita. Dicho esto, a menudo es más inteligente que su lista promedio, por ejemplo, usará . El eficiente contiene métodos de la colección de respaldo.

3

Se podría hacer uso de java.util.concurrent.CopyOnWriteArrayList<E>

Según documentación:

Una variante flujos seguros de ArrayList en el que todas las operaciones mutativas (añadir, configurar, etc.) son implementado haciendo una nueva copia de la matriz subyacente .

Es costoso, pero seguro para subprocesos.

Ésta es normalmente muy costoso, pero puede ser más eficiente que alternativas cuando las operaciones de recorrido superan enormemente a las mutaciones, y es útil cuando no se puede o no se quiere sincronizar recorridos, sin embargo necesita para evitar interferencias entre hilos concurrentes. El método del iterador de estilo "snapshot" utiliza una referencia al estado de la matriz en en el punto donde se creó el iterador.

medida que se produce la iteración más de un tipo de instantánea, las operaciones (remove, set, y add) en Iterator en sí no son compatibles.

0

javolution tiene threadsafe FastMap

Cuestiones relacionadas