Iterable, Iterator

0

Witam
Nie wiem jak ogarnąć temat iteratora. a dokładnie co to jest? po co? i jak go użyć.
Szukałem po necie jakiegoś wyjaśnienia ale nadal nic :)

Mam klasę Report która ma przechowywać listę rachunków

Mam ArrayList

static List<Bill> report = new ArrayList<Bill>();

i jak mam podpiąć pod nią iterator? i w sumie po co mi on skoro mogę wypisać dane za pomocą pętli for?

for(Bill z : report){
    System.out.println(...);
}

Próbowałem zrobić tak:

//do klasy dodaje implementacje
public class Report implements Iterable<Bill>

static List<Bill> report = new ArrayList<Bill>();
static Iterator<Bill> it = report.iterator();

//metoda iteratora
@Override
	public Iterator<Bill> iterator() {
		return null;
	}

//wypisywanie za pomoca iteratora:
while(it.hasNext()){
  System.out.println(it.next());
}

I niestety nie działa. Ktoś mógłby zerknąć i podpowiedzieć??:) z góry dzięki

1

Foreach z Javy pod maską używa dokładnie Iteratora. Dokładniej to foreach przyjmuje jako parametr dowolne Iterable, a Iterable ma metodę iterator() która zwraca świeży Iterator.

ArrayList implementuje Iterable i dlatego możesz tego użyć w foreachu.

Foreach działa też dla tablic, chociaż nie implementują one interfejsu Iterable - ale to raczej szczegół w kontekście problemu z pierwszego posta.

Przykład implementacji:

import java.util.Iterator;

class Zakres implements Iterable<Integer> {
    
    final int start;
    final int koniec;
    
    public Zakres(final int start, final int koniec) {
        this.start = start;
        this.koniec = koniec;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            
            int aktualny = start;

            @Override
            public boolean hasNext() {
                return aktualny <= koniec;
            }

            @Override
            public Integer next() {
                return aktualny++;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("Illegal action.");
            }
        };
    }
    
}

public class Main {

    public static void main(String[] args) {
        Zakres zakres = new Zakres(5, 8);
        for (int i : zakres) {
            System.out.println(i);
        }
        for (int i : zakres) {
            System.out.println(i);
        }
        for (int i : zakres) {
            System.out.println(i);
        }
    }
}

Wynik działania: http://ideone.com/avtl9i

Moja implementacja Iterable (czyli tutaj Zakres) jest zgodna ze specyfikacją, a więc zwrócony Iterator nie zmienia stanu obiektu iterowanego podczas iterowania (wyjątek stanowi usuwanie za pomocą metody remove, ale tutaj nie jest zaimplementowana). Dlatego mogę iterować po jednym i tym samym Zakresie wiele razy.

Kod:

        for (int i : zakres) {
            System.out.println(i);
        }

Jest równoznaczny z:

        Iterator<Integer> iterator = zakres.iterator();
        while (iterator.hasNext()) {
            int i = iterator.next();
            System.out.println(i);
        }

Tzn każdy foreach to osobne stworzenie Iteratora.

0

Co robie zle, ze metoda test nie wypisuje obiektow klasy Bill?

public class Report implements Iterable<Bill>{
	static List<Bill> report = new ArrayList<Bill>();
	static Iterator<Bill> it = report.iterator();
	
	public static void test(){
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}
	
	@Override
	public Iterator<Bill> iterator() {
		return new Iterator<Bill>(){
	        final int start = 0;
	        final int koniec = report.size();
	        int aktualny = start;
	        
	        @Override
	        public boolean hasNext() {
	            return aktualny <= koniec;
	        }
 
	        @Override
	        public Bill next(){
	        	aktualny++;
	           return report.get(aktualny);
	        }
 
            @Override
            public void remove() {
            }   
          };
}
		

	 

}
0

Nic nie dodajesz do listy report.

0

Dodaje, tylko nie wpisałem wyżej żeby kod był czytelniejszy. W liscie znajduja sie elementy, bo nawet w petli for(Bill z : report) sie pokazuja :)

public static void add_bill(Bill x){
	report.add(x);
}
1

Iteratory są jednokrotnego użytku. Przeiterujesz i koniec (no chyba, że użyjesz specjalnego iteratora jak ListIterator, ale to jest dość niestandardowe). Twórz iteratory tuż przed iterowaniem.

(nie wiem czy to pomoże, ale i tak kod razi w oczy)

Poza tym z kodu wynika, że w metodzie test używasz Iteratora zwracanego z ArrayListy, a nie twojego Iteratora. No chyba, że tak pociąłeś kod zanim go tu wkleiłeś że już nic z niego nie wynika.

0

hmm. wysyłam cały kod
Maina nie wysylam ale on dodaje elementy Bill do Listy i wywołuje metode test:

package shop;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.lang.Iterable;

public class Report implements Iterable<Bill>{
	
	static List<Bill> report = new ArrayList<Bill>();
	static Iterator<Bill> it = report.iterator();

	public static List<Bill> get_report(){
		return report;
	}
	
	public static void add_bill(Bill x){
		report.add(x);
	}
	
	@Override
	public Iterator<Bill> iterator() {
			return new Iterator<Bill>(){
	        final int start = 0;
	        final int koniec = report.size();
	        int aktualny = start;
	        
	        @Override
	        public boolean hasNext() {
	            return aktualny <= koniec;
	        }
 
	        @Override
	        public Bill next(){
	        	aktualny++;
	        	return report.get(aktualny);
	        }
 
            @Override
            public void remove() {
            }   
    };
 }
	
	
	public static void test(){
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}	

}

0

OK działa :)

metoda test:

public static void test(){
		Iterator<Bill> it = report.iterator();

		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}	

1 użytkowników online, w tym zalogowanych: 0, gości: 1