Funcionameto Iterator

Asked

Viewed 131 times

5

I’m having an absurd doubt with use of Iterator, I’m doing an exercise in which I have a Data class that checks the existence of the date, this is working perfectly,in my main I make an array of date and give setData in some

Data d[] = { new Data(), new Data(), new Data(), new Data() };

    d[0].setData( 2, 4, 2016 );
    d[1].setData( 12, 3, 2006 );
    d[2].setData( 3, 3, 2006 );
    d[3].setData( 7, 9, 2015 );

So far so good, doubt arises when I will use a for each to print out all the dates between a two

for( Data x : new RangeData( d[2], d[1] ) )
        System.out.println( x );

In the Rangedata class I create an iterator, but how does it work? I have read in the documentation that hasnext returns true if there is a next element in the iterator and next returns the next element, but how do I fill the iterator with those dates ? My iterator construction is correct? What’s missing? How can I improve?

@Override
public Iterator<Data> iterator() {
    return new Iterator<Data>() {
        Data hoje = data;


        @Override
        public boolean hasNext() {
            return hoje.equals(data2);
        }

        @Override
        public Data next() {
            return hoje;
        }

    };
}

Thanks for your help.

  • The RangeData would spend each day between the two chosen dates ? Your class Data is implemented by hand or is based on the implementation of Date and derivatives ?

  • Exactly that, Rangedata will go through every day between the two, and my date class is implemented by hand even, it simply tests whether the date exists taking into account leap year, amount of days of each month and such things.

2 answers

3


In the Rangedata class I create an iterator, but how it works?

Your explanation is exactly what you do:

I’ve read in the documentation that hasnext returns true if there is a next element in the iterator and next returns the next element

That is to say hasNext has to assess whether it is already at the final date and the next has to return and advance on the day. It is also important to understand how this fits with a foreach normal. Looking for example at:

for (Data x : new RangeData(d[2], d[1]))

Internally Java will get the iterator returned by RangeData and call next() to obtain the value for x in all iterations of for. And just ends the for when the hasNext() of that same iterator return false.

but how I fill the iterator with those dates ?

You will need to store the initial and final date received in the constructor within the class RangedData and uses them in the iterator created within it. The iterator will be responsible for moving forward day by day and return the appropriate day.

Example:

public class RangeData implements Iterable<Data>{
    private Data inicio;
    private Data fim;

    public RangeData(Data inicio, Data fim) {
        this.inicio = inicio;
        this.fim = fim;
    }

    @Override
    public Iterator<Data> iterator() {
        return new Iterator<>() {
            //data corrente do iterador começa como a data de inicio da RangeData
            Data corrente = inicio; 

            @Override
            public boolean hasNext() {
                //se já chegou ao fim ou não. Tem próximo se a data corrente
                //for menor ou igual à data de fim
                return corrente.menorOuIgual(fim); 
            }

            @Override
            public Data next() {
                Data atual = corrente; //data a devolver, a atual
                corrente = corrente.proximoDia(); //corrente avança 1 dia
                return atual;
            }
        };
    }
}

Now we need to implement the methods menorOuIgual and proximoDia used in the iterator I exemplified above. For simplicity and even because the focus of the question is not this, consider the following implementation (proximoDia is not correct but serves to exemplify):

public class Data {
    private int dia;
    private int mes;
    private int ano;

    public Data(){ //para que o código que tinha não deixe de funcionar
    }

    public Data(int dia, int mes, int ano){
        setData(dia, mes, ano);
    }

    public void setData(int dia, int mes, int ano){
        this.dia = dia;
        this.mes = mes;
        this.ano = ano;
    }

    public boolean menorOuIgual(Data data) {
        return ano < data.ano || 
              (ano == data.ano && mes < data.mes) ||
              (ano == data.ano && mes == data.mes && dia <= data.dia);
    }

    public Data proximoDia(){
        //não está correto, mas exemplifica para as duas datas da pergunta
        return new Data(dia + 1, mes, ano);
    }

    @Override
    public String toString() { //para que o System.out que tem no main funcione
        return String.format("%02d/%02d/%d",dia, mes, ano);
    }
}

With this your main will already work.

Exit:

03/03/2006
04/03/2006
05/03/2006
06/03/2006
07/03/2006
08/03/2006
09/03/2006
10/03/2006
11/03/2006
12/03/2006

View execution in Ideone

As a small aside, I advise to simplify the construction of the dates in the main, using a constructor (the one I exemplified) that receives the values you want directly instead of having to do setData for each date individually.

  • Thank you very much, explained excellently, now just see if I understand , the iterator creates an internal list of type defined ( knowing in advance who is the last) and adds it until it arrives at the last and hasNext is false. Correct?

  • @Patricksasso The iterator does not have to create a list. In the example of the reply a list is not created, it only goes from date to date until the deadline (hasNext gives false). Each previous date is not stored anywhere and is therefore discarded. Advance dates are done with a method of your class Data. A more common iterator, type the ArrayList or LinkedList will actually be supported by a list in its implementation. What is perhaps not yet clear is that the foreach will call next() and use the outgoing element until the hasNext fake money.

  • Perfect! I understood the operation and cleared my doubts.

0

Basically the iterator pattern serves for you to encapsulate the iteration in a set of objects, so you don’t have to know if the object is an Arraylist, a Hashtable or a tree, if you implement the iterator you can perform a foreach.

In your case, do you really need this Rangedata? She is quite mistaken and if the problem is just iterate on a subarray you could do as follows

int[] subArray = Arrays.copyOfRange(d, 1, 3);
Iterable<Data> iterable = Arrays.asList(subarray);
for( Data x : iterable ) ){
   System.out.println( x );
}

We’re creating a subarray from your main array, turning your array into a list (Lists implement the Iterable interface in java) and foreach this guy.

About your implementation, I think you are a little lost and it is not worth me replicate what already exists in great quality out there, follow a post on the topic, maybe one of the best in Portuguese: https://www.devmedia.com.br/padrao-de-projeto-iterator-em-java/26733

Browser other questions tagged

You are not signed in. Login or sign up in order to post.