Iterator Function

5

I have an absurd doubt with 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 I 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, the question arises when I use a for each to print 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 already read in the documentation that the hasnext returns true if there is a next element in the iterator and the next one returns the next element, but how do I populate the iterator with those dates? Is my iterator construct correct? What is 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 in advance for your help.

    
asked by anonymous 03.05.2018 / 21:10

2 answers

3
  

In the RangeData class I create an iterator, but how does it work?

Your explanation is exactly what it does:

  

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

That is hasNext has to evaluate if it is already on the end date and next has to return and move forward on the day. It is also important to realize how this fits with a foreach normal. Looking at for example:

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

Internally Java will get the iterator returned by RangeData and call next() to get the value for x on all iterations of for . And it only ends for when hasNext() of that same iterator returns false .

  

But how do I populate the iterator with these dates?

You will need to save the start and end dates you received in the constructor within the RangedData class and use them in the iterator created within it. The iterator will be responsible for moving forward day by day and returning 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 have to implement the menorOuIgual and proximoDia methods 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.

Output:

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 on Ideone

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

04.05.2018 / 00:53
0

Basically the iterator pattern is for you to encapsulate the iteration in a set of objects, so you do not have to know if the object is an ArrayList, a HashTable, or a tree, if you implement the iterator you can perform a foreach. / p>

In your case, do you really need this RangeData? It is quite misleading and if the problem is just iterating in a subarray you could do it as follows

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

We are creating a subarray from your main array, transforming your array into a list (Lists implement the Iterable interface in java) and making a foreach on top of that face.

About your implementation, I think you're a little lost and it's not worth me to replicate what already exists in great quality there, here's a post on the topic, maybe one of the best in Portuguese: link

    
04.05.2018 / 00:54