如何使我的类可迭代,以便我可以使用 foreach 语法?

Posted

技术标签:

【中文标题】如何使我的类可迭代,以便我可以使用 foreach 语法?【英文标题】:How can I make my class iterable so I can use foreach syntax? 【发布时间】:2014-02-26 01:08:03 【问题描述】:

我有 BookBookList 课程。 BookList 是这样的:

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 Book get(int index)  ... 
 

在我的主课中,我想在 for each 循环中打印书名:

for(Book b : bList)

    b.print();

Eclipse 说:

只能遍历数组或 java.lang.Iterable 的实例

我怎样才能让它工作?

【问题讨论】:

你需要实现那个接口。 尝试实现Iterable接口。 你在一个简单的 List 中添加了什么?它甚至删除了类型安全,因为它有一个 add(Object) 方法而不是 add(Book) 我在我的真实应用程序中将对象更改为预订,这是自动生成的 eclipse 代码似乎我在发布问题之前忘记将对象更改为预订。 【参考方案1】:

你需要实现Iterable接口,也就是说你需要实现iterator()方法。在您的情况下,这可能看起来像这样:

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

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

    ...

【讨论】:

【参考方案2】:

实现Iterable 接口。这意味着您需要实现一个返回 Iterator 对象的方法,该对象将遍历 BookList 的元素。

在这种情况下,您的iterator() 方法可能只返回调用bList.iterator() 的结果。 (这将导致for (Book b : somBookList) 遍历BookList.bList 中的Book 对象...)

在其他情况下,您可能需要编写自己的Iterator&lt;T&gt; 实现类,并使用T next()boolean hasNext()remove() 方法完成。例如,如果你想阻止外部代码通过迭代器从 BookList 中删除元素,你可以这样实现它:

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");
            
        ;
    

【讨论】:

┼1 用于“其他情况”部分。【参考方案3】:

这里我们可以看到使用迭代器和foreach语法的LinkedList的简单实现

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());
        
    

【讨论】:

【参考方案4】:

更具体地说明如何“实现Iterable 接口”:

public class BookList implements Iterable<Book>

    private final List<Book> bList = new ArrayList<Book>();

    ... 

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

【讨论】:

请注意,这将允许调用者在不通过破坏封装的 BookList.remove() 方法的情况下删除书籍。你最好用return Collections.unmodifiableList(bList).iterator();【参考方案5】:

要使类可迭代,您需要实现Iterable 接口。

a) 如下声明类

public class BookList implements Iterable<Book>

b) 覆盖iterator() 方法

Read More。 希望对你有帮助。

【讨论】:

以上是关于如何使我的类可迭代,以便我可以使用 foreach 语法?的主要内容,如果未能解决你的问题,请参考以下文章

使类可迭代尊重继承

在 R 中运行 foreach 而不返回任何值

Laravel @foreach 使我的网站没有响应

007-迭代器-生成器-协程

Swift 5.+ - 使类可散列?

使我的 python 脚本可执行,以便任何人都可以在任何 Windows 系统中使用?