2008-10-10 10 views
12

Personalmente, considero que el rango de funcionalidad proporcionado por java.util.Iterator es bastante patético. Como mínimo, me gustaría disponer de métodos tales como:colección mejorada iterador

  • peek() devuelve siguiente elemento sin mover el iterador hacia adelante
  • anterior() devuelve el elemento anterior

Aunque hay muchas otras posibilidades como first() y last().

¿Alguien sabe si existe un iterador de terceros? Probablemente necesite implementarse como decorador de java.util.Iterator para que pueda funcionar con las colecciones java existentes. Idealmente, debería ser "genérico consciente".

Gracias de antemano, Don

Respuesta

8
+1

Gracias, pero AFAIK las colecciones comunes de Apache * todavía * no se ha generado –

+0

ambos enlaces están ahora muertos – Quince

+0

corrigió los enlaces, gracias. Apache ahora también es consciente de los genéricos y Google Collections está disponible como parte de guayaba. – ykaganovich

9

Usted puede conseguir fácilmente con sólo previous() utilizando un java.util.ListIterator.

Peek en ese punto se implementa fácilmente haciendo un

public <T> T peek(ListIterator<T> iter) throws NoSuchElementException { 
    T obj = iter.next(); 
    iter.previous(); 
    return obj; 
} 

desgracia que será más fácil para tenerlo como un método de utilidad ya que cada clase de colección implementa sus propias iteradores. Hacer un wrapper para obtener un método peek en cada colección en alguna interfaz como MyListIterator sería mucho trabajo.

8

Creo que el motivo por el que no se implementan es porque no son triviales para algunas colecciones y tendrían un gran impacto en el rendimiento. Creo que sería bastante simple para usted hacer que esto funcione para las colecciones que le interesan.

Tampoco me gusta que los iteradores de Java no tengan forma de obtener el valor actual sin moverlo (y por lo tanto no se puede escribir fácilmente el código que se basa en el valor, simplemente pasando el iterador; pasa el valor que ahora tienes también).

0

Nunca me he encontrado con un problema donde he necesitado un vistazo(); Iterator ha funcionado bien para mí. Me llama la atención cómo está utilizando los iteradores que cree que necesita esta funcionalidad adicional.

+0

Creo que el caso más común es algún tipo de envío. Desea leer el primer elemento para ver quién debe manejarlo y enviarlo: si el receptor necesita toda la secuencia, es bueno pasarla y no tener que pasar el objeto eliminado. –

+0

Puedo ver eso. Simplemente tiene el olor de algo que podría hacerse mucho más fácil de otra manera, como un visitante o algo así. –

3

Una cosa que me gustaría ver es la implementación de Sec clojure

http://clojure.org/sequences

La implementación de la base de las clases están en Java y fuente completo está disponible. Los Seqs son decoradores en iteradores de Java (toman e implementan interfaces de iteradores de Java), pero también proporcionan su propia interfaz que podría ser más de lo que usted desea, o al menos un punto de partida.

0

Suena como que podría ser mejor usar una pila.

4

Existe una buena razón para que los operadores genéricos no implementen estas características: no existen para todos los contenedores. El ejemplo típico es un contenedor que representa una entrada de datos externos, como un archivo visto como una secuencia.Cada vez que lea un valor, consume y mueve el puntero hacia adelante, si lo desea o no. Si se imponen estas restricciones en los iteradores genéricos, se pierde la genérica de los iteradores.

Si desea un método previous, como se sugiere, use el ListIterator<>, que luego se limita al contenedor que se comporta como listas.

+0

El argumento de archivo no es realmente convincente, no hay ninguna razón por la cual no pudiéramos obtener el carácter actual (o lo que sea que estamos leyendo) sin avanzar el cursor en el archivo. Sin embargo, estoy de acuerdo en que la característica 'anterior' no puede ser proporcionada por cada iterador (especialmente los iteradores de" generador ", que genera un nuevo valor en cada paso). –

+0

@Luc: esto se debe a que ve los archivos como acceso aleatorio. Y realmente no tienen que serlo. Si lo prefiere, considere una secuencia como sockets de red. Lees lo que recibes y, si quieres leer más adelante, necesitas todo un mecanismo de caché. Entonces, si desea que su iterador se use en todas las situaciones, * realmente * necesita la interfaz que proporciona Java. Después de eso, puede usar adaptadores o iteradores más especializados. Se mantiene que la interfaz que proporciona Java es la más sensible para los iteradores genéricos. – PierreBdR

+0

Esto no es una cuestión de acceso aleatorio: incluso en una transmisión solo hacia adelante, no veo una razón por la que acceder al valor que acaba de leerse y leer la siguiente se debe considerar como una operación única. Pero supongo que esto es bastante subjetivo, y que tendremos que estar de acuerdo en estar en desacuerdo :). Sin embargo, me gustaría añadir que me parece un poco extraño tener un método 'remove' en una interfaz que se supone que es muy genérico, cuando eliminar es una operación que solo es posible en un conjunto bastante limitado de objetos iterables . –

1

Como sugirió ykaganovich, es posible que desee consultar las google-collections cosas. Definitivamente hay algo de apoyo para algunas de las cosas que desea, como peeking. Además, como han mencionado otros, la implementación de todas estas cosas para todas las colecciones puede ser peligrosa desde el punto de vista de la posibilidad o el rendimiento.

0

Las colecciones de Java se escribieron para proporcionar un conjunto mínimo de funcionalidades útiles. Este es un enfoque muy bueno para el código que tiene para ser implementado por cualquier persona que implemente Java. La hinchazón de una interfaz con funcionalidad que podría ser útil puede conducir a un aumento considerable en el volumen de código con mejoras notadas solo por unos pocos. Si peek() y previous() formaban parte del iterador estándar, significa que todos los que escriban un nuevo tipo de Colección deben implementarlo, ya sea sensible o no,.

Los iteradores también están diseñados para trabajar en cosas que físicamente no pueden ir hacia atrás, haciendo que peek() y previous() sean imposibles.

1
public class Iterazor<T> { 
    private Iterator<T> it; 
    public T top; 
    public Iterazor(Collection<T> co) { 
    this.it = co.iterator(); 
    top = it.hasNext()? it.next(): null; 
    } 
    public void advance() { 
    top = it.hasNext()? it.next(): null; 
    } 
} 

// usage 

for(Iterazor<MyObject> iz = new Iterazor<MyObject>(MyCollection); 
    iz.top!=null; iz.advance()) 
    iz.top.doStuff(); 
} 
1

Vi a alguien vinculado a Google Collections, pero nadie mencionó que el método que está buscando se llama Iterators.peekingIterator().

Aún así, sería mejor si solo pudiera usar un ListIterator.