web-dev-qa-db-fra.com

Comment puis-je rendre ma classe itérable afin que je puisse utiliser foreach syntax?

J'ai des classes Book et BookList. BookList est quelque chose comme ceci:

public class BookList 
{
    private final List<Book> bList = new ArrayList<Book>();

    public int size() { return bList.size(); }

    public boolean isEmpty() {  ... }

    public boolean contains(Book b) { ...  }

    public boolean add(Book b) { ...  }

    public boolean remove(Book b) {  .. } 

    public void clear() { ... }

    public Object get(int index) { ... }

}

Dans ma classe principale, je veux imprimer des titres de livres avec dans chaque boucle:

for(Book b : bList)
{
    b.print();
}

Eclipse dit:

Peut uniquement itérer sur un tableau ou une instance de Java.lang.Iterable

Comment puis-je faire fonctionner cela?

24
mk_

Vous devez implémenter l'interface Iterable , ce qui signifie que vous devez implémenter la méthode iterator(). Dans votre cas, cela pourrait ressembler à ceci:

public class BookList implements Iterable<Book> {
    private final List<Book> bList = new ArrayList<Book>();

    @Override
    public Iterator<Book> iterator() {
        return bList.iterator();
    }

    ...
}
29
andersschuller

Implémentez l'interface Iterable . Cela signifie que vous devez implémenter une méthode qui renvoie un objet Iterator qui itérera sur les éléments d'un BookList.

Dans ce cas, votre méthode iterator() pourrait simplement retourner le résultat de l'appel de bList.iterator(). (Cela entraînera l'itération de for (Book b : somBookList) sur les objets Book dans le BookList.bList ...)

Dans d'autres cas, vous devrez peut-être écrire votre propre classe d'implémentation Iterator<T>, Avec les méthodes T next(), boolean hasNext() et remove(). Par exemple, si vous vouliez empêcher le code externe de supprimer des éléments du BookList via votre itérateur, vous pouvez l'implémenter comme ceci:

public class BookList implements Iterable<Book> {
    private final List<Book> bList = new ArrayList<Book>();
    //...
    @Override
    public Iterator<Book> iterator() {
        return new Iterator<Book> () {
            private final Iterator<Book> iter = bList.iterator();

            @Override
            public boolean hasNext() {
                return iter.hasNext();
            }

            @Override
            public Book next() {
                return iter.next();
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("no changes allowed");
            }
        };
    }
}
25
Stephen C

Ici, nous pouvons voir l'implémentation simple de LinkedList avec itérateur et syntaxe foreach

class LinkedList implements Iterable<LinkedList.Node>{
    private Node node;
    public void add(Object data){
        if(!Optional.ofNullable(node).isPresent()){
            node = new Node();
            node.setData(data);
        }else{
            Node node = new Node();
            node.setData(data);
            Node lastNode = getLastNode(this.node);
            lastNode.setNext(node);
        }
    }

    private Node getLastNode(Node node){
        if(node.getNext()==null){
            return node;
        }else{
            return getLastNode(node.getNext());
        }
    } 

    class Node{
        private Object data;
        private Node next;
        public Object getData() {
            return data;
        }
        public void setData(Object data) {
            this.data = data;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
    }

    public Iterator<Node> iterator() {
        return new NodeIterator();
    }

    class NodeIterator implements Iterator<Node>{
        private Node current;

        public boolean hasNext() {
            if(current == null){
                current = node;
                return Optional.ofNullable(current).isPresent();
            }else{
                current = current.next;
                return Optional.ofNullable(current).isPresent();
            }
        }

        public Node next() {
            return current;
        }
    }
}

public class LinkedListImpl {
    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
        linkedList.add("data1");
        linkedList.add("data2");
        linkedList.add("data3");
        for(LinkedList.Node node: linkedList){
            System.out.println(node.getData());
        }
    }
}
7
user3531588

Pour être plus précis sur la façon de "mettre en œuvre l'interface Iterable":

public class BookList implements Iterable<Book>
{
    private final List<Book> bList = new ArrayList<Book>();

    ... 

    @Override
    public Iterator<Book> iterator()
    {
        return bList.iterator();
    }
}
2
Alden

Pour rendre une classe itérable, vous devez implémenter Iterable Interface.

a) Déclarez la classe comme ci-dessous

public class BookList implements Iterable<Book>

b) Remplacez la méthode iterator()

En savoir plus . J'espère que cela vous aidera.

1
JDGuide