Se eu tiver uma lista contendo [alice, bob, abigail, charlie]
e quiser escrever um iterador de forma que itere sobre os elementos que começam com 'a', posso escrever o meu próprio? Como eu posso fazer isso ?
Se eu tiver uma lista contendo [alice, bob, abigail, charlie]
e quiser escrever um iterador de forma que itere sobre os elementos que começam com 'a', posso escrever o meu próprio? Como eu posso fazer isso ?
Respostas:
Certo. Um iterador é apenas uma implementação da java.util.Iterator
interface. Se você estiver usando um objeto iterável existente (digamos, a LinkedList
) de java.util
, você precisará subclassificá-lo e sobrescrever sua iterator
função para que você retorne a sua, ou fornecer um meio de agrupar um iterador padrão em sua Iterator
instância especial (que tem a vantagem de ser mais amplamente utilizado), etc.
Iterator
instância especial ..." (e obrigado). :-)
A melhor opção reutilizável é implementar a interface Iterable e substituir o iterador do método ().
Aqui está um exemplo de uma classe como ArrayList implementando a interface, na qual você substitui o 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 classe implementa a interface Iterable usando Genéricos . Considerando que você tem elementos para o array, você poderá obter uma instância de um Iterator, que é a instância necessária usada pelo loop "foreach", por exemplo.
Você pode simplesmente criar uma instância anônima do iterador sem criar estendendo Iterator e aproveitar o valor de currentSize para verificar até onde você pode navegar sobre a matriz (digamos que você criou uma matriz com capacidade de 10, mas você tem apenas 2 elementos em 0 e 1). A instância terá seu contador proprietário de onde está e tudo que você precisa fazer é brincar com hasNext (), que verifica se o valor atual não é nulo, e o next (), que retornará a instância de seu currentIndex. Abaixo está um exemplo de uso desta 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
Se desejar, você também pode iterar sobre ele usando a instância 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
A documentação do foreach está localizada em http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html . Você pode dar uma olhada em uma implementação mais completa em meu código de prática pessoal do Google .
Agora, para obter os efeitos do que você precisa, acho que você precisa conectar um conceito de filtro no Iterator ... Como o iterador depende dos próximos valores, seria difícil retornar true em hasNext () e, em seguida, filtre a implementação next () com um valor que não comece com um caractere "a", por exemplo. Acho que você precisa brincar com um Interator secundário com base em uma lista filtrada com os valores com o filtro fornecido.
for instance
, isso é um trocadilho?
Bom exemplo de Iterable para calcular fatorial
FactorialIterable fi = new FactorialIterable(10);
Iterator<Integer> iterator = fi.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Código curto para Java 1.8
new FactorialIterable(5).forEach(System.out::println);
Classe Iterable Customizada
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);
}
}
Classe Iterator Customizado
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 é o código completo para escrever um iterador de forma que itere sobre os elementos que começam com '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);
}
}
}
Classe Iterator Customizado
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;
}
}
}
Você pode implementar seu próprio Iterator. Seu iterador pode ser construído para envolver o Iterador retornado pela Lista, ou você pode manter um cursor e usar o método get (int index) de List. Você só precisa adicionar lógica ao próximo método de seu Iterator E ao método hasNext para levar em consideração seus critérios de filtragem. Você também terá que decidir se o seu iterador suportará a operação de remoção.
Aqui está a resposta completa para a pergunta.
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
é o iterador para a matriz que retorna os elementos que começam com 'a'. NoSuchElementException
exceção válida .