¿Podemos escribir nuestro propio iterador en Java?

Si tengo una lista que contiene [alice, bob, abigail, charlie] y quiero escribir un iterador para que itere sobre los elementos que comienzan con ‘a’, ¿puedo escribir el mío? Cómo puedo hacer eso ?

Por supuesto. Un iterador es solo una implementación de la interfaz java.util.Iterator . Si está utilizando un objeto iterable existente (por ejemplo, una LinkedList ) de java.util , necesitará subclasificarlo y anular su función de iterator para que pueda devolver el suyo propio, o proporcionar un medio para envolver un iterador estándar en su instancia Iterator especial (que tiene la ventaja de ser utilizada de manera más amplia), etc.

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 sobrescribe el método Iterator ().

 import java.util.Iterator; public class SOList implements Iterable { private Type[] arrayList; private int currentSize; public SOList(Type[] newArray) { this.arrayList = newArray; this.currentSize = arrayList.length; } @Override public Iterator iterator() { Iterator it = new Iterator() { private int currentIndex = 0; @Override public boolean hasNext() { return currentIndex < currentSize && arrayList[currentIndex] != null; } @Override public Type next() { return arrayList[currentIndex++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; return it; } } 

Esta clase implementa la interfaz Iterable usando Generics . Teniendo en cuenta que tiene elementos para la matriz, podrá obtener una instancia de un iterador, que es la instancia necesaria utilizada por el ciclo "foreach", por ejemplo.

Solo puede crear una instancia anónima del iterador sin crear Iterator extendido y aprovechar el valor de currentSize para verificar hasta dónde puede navegar por 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 donde está y todo lo que necesita hacer es jugar con hasNext (), que verifica si el valor actual no es nulo, y el siguiente (), que devolverá la instancia de su currentIndex. A continuación se muestra un ejemplo del uso de esta API ...

 public static void main(String[] args) { // create an array of type Integer Integer[] numbers = new Integer[]{1, 2, 3, 4, 5}; // create your list and hold the values. SOList stackOverflowList = new SOList(numbers); // Since our class SOList is an instance of Iterable, then we can use it on a foreach loop for(Integer num : stackOverflowList) { System.out.print(num); } // creating an array of Strings String[] languages = new String[]{"C", "C++", "Java", "Python", "Scala"}; // create your list and hold the values using the same list implementation. SOList languagesList = new SOList(languages); System.out.println(""); // Since our class SOList is an instance of Iterable, then we can use it on a foreach loop for(String lang : languagesList) { System.out.println(lang); } } // will print "12345 //C //C++ //Java //Python //Scala 

Si lo desea, también puede iterar sobre él utilizando la instancia de Iterator:

 // navigating the iterator while (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 

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 google personal de práctica.

Ahora, para obtener los efectos de lo que necesita, creo que necesita 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 filtre la implementación next () con un valor que no comience con un carácter "a", por ejemplo. Creo que debes jugar con un Interator secundario basado en una lista filtrada con los valores con el filtro dado.

Buen ejemplo para Iterable para calcular factorial

 FactorialIterable fi = new FactorialIterable(10); Iterator iterator = fi.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } 

en breve código para Java 1.8

 new FactorialIterable(5).forEach(System.out::println); 

clase personalizada Iterable

 public class FactorialIterable implements Iterable { private final FactorialIteartor factorialIteartor; public FactorialIterable(Integer value) { factorialIteartor = new FactorialIteartor(value); } @Override public Iterator iterator() { return factorialIteartor; } @Override public void forEach(Consumer< ? super Integer> action) { Objects.requireNonNull(action); Integer last = 0; for (Integer t : this) { last = t; } action.accept(last); } } 

clase Iterator personalizada

 public class FactorialIteartor implements Iterator { private final Integer mNumber; private Integer mPosition; private Integer mFactorial; public FactorialIteartor(Integer number) { this.mNumber = number; this.mPosition = 1; this.mFactorial = 1; } @Override public boolean hasNext() { return mPosition < = mNumber; } @Override public Integer next() { if (!hasNext()) return 0; mFactorial = mFactorial * mPosition; mPosition++; return mFactorial; } } 

Puede implementar su propio iterador. Su iterador podría construirse para ajustar el Iterador devuelto por la Lista, o podría mantener un cursor y usar el método get (int index) de la Lista. Solo tiene que agregar lógica al siguiente método de Iterator Y al método de hasNext para tener en cuenta sus criterios de filtrado. También deberá decidir si su iterador admitirá la operación de eliminación.

Este es el código completo para escribir un iterador de modo que itere sobre los elementos que comienzan con ‘a’:

 import java.util.Iterator; public class AppDemo { public static void main(String args[]) { Bag bag1 = new Bag<>(); bag1.add("alice"); bag1.add("bob"); bag1.add("abigail"); bag1.add("charlie"); for (Iterator it1 = bag1.iterator(); it1.hasNext();) { String s = it1.next(); if (s != null) System.out.println(s); } } } 

Clase Iterator personalizada

 import java.util.ArrayList; import java.util.Iterator; public class Bag { private ArrayList data; public Bag() { data = new ArrayList<>(); } public void add(T e) { data.add(e); } public Iterator iterator() { return new BagIterator(); } public class BagIterator implements Iterator { private int index; private String str; public BagIterator() { index = 0; } @Override public boolean hasNext() { return index < data.size(); } @Override public T next() { str = (String) data.get(index); if (str.startsWith("a")) return (T) data.get(index++); index++; return null; } } }