2

EDIT2:在你们提出了很多很好的建议之后,我决定DT. 作业中给出的方法确实指定了 a D,但由于T有效并且你们中的绝大多数人认为它应该是T,我只是要更改它,我的老师可以处理它。如果我发现一些神奇的解决方法可以解决所有问题并使其D正常工作,我会在此处发布。谢谢大家的帮助!我今天学到了很多。


编辑:我想重复一遍,因为我想我一开始并不清楚这一点,我不能把它改成T next(). 在分配描述中,它将方法列为D next()。我无法改变这一点,这就是它被赋予我的方式。对于那些建议我改变它的人,谢谢你的时间,但这不是一个选择。


我正在执行一项任务,其中为我提供了自定义 List 类的“骨架”,我必须编写所有方法。Node最后还提供了一个类List。我应该写一个方法Iterator在其中的类。但是,由于泛型只出现在类中,所以我尝试编写的类一直告诉我无法解析为类型。我试过在 Node 类中编写这个类,但后来我明白了。next()D next() throws NoSuchElementExceptionDNodeIteratorDThe return type is incompatible with Iterator<T>.next()

根据分配,迭代器类必须是类型T,这就是类型List,但next()方法必须返回类型 D。请有人帮我理解我可以做些什么来让Iterator类识别类型D是同一个Node班?我已经包含了没有实现任何其他方法的框架代码——我正在尝试编写的 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

4 回答 4

1

你在哪里:

private Node head;

你应该有:

private Node<T> head;

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

请记住,Node您定义的类是泛型的——您应该始终指定其泛型参数,就像您应该始终使用List<Foo>而不只是使用 raw 一样List。因为T extends Comparable<T>,编译器会知道它满足NodeD extends Comparable<D>.


不相关:您应该考虑制作Nodeaprivate static class而不是 a public class。这private有利于封装,因为您的用户List不应该关心它的内部链表实现。这static是一个很好的做法,除非内部类实际上需要访问其封闭类中的字段(也就是说,除非Node需要访问 中的字段List,它在您的代码中没有)。

于 2013-10-15T20:36:39.887 回答
0

Like Eugen Halca said, you need to define an iterator class; I would recommend doing it slightly differently: instead of defining Node and ListIterator as inner classes of the list class, I would define them as independent top-level classes. I'm really not sure what it is you get from using inner classes other than a big headache over namespace issues, so I would recommend just defining them independently (except for anonymous inner classes, those are OK).

So the file ListIterator.java should contain:

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
    }

}

Note the use of annotations to help protect you against problems that can arise if no parent class or interface actually defines a method you believe is being overridden. You also need to add one to the iterator method in your List class, because that method is (supposedly) inherited from the Iterable interface.

The file Node.java should contain:

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

Note that the type parameter for the Node class should NOT be specified Comparable, because there are no methods in the Node class that invoke any methods specified in the Comparable interface. Any class that will be using the comparability of the elements stored in the nodes will already know about the comparability of it, but forcing them to be comparable means you can't use that class for other things you might like to be able to.

Please, don't pick up bad habits like these; if I ever found a book with code in it like the code you gave (except if used as an example of almost-but-not-quite-acceptable code), I would throw it out. If an instructor were insisting that I do it this way, I would drop the class, since clearly the instructor has no idea what they are talking about.

于 2013-10-15T21:19:00.317 回答
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
    }

    }
于 2013-10-15T20:32:40.467 回答
0

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

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

这就是 theD和 theT相等的地方。

于 2013-10-15T20:32:50.327 回答