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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章