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 ?
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 ?
Respuestas:
Por supuesto. Un iterador es solo una implementación de la java.util.Iterator
interfaz. Si está utilizando un objeto iterable existente (digamos, a LinkedList
) de java.util
, deberá subclasificarlo y anular su iterator
función para que devuelva la suya propia, o proporcionar un medio para envolver un iterador estándar en su Iterator
instancia especial (que tiene la ventaja de ser más ampliamente utilizado), etc.
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 ().
import java.util.Iterator;
public class SOList<Type> implements Iterable<Type> {
private Type[] arrayList;
private int currentSize;
public SOList(Type[] newArray) {
this.arrayList = newArray;
this.currentSize = arrayList.length;
}
@Override
public Iterator<Type> iterator() {
Iterator<Type> it = new Iterator<Type>() {
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 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 ...
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<Integer> stackOverflowList = new SOList<Integer>(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<String> languagesList = new SOList<String>(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 usando 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 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.
for instance
, ¿es un juego de palabras?
Buen ejemplo de Iterable para calcular factorial
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Código corto para Java 1.8
new FactorialIterable(5).forEach(System.out::println);
Clase Iterable personalizada
public class FactorialIterable implements Iterable<Integer> {
private final FactorialIterator factorialIterator;
public FactorialIterable(Integer value) {
factorialIterator = new FactorialIterator(value);
}
@Override
public Iterator<Integer> iterator() {
return factorialIterator;
}
@Override
public void forEach(Consumer<? super Integer> action) {
Objects.requireNonNull(action);
Integer last = 0;
for (Integer t : this) {
last = t;
}
action.accept(last);
}
}
Clase de iterador personalizado
public class FactorialIterator implements Iterator<Integer> {
private final Integer mNumber;
private Integer mPosition;
private Integer mFactorial;
public FactorialIterator(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;
}
}
Este es el código completo para escribir un iterador de modo que repita los elementos que comienzan con 'a':
import java.util.Iterator;
public class AppDemo {
public static void main(String args[]) {
Bag<String> bag1 = new Bag<>();
bag1.add("alice");
bag1.add("bob");
bag1.add("abigail");
bag1.add("charlie");
for (Iterator<String> it1 = bag1.iterator(); it1.hasNext();) {
String s = it1.next();
if (s != null)
System.out.println(s);
}
}
}
Clase de iterador personalizado
import java.util.ArrayList;
import java.util.Iterator;
public class Bag<T> {
private ArrayList<T> data;
public Bag() {
data = new ArrayList<>();
}
public void add(T e) {
data.add(e);
}
public Iterator<T> iterator() {
return new BagIterator();
}
public class BagIterator<T> implements Iterator<T> {
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;
}
}
}
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.
Aquí está la respuesta completa a la pregunta.
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
class ListIterator implements Iterator<String>{
List<String> list;
int pos = 0;
public ListIterator(List<String> list) {
this.list = list;
}
@Override
public boolean hasNext() {
while(pos < list.size()){
if (list.get(pos).startsWith("a"))
return true;
pos++;
}
return false;
}
@Override
public String next() {
if (hasNext())
return list.get(pos++);
throw new NoSuchElementException();
}
}
public class IteratorTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("alice", "bob", "abigail", "charlie");
ListIterator itr = new ListIterator(list);
while(itr.hasNext())
System.out.println(itr.next()); // prints alice, abigail
}
}
ListIterator
es el iterador de la matriz que devuelve los elementos que comienzan con 'a'. NoSuchElementException
excepción válida .