¿Podemos escribir nuestro propio iterador en Java?
104
Si tengo una lista que contiene [alice, bob, abigail, charlie]y quiero escribir un iterador de modo que repita los elementos que comienzan con 'a', ¿puedo escribir el mío propio? Cómo puedo hacer eso ?
Por supuesto. Un iterador es solo una implementación de la java.util.Iteratorinterfaz. Si está utilizando un objeto iterable existente (digamos, a LinkedList) de java.util, deberá subclasificarlo y anular su iteratorfunción para que devuelva la suya propia, o proporcionar un medio para envolver un iterador estándar en su Iteratorinstancia especial (que tiene la ventaja de ser más ampliamente utilizado), etc.
buena respuesta .... +1 Sin embargo, no está obligado a subclase LinkedList. Puede escribir un CustomIterator que se instancia con el nuevo CustomIterator (somelist), ya que las interfaces no dicen nada sobre los constructores.
gd1
1
@Giacomo: Eso es lo que quise decir con "... o proporcionar un medio para envolver un iterador estándar en su Iteratorinstancia especial ..." (y gracias). :-)
TJ Crowder
196
La mejor opción reutilizable es implementar la interfaz Iterable y anular el método iterator ().
Aquí hay un ejemplo de una clase similar a ArrayList que implementa la interfaz, en la que anula el método Iterator ().
Esta clase implementa la interfaz Iterable usando Generics . Teniendo en cuenta que tiene elementos en la matriz, podrá obtener una instancia de un Iterador, que es la instancia necesaria utilizada por el bucle "foreach", por ejemplo.
Puede simplemente crear una instancia anónima del iterador sin crear un iterador extendido y aprovechar el valor de currentSize para verificar hasta dónde puede navegar sobre la matriz (digamos que creó una matriz con capacidad de 10, pero solo tiene 2 elementos en 0 y 1). La instancia tendrá su contador de propietario de dónde está y todo lo que necesita hacer es jugar con hasNext (), que verifica si el valor actual no es nulo, y next (), que devolverá la instancia de su currentIndex. A continuación se muestra un ejemplo del uso de esta API ...
publicstaticvoid main(String[] args){// create an array of type IntegerInteger[] numbers =newInteger[]{1,2,3,4,5};// create your list and hold the values.SOList<Integer> stackOverflowList =newSOList<Integer>(numbers);// Since our class SOList is an instance of Iterable, then we can use it on a foreach loopfor(Integer num : stackOverflowList){System.out.print(num);}// creating an array of StringsString[] languages =newString[]{"C","C++","Java","Python","Scala"};// create your list and hold the values using the same list implementation.SOList<String> languagesList =newSOList<String>(languages);System.out.println("");// Since our class SOList is an instance of Iterable, then we can use it on a foreach loopfor(String lang : languagesList){System.out.println(lang);}}// will print "12345//C//C++//Java//Python//Scala
Si lo desea, también puede iterar sobre él usando la instancia de Iterator:
// navigating the iteratorwhile(allNumbers.hasNext()){Integer value = allNumbers.next();if(allNumbers.hasNext()){System.out.print(value +", ");}else{System.out.print(value);}}// will print 1, 2, 3, 4, 5
Ahora, para obtener los efectos de lo que necesita, creo que debe conectar un concepto de filtro en el Iterador ... Dado que el iterador depende de los siguientes valores, sería difícil devolver verdadero en hasNext (), y luego filtrar la implementación next () con un valor que no comience con un carácter "a", por ejemplo. Creo que necesitas jugar con un Interator secundario basado en una lista filtrada con los valores con el filtro dado.
Otras 30 personas no pensaron que fuera un juego de palabras :)
Marcello de Sales
2
Es una buena práctica lanzar una excepción de operación no admitida de nuestros métodos implementados. ¡Creo que es una buena idea lanzar una excepción de operación no admitida del método remove ()!
darshan
2
Lo siento @darshan, pero esta solución tiene que ver con "cómo escribir iteradores" ... Si el enfoque fuera "escribir código perfectamente escrito", ¡eso estaría ahí!
Marcello de Sales
no está claro por qué se requiere la verificación 'arrayList [currentIndex]! = null' dentro de hasNext (). alguien puede explicar por favor.
Bhushan Karmarkar
12
Buen ejemplo de Iterable para calcular factorial
FactorialIterable fi =newFactorialIterable(10);Iterator<Integer> iterator = fi.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}
Puede implementar su propio iterador. Su iterador podría construirse para envolver el Iterador devuelto por la Lista, o podría mantener un cursor y usar el método get (índice int) de la Lista. Solo tiene que agregar lógica al siguiente método de su Iterador Y al método hasNext para tener en cuenta sus criterios de filtrado. También tendrá que decidir si su iterador admitirá la operación de eliminación.
ListIterator es el iterador de la matriz que devuelve los elementos que comienzan con 'a'.
No es necesario implementar una interfaz iterable. Pero esa es una posibilidad.
No es necesario implementar esto de forma genérica.
Satisface completamente el contrato para hasNext () y next (). es decir, si hasNext () dice que todavía hay elementos, next () devolverá esos elementos. Y si hasNext () dice que no hay más elementos, devuelve una NoSuchElementExceptionexcepción válida .
Respuestas:
Por supuesto. Un iterador es solo una implementación de la
java.util.Iterator
interfaz. Si está utilizando un objeto iterable existente (digamos, aLinkedList
) dejava.util
, deberá subclasificarlo y anular suiterator
función para que devuelva la suya propia, o proporcionar un medio para envolver un iterador estándar en suIterator
instancia especial (que tiene la ventaja de ser más ampliamente utilizado), etc.fuente
Iterator
instancia especial ..." (y gracias). :-)La mejor opción reutilizable es implementar la interfaz Iterable y anular el método iterator ().
Aquí hay un ejemplo de una clase similar a ArrayList que implementa la interfaz, en la que anula el método Iterator ().
Esta clase implementa la interfaz Iterable usando Generics . Teniendo en cuenta que tiene elementos en la matriz, podrá obtener una instancia de un Iterador, que es la instancia necesaria utilizada por el bucle "foreach", por ejemplo.
Puede simplemente crear una instancia anónima del iterador sin crear un iterador extendido y aprovechar el valor de currentSize para verificar hasta dónde puede navegar sobre la matriz (digamos que creó una matriz con capacidad de 10, pero solo tiene 2 elementos en 0 y 1). La instancia tendrá su contador de propietario de dónde está y todo lo que necesita hacer es jugar con hasNext (), que verifica si el valor actual no es nulo, y next (), que devolverá la instancia de su currentIndex. A continuación se muestra un ejemplo del uso de esta API ...
Si lo desea, también puede iterar sobre él usando la instancia de Iterator:
La documentación de foreach se encuentra en http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html . Puede echar un vistazo a una implementación más completa en mi código de Google de práctica personal .
Ahora, para obtener los efectos de lo que necesita, creo que debe conectar un concepto de filtro en el Iterador ... Dado que el iterador depende de los siguientes valores, sería difícil devolver verdadero en hasNext (), y luego filtrar la implementación next () con un valor que no comience con un carácter "a", por ejemplo. Creo que necesitas jugar con un Interator secundario basado en una lista filtrada con los valores con el filtro dado.
fuente
for instance
, ¿es un juego de palabras?Buen ejemplo de Iterable para calcular factorial
Código corto para Java 1.8
Clase Iterable personalizada
Clase de iterador personalizado
fuente
Este es el código completo para escribir un iterador de modo que repita los elementos que comienzan con 'a':
Clase de iterador personalizado
fuente
Puede implementar su propio iterador. Su iterador podría construirse para envolver el Iterador devuelto por la Lista, o podría mantener un cursor y usar el método get (índice int) de la Lista. Solo tiene que agregar lógica al siguiente método de su Iterador Y al método hasNext para tener en cuenta sus criterios de filtrado. También tendrá que decidir si su iterador admitirá la operación de eliminación.
fuente
Aquí está la respuesta completa a la pregunta.
ListIterator
es el iterador de la matriz que devuelve los elementos que comienzan con 'a'.NoSuchElementException
excepción válida .fuente