【问题标题】:java iterator could not be applied to for_eachjava迭代器无法应用于for_each
【发布时间】:2025-12-20 16:10:07
【问题描述】:

在学习 Java 第 6 版中的数据结构和算法时,我尝试自己构建一个链接位置列表。 Position 实现 Node 来存储数据。 我想构建两个迭代器,一个用于迭代位置,另一个用于迭代位置中的元素。所以我认为两种for-each循环可以应用如下:

    LinkedPositionalList<String> list = new LinkedPositionalList<>();
    list.addFirst("A");
    list.addLast("B");
    list.addLast("V");
    for (Position posi : list.positions()) {
    }
    for (String str:list ) {
    }

事实证明,第二个 for-each 不适用于 type,但第一个效果很好。那么如何让第二个 for-each 迭代器工作呢?

这是我构建此类的代码: p.s.:代码很长。嵌套类的最后一部分尝试实现Iterator接口。之前的代码是构建Linked Positional List的方式,我认为这并不重要......

    public class LinkedPositionalList<E> implements PositionalList<E> {
    private static class Node<E> implements Position<E> {
        private E element;
        private Node<E> prev;
        private Node<E> next;

        public Node(E e, Node<E> p, Node<E> n) {
            element=e;
            prev=p;
            next=n;
        }
        public E getElement() throws IllegalStateException {
            if (next == null) {
                throw new IllegalStateException("Position no longer valid");
            }
            return element;
        }

        public Node<E> getPrev() {
            return prev;
        }

        public Node<E> getNext() {
            return next;
        }

        public void setElement(E e) {
            element=e;
        }

        public void setPrev(Node<E> prev) {
            this.prev = prev;
        }

        public void setNext(Node<E> next) {
            this.next=next;
        }
    }
    private Node<E> header;
    private Node<E> trailer;
    private int size=0;

    public LinkedPositionalList() {
        header = new Node<>(null, null, null);
        trailer = new Node<>(null, header, null);
        header.setNext(trailer);
    }
    private Node<E> validate(Position p)throws IllegalArgumentException {
        if (!(p instanceof Node)) {
            throw new IllegalArgumentException("Invalid p");
        }
        Node<E> node=(Node<E>)p;
        if (node.getNext() == null) {
            throw new IllegalArgumentException("p is no longer in the list");
        }
        return node;
    }

    private Position<E> position(Node<E> node) {
        if (node == header || node == trailer) {
            return null;
        }
        return node;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public Position<E> first() {
        return position(header.getNext());
    }

    public Position<E> last() {
        return position(trailer.getPrev());
    }

    public Position<E> before(Position<E> p) throws IllegalArgumentException {
        Node<E> node = validate(p);
        return position(node.getPrev());
    }
    public Position<E> after(Position<E> p) throws IllegalArgumentException {
        Node<E> node = validate(p);
        return position(node.getNext());
    }

    public Position<E> addBetween(E e, Node<E> pred, Node<E> succ) {
        Node<E> newest = new Node<>(e, pred, succ);
        pred.setNext(newest);
        succ.setPrev(newest);
        size++;return newest;
    }

    public Position<E> addFirst(E e) {
        return addBetween(e, header, header.getNext());
    }

    public Position<E> addLast(E e) {
        return addBetween(e, trailer.getPrev(), trailer);

    }

    public Position<E> addBefore(Position<E> p, E e) throws IllegalArgumentException {
        Node<E> node = validate(p);
        return addBetween(e, node.getPrev(), node);
    }
    public Position<E> addAfter(Position<E> p,E e) throws IllegalArgumentException {
        Node<E> node = validate(p);
        return addBetween(e,node,node.getNext());
    }

    public E set(Position<E> p, E e) throws IllegalArgumentException {
        Node<E> node = validate(p);
        E answer = node.getElement();
        node.setElement(e);
        return answer;
    }
    public E remove(Position<E> p)throws IllegalArgumentException {
        Node<E> node = validate(p);
        Node<E> pre = node.getPrev();
        Node<E> succ = node.getNext();
        pre.setNext(succ);
        succ.setPrev(pre);
        size--;
        E answer = node.getElement();
        node.setNext(null);
        node.setPrev(null);
        node.setElement(null);
        return answer;
    }

//Here is the part that I think should be redesigned!!!!

private class PositionIterator implements Iterator<Position<E>> {
    private Position<E> cursor = first(); // position of the next element to report
    private Position<E> recent = null; // position of last reported element

    public boolean hasNext() { return (cursor != null); }

    public Position<E> next() throws NoSuchElementException {
        if (cursor == null) throw new NoSuchElementException("nothing left");
        recent = cursor; // element at this position might later be removed
        cursor = after(cursor);
        return recent;
    }

    public void remove() throws IllegalStateException {
        if (recent == null) throw new IllegalStateException("nothing to remove");
        LinkedPositionalList.this.remove(recent); // remove from outer list
        recent = null; // do not allow remove again until next is called
    }

} //------------ end of nested PositionIterator class ------------

    //---------------- nested PositionIterable class ----------------
    private class PositionIterable implements Iterable<Position<E>> {
        public Iterator<Position<E>> iterator() { return new PositionIterator(); }
    } //------------ end of nested PositionIterable class ------------


    public Iterable<Position<E>> positions() {
        return new PositionIterable(); // create a new instance of the inner class
    }

    //---------------- nested ElementIterator class ----------------

    private class ElementIterator implements Iterator<E> {
        Iterator<Position<E>> posIterator = new PositionIterator();
        public boolean hasNext() { return posIterator.hasNext(); }
        public E next() { return posIterator.next().getElement(); } // return element!
        public void remove() { posIterator.remove(); }
    }


    public Iterator<E> iterator() { return new ElementIterator(); }



}

【问题讨论】:

  • 一开始,我上传了一个完全错误的版本...我不得不修改它并添加一张图片来描述情况

标签: java interface iterator


【解决方案1】:

对于内置的 Java Collection Framework 类,如果您只想要项目,请使用:

for (String item : list) {
    // do something with item
}

要使用显式迭代器(例如,您可以使用迭代器的 remove() 方法),您可以使用常规的 for 循环:

for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
    String item = iter.next();
    // do something with item
}

当然,您也可以使用while 循环。

对于您的特定班级,很难判断上述是否适用,因为您尚未发布 PositionalList 的定义。

【讨论】:

  • 我一开始就按照你的建议去做。问题中的for_each循环显然是错误的。IDE使它成为第二种方式,我尝试删除它,但忘记像以前一样更改它.....
  • @HqLi - 我的猜测是您的列表类没有实现Iterable&lt;String&gt;,但确实有一个带有签名Iterator&lt;String&gt; iterator() 的方法。如果PositionalList 没有实现某种类型的Iterable,您可以修改LinkedPositionalList 的声明以包含implements Iterable&lt;String&gt;,然后for-each 循环应该可以工作。
【解决方案2】:

将内部循环替换为:

for (String str : list) {
}

这是 Java for-each 循环的正确语法。

【讨论】: