Podemos escrever o nosso iterator em Java?

Se eu tiver uma lista contendo {[[0]} e eu quiser escrever um iterador de modo que itere sobre elementos que começam com 'a', Posso escrever o meu próprio ? Como posso fazer isso ?

 105
Author: user2864740, 2011-05-01

6 answers

Claro. Um iterador é apenas uma implementação do java.util.Iterator interface. Se você estiver usando um iterable objeto (digamos, um LinkedList) a partir de java.util, terá de subclasse-lo e substituir o seu iterator a função para que você retornar a sua própria, ou fornecer um meio de moldagem de um padrão iterator em seu especial Iterator exemplo (que tem a vantagem de ser mais amplamente utilizado), etc.
 48
Author: T.J. Crowder, 2011-05-01 15:03:52

A melhor opção reutilizável é implementar a interface iterável e anular o método iterator().

Aqui está um exemplo de uma classe como ArrayList implementando a interface, na qual você sobrepõe 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 iterável usando genéricos . Considerando que você tem elementos para a matriz, você será capaz de obter uma instância de um iterador, que é a instância necessária usada pelo laço "foreach", para instancia.

Você pode simplesmente criar um anônimo instância do iterador sem criar estendendo Iterador e aproveitar o valor do currentSize para verificar até onde você pode navegar sobre a matriz (digamos que você criou uma matriz com a capacidade de 10, mas você tem apenas 2 elementos 0 e 1). A instância terá seu contador proprietário de onde ele está e tudo que você precisa fazer é brincar com o hasNext (), que verifica se o valor atual não é nulo, e o próximo (), que irá devolve a instância do teu index actual. Abaixo está um exemplo de usar 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

Se quiseres, também podes usar 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

O foreach documentação está localizado 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 na minha prática pessoal google code.

Agora, para obter os efeitos do que você precisa, acho que você precisa plugar um conceito de filtro no iterador... Uma vez que o iterator depende dos próximos valores, seria difícil retornar verdadeiro no hasNext(), e então filtrar a próxima implementação() com um valor que não começa com um char "a", por exemplo. Eu acho que você precisa brincar com um Interador secundário baseado em uma lista filtrada com os valores com o filtro dado.
 202
Author: Marcello de Sales, 2014-12-09 19:49:54

Bom exemplo para calcular factorial

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

Código abreviado para Java 1.8

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

Classe iterável 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);
    }

}

Iterator 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;
    }
}
 13
Author: Vahe Gharibyan, 2020-02-14 18:50:00

Este é o código completo para escrever um iterador tal que itera sobre 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); 
        }
    }
}

Iterator 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; 
        }
    } 
}
 8
Author: elvis, 2018-05-19 10:41:50
Podes implementar o teu próprio iterador. Seu iterator poderia ser construído para embrulhar o Iterator retornado pela lista, ou você poderia manter um cursor e usar o método get(int índice) da lista. Você só tem que adicionar lógica ao próximo método do iterador e ao método hassnext para levar em conta seus critérios de filtragem. Você também terá que decidir se o seu iterador irá apoiar a operação de remoção.
 5
Author: ditkin, 2011-05-01 15:10:46
Aqui está a resposta completa à 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 o array que devolve os elementos que começam com 'a'.
  • Não é necessário implementar uma interface iterável. Mas isso é uma possibilidade. Não há necessidade de implementar isto genericamente.
  • satisfaz plenamente o contrato para o hasNext() e o next(). ie se o hasNext() diz que ainda existem elementos, o next () irá devolver esses elementos. And if hasNext() diz que não há mais elementos, devolve uma excepção válida NoSuchElementException.
 2
Author: apadana, 2020-04-14 08:45:33