java迭代器中的自定义链表无法遍历整个列表

时间:2015-01-24 06:51:34

标签: java iterator

我在java中创建了一个链表,问题在于

    public void add(T data) 

当我尝试在列表的末尾添加一些东西时,“null”会被添加到列表的末尾。我认为我的迭代器存在一些问题,无法找到最后一个节点。 Plz帮助。

public class LinkedList<T> implements Iterable<T> {
    private Node<T> head;
    /**
     * Default constructor
     * 
     * @param head
     */
    public LinkedList() {
        super();
        this.head = new Node<T>(null);
    }
    /**
     * Inserts a new node at the beginning of this list.
     */
    public void addFirst(T data) {
        Node<T> newNode = new Node<T>(data, head);
        head = newNode;
    }
    public void add(T data) {
        Node<T> tempNpde = head;
        while (tempNpde.next != null) {
            tempNpde = tempNpde.next;
        }
        tempNpde.next = new Node<T>(data, null);
    }
    /**
     * 
     * @param head
     * @return
     */
    public T getNode() {
        return head.data;
    }
    @Override
    public Iterator<T> iterator() {
        return new ListIterator<T>();
    }
    public class ListIterator<T> implements Iterator<T> {
        private Node<T> currentNode;
        /**
         * @param currentNode
         */
        public ListIterator() {
            super();
            this.currentNode = (Node<T>) head;
        }
        @Override
        public boolean hasNext() {
            if (currentNode != null && currentNode.next != null)
                return true;
            else
                return false;
        }
        @Override
        public T next() {
            if (!hasNext())
                throw new NoSuchElementException();
            T node = currentNode.data;
            currentNode = currentNode.next;
            return node;
        }
        @Override
        public void remove() {
            // TODO Auto-generated method stub
        }
    }
    // Same as using struct in C
    private static class Node<T> {
        private T data;
        private Node<T> next;
        /**
         * @param data
         * @param next
         */
        public Node(T data, Node<T> next) {
            super();
            this.data = data;
            this.next = next;
        }
        /**
         * @param next
         */
        public Node(Node<T> next) {
            super();
            this.data = null;
            this.next = next;
        }
    }
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<String>();
        list.addFirst("aaaa");
        list.addFirst("bbbb");
        list.add("dddd");
        Iterator<String> itr = list.iterator();
        while (itr.hasNext()) {
            System.out.println(itr.next());
        }
    }

3 个答案:

答案 0 :(得分:3)

正如已经说过的,最大的问题是你的next()没有按照你的想法行事......试试这个:

public class LinkedList<T> implements Iterable<T> {
    private Node<T> head;

    /**
     * Default constructor
     *
     * @param head
     */
    public LinkedList() {
        super();
        this.head = null;
    }

    /**
     * Inserts a new node at the beginning of this list.
     */
    public void addFirst(T data) {
        Node<T> newNode = new Node<T>(data, head);
        head = newNode;
    }

    public void add(T data) {

        if ( head == null )
        {
            head = new Node<T>(data, null);
            return;
        }

        Node<T> tempNode = head;
        while (tempNode.next != null) {
            tempNode = tempNode.next;
        }
        tempNode.next = new Node<T>(data, null);
    }

    /**
     * @param head
     * @return
     */
    public T getNode() {
        return head.data;
    }

    @Override
    public Iterator<T> iterator() {
        return new ListIterator<T>();
    }

    public class ListIterator<T> implements Iterator<T> {
        private Node<T> currentNode;
        private Node<T> previous;

        /**
         * @param currentNode
         */
        public ListIterator() {
            super();
            this.currentNode = (Node<T>) head;
            this.previous = null;
        }

        @Override
        public boolean hasNext() {
            if (currentNode != null && currentNode.next != null)
                return true;
            else
                return false;
        }

        @Override
        public T next() {
            if (!hasNext())
                throw new NoSuchElementException();
            if ( previous == null )
            {
                previous = currentNode;
                return previous.data;
            }
            T node = currentNode.data;
            currentNode = currentNode.next;
            return currentNode.data;
        }

        @Override
        public void remove() {
            // TODO Auto-generated method stub
        }
    }

    // Same as using struct in C
    private static class Node<T> {
        private T data;
        private Node<T> next;

        /**
         * @param data
         * @param next
         */
        public Node(T data, Node<T> next) {
            super();
            this.data = data;
            this.next = next;
        }

        /**
         * @param next
         */
        public Node(Node<T> next) {
            super();
            this.data = null;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<String>();
        list.add("aaaa");
        list.add("bbbb");
        list.addFirst("cccc");
        list.add("dddd");
        list.add("eeee");
        list.add("ffff");
        for ( String s : list ) // same thing as using an iterator
            System.out.println(s);
    }
}

这是整个班级。这应该为您修复功能,但如果您发现任何不满意的更改(例如,将head更改为最初为null而不是具有空数据的节点),请告诉我......

答案 1 :(得分:2)

更简单的解决方案是将ListIterator#hasNext()实施修改为

@Override
public boolean hasNext() {
    if (currentNode != null)
        return true;
    else
        return false;
}

您的ListIterator未覆盖最后一个元素的原因是它始终会false返回currentNode.next != null,因为它已经结束了。

删除此条件不会破坏迭代器实现。通过上述更改,当ListIterator位于最后一个元素时,hasNext()现在返回true。随后的next()调用将返回currentNode.data并将ListIterator指向null,然后根据需要中断迭代循环。

基本上,你的ListIterator#next()实施就好了。

答案 2 :(得分:1)

为什么不简单地将Head和Tail跟踪为两个单独的字段,当您需要添加新节点时,将Tail.next设置为新节点,然后将Tail设置为新节点?每次想要添加内容时,遍历整个列表都是非常低效的。

此外,要直接回答您的问题,您的迭代器会被破坏。看看你的next()方法正在做什么。事实上,它是否会返回下一个节点?