当Node泛型不同于List泛型时,在Java泛型列表中实现Iterable

时间:2013-10-15 20:20:02

标签: java generics iterator

EDIT2:经过大家提出的很多好建议后,我决定将D更改为T。作业中给出的方法确实指定了D,但由于T有效且绝大多数人认为它应该是T,我只是要改变它和我的导师可以处理它。如果我发现一些神奇的解决方法可以修复所有内容并使D正常工作,我会在此处发布。谢谢大家的帮助!我今天学到了很多东西。


编辑:我想重复一遍,因为我想我起初并不清楚这一点,我不能把它改为T next()。在分配说明中,它将方法列为D next()。我不能改变它,它是如何给我的。对于那些建议我改变它的人,谢谢你的时间,但这不是一个选择。


我正在进行一项任务,其中为我提供了自定义List类的“骨架”,我必须编写所有方法。最后Node内还提供了List课程。我应该写一个Iterator类,其中next()方法是D next() throws NoSuchElementException。但是,由于D泛型仅出现在Node类中,因此我尝试编写的Iterator类一直告诉我D无法解析为某个类型。我试过在Node类中编写类,但后来我得到了The return type is incompatible with Iterator<T>.next()

根据赋值,迭代器类必须是T类型,这是List的类型,但next()方法必须返回类型D.请有人请帮助我理解我可以做些什么来让Iterator类认识到类型DNode类中的类型相同?我已经包含了骨架代码而没有实现任何其他方法 - 我试图编写的Iterator类位于“附加类”下的底部。

我可以在世界上如何使next()方法有效吗?感谢任何花时间向我解释这一点的人。

package list;

import java.lang.Iterable;
import java.util.Iterator;
import java.lang.IndexOutOfBoundsException;
import java.util.NoSuchElementException;

public class List<T extends Comparable<T>> implements Iterable<T> {

    public class Node<D extends Comparable<D>> {
        private D data;
        private Node<D> next;
    }

    private Node head;

    public List() {
        head = null;
    }

    public boolean add(T newElt) {
        if(head == null){
            head.data = newElt;
            head.next = null;
            return true;
        }
        return false;
        //Unfinished.  Iterate to check for duplicates.
    }

    public T getFirst() throws NoSuchElementException {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public T get(int index) throws IndexOutOfBoundsException {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public T lookup(T element) {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public int size() {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public void delete(T element) throws NoSuchElementException {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public void reset() {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public String toString() {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public List<T> subList(int start, int end) throws NoSuchElementException {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public void removeSubList(int start, int end) throws NoSuchElementException {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public boolean equals(Object obj) {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public Iterator<T> iterator() {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public Comparator<List<T>> lengthComparator() {
        throw new UnsupportedOperationException("You must write this method.");
    }

    public Comparator<List<T>> orderComparator() {
        throw new UnsupportedOperationException("You must write this method.");
    }


    /*
     * Additional classes
     */


    public class ListIterator<T> implements Iterator<T>{

        Node current = head; 

        public boolean hasNext() {
            if(head.next == null){
                return false;
            }
            return true;
        }

        public D next() throws NoSuchElementException{
            return null;
        }

        public void remove() {

        }

    }

}

4 个答案:

答案 0 :(得分:1)

你在哪里:

private Node head;

你应该改为:

private Node<T> head;

同样的事情适用于迭代器中的Node current = head;

请记住,您定义的Node类是通用的 - 您应该始终指定其通用参数,就像您应该始终使用List<Foo>而不仅仅是原始List一样。从T extends Comparable<T>开始,编译器就会知道它满足NodeD extends Comparable<D>的要求。


无关:您应该考虑将Node设为private static class而不是public classprivate适用于封装,因为List的用户不应该关心其内部链表实现。 static是一个很好的做法,除非内部类实际上需要访问其封闭类中的字段(即,Node需要访问List中的字段,而不是{{1}}中的字段你有的代码。)

答案 1 :(得分:0)

你的迭代器类应该如下:

public class ListIterator<T> implements Iterator<T>{

    Node<T> current = head; 

    public boolean hasNext() {
        if(current.next == null){ // check if next node exists
            return false; // doesn't exist
        }
        return true; // exists
    }

    public D next() throws NoSuchElementException{
        if (current.next == null){ // check if there is next node
            throw new NoSuchElementException(); // if not throw new exception
        }
        current = current.next; // changing to next node
        return current.data; // provide the data in next node
    }

    public void remove() {
        // since Node class save the reference to next Node and doesn't for previous, 
        // removing objects it quite difficult, because it will break the lis
    }

    }

答案 2 :(得分:0)

Node类将包含一个D,它与T相同,因为您将使用以下代码创建节点:

Node<T> newNode = new Node<T>();
newNode.data = newElt.

这就是DT变得相等的地方。

答案 3 :(得分:0)

就像Eugen Halca所说,你需要定义一个迭代器类;我建议稍微改变一下:不是将NodeListIterator定义为列表类的内部类,而是将它们定义为独立的顶级类。我真的不确定你使用内部类除了对命名空间问题感到头疼之外是什么,所以我建议你单独定义它们(除了匿名内部类,那些都没关系。)

因此文件ListIterator.java应包含:

protected class ListIterator<T> implements Iterator<T> {

    Node<T> last, current;

    public ListIterator(Node start) {
        current = start;
    }

    @Override
    public boolean hasNext() {
        if(current.next == null) return false;
        return true;
    }

    @Override
    public D next() throws NoSuchElementException{
        if (current.next == null) throw new NoSuchElementException();
        last = current;
        current = current.next;
        return last.data; //otherwise it will skip the first item!
    }

    @Override
    public void remove() throws IllegalStateException {
        if(last == null) throw new IllegalStateException();
        current = last.next = current.next;
        //doing it this way, the remove method is very simple
    }

}

请注意,如果没有父类或接口实际定义您认为被覆盖的方法,则使用注释来帮助保护您免受可能出现的问题的影响。您还需要在iterator类中的List方法中添加一个,因为该方法(假设)是从Iterable接口继承的。

文件Node.java应包含:

protected class Node<T> {
    private T data;
    private Node<T> next;
}

请注意,Node类的type参数应 NOT 指定Comparable,因为Node类中没有调用任何方法的方法在Comparable接口中指定。任何将使用存储在节点中的元素的可比性的类已经知道它的可比性,但是强制它们具有可比性意味着你不能将该类用于你可能想要的其他事物。 / p>

请不要捡到像这样的坏习惯;如果我找到了一本带有代码的书,就像你给出的代码一样(除非用作几乎但不太可接受的代码的例子),我会抛弃它。如果一位教练坚持我这样做,我会放弃课程,因为教师显然不知道他们在说什么。