java数据结构——4迭代器(iterator)

四、迭代器(iterator)

如果我们想遍历数组,这很容易,因为可以用数组的下标跟踪所在的位置,然而在链表中,节点没有这样的下标,怎样才能提供给链表用户类似于数组下标的东西呢?这就是迭代器(iterator)的作用。

我们知道添加到链表中的数据(data),都会包装成一个节点(node),节点之间通过引用保存了先后关系(pre、next)。但是由于在获取数据时(如getFirst),返回的直接是数据(data),数据本身没有其之后数据的引用,因此无法遍历。

但是node存在这样的引用,如果我们直接把node返回给用户,让用户自己从node获取数据,不就可以实现遍历了吗?我们可以提供一个getFirstNode()方法,然后按照类似以下代码片段进行遍历:

Node node=linkedList.getFirstNode();
while(node!=null){
     Object data=node.getData();
     //. . . 操作数据
    node=node.getNext();//获取下一个node
}

上述这样的方式,的确是可以遍历链表中的所有元素,但是却不是一个好的设计方式,因为我们把链表的基础数据结构Node直接暴露给用户了,普遍的做法就是利用迭代器(iterator)来实现链表的迭代功能。

我们以上一节编写的SingleLinkList为例进行讲解,为其提供一个迭代所有元素的迭代器
关于迭代器,Java中已经相关的接口定义java.util.Iterator,其定义了一个迭代器最基本要实现的功能,虽然实现这个接口不是必要的,但是这里打算实现这个接口:

public interface Iterator<E> {
    /** 是否还有更多的元素可以迭代*/
    boolean hasNext();
    /** 返回下一个元素*/
    E next();
    /** 将迭代器当前迭代的元素,从链表中移除*/
    void remove();
}

1、在SingleLinkList中定义一个内部类NodeIterator,实现Iterator接口

2、修改SingleLinkList,新增一个返回迭代器的方法

关于返回迭代器方法的名称,是任意的,不过最好还是符合某种规范,java.lang.Iterable接口,定义了这样一个放回迭代器的方法:

public interface Iterable<T> {
    Iterator<T> iterator();
}

其返回类型就是Iterator,现在你可能知道我们让NodeIterator实现Iterator接口的原因了,因为这样,我们就可以将自己写的迭代器通过Java的标准接口返回
现在我们让SingleLinkList实现.Iterable接口,实现这个方法。

下面是代码实现:

public class SingleLinkList<V> implements Iterable<V>{
    protected Node firstNode = null;// 链表的第一个节点
    protected int size;// 链表中维护的节点总数
    /**
     * 添加到链表最前面
     * @return 
     */
    public Node addFirst(V v) {
        Node node = new Node();
        node.setData(v);
        Node currentFirst = firstNode;
        node.setNext(currentFirst);
        firstNode = node;
        size++;
        return node;
    }
    /**
     * 如果链表中包含要删除的元素,删除第一个匹配上的要删除的元素
     */
    public void remove(V v) {
        if (size == 0) {
            return;
        }
        if (size == 1) {
            firstNode = null;
            size--;
            return;
        }
        if (Objects.equals(firstNode.getData(), v)) {
            firstNode = firstNode.getNext();
            size--;
        }
        Node pre = firstNode;
        Node next = pre.getNext();
        while (next != null) {
            if (Objects.equals(next.getData(), v)) {
                pre.setNext(next.getNext());
                size--;
                next = pre.getNext();
            }else {
                pre = pre.getNext();
                next = pre.getNext();
            }
        }
    }
    /**
     * 是否包含,包含返回true,不包含返回false
     */
    public boolean contains(V v){
        if (size == 0) {
            return false;
        }
        Node current = firstNode;
        while (current != null) {
            if (Objects.equals(v, current.getData())) {
                return true;
            }
            current = current.getNext();
        }
        return false;
    }
    /**
     * 获取第一个元素
     */
    public V getFirst(){
        if (size == 0) {
            return null;
        }
        return (V)firstNode.getData();
    }
    /**
     * 删除第一个元素
     */
    public V removeFirst(){
        if (size == 0) {
            return null;
        }
        Node temp = firstNode.getNext();
        firstNode = temp;
        if (temp == null) {
            return null;
        }
        size--;
        return (V)temp.getData();
    }
    /**
     * 打印链表的所有元素
     */
    public void showAll(){
        if (size != 0) {
            Node current = firstNode;
            while (current != null){
                System.out.print(current.getData() + "/");
                current = current.getNext();
            }
        }
    }
    /**
     * 获取元素个数
     */
    public int getSize(){
        return size;
    }
    /**
     * 内部类
     */
    private  class NodeIterator<E> implements Iterator<E>{
        private Node node;
        public NodeIterator(Node current) {
            this.node = current;
        }
        @Override
        public boolean hasNext() {
            node = node.getNext();
            return node != null;
        }
        @Override
        public E next() {
            Object data = node.getData();
            return (E)data ;
        }
        @Override
        public void remove() {
            V v = (V) node.getData();
            SingleLinkList.this.remove(v);
        }
    }
    @Override
    public Iterator<V> iterator() {
        return new NodeIterator<V>(firstNode);
    }
}

猜你喜欢

转载自blog.csdn.net/zajiayouzai/article/details/79147060