【问题标题】:How can I make my class iterable so I can use foreach syntax?如何使我的类可迭代,以便我可以使用 foreach 语法?
【发布时间】: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 代码似乎我在发布问题之前忘记将对象更改为预订。

标签: java foreach iterable


【解决方案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。 希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2021-09-21
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 2010-11-07
        • 2017-04-04
        • 2020-12-21
        相关资源
        最近更新 更多