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
类认识到类型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() {
}
}
}
答案 0 :(得分:1)
你在哪里:
private Node head;
你应该改为:
private Node<T> head;
同样的事情适用于迭代器中的Node current = head;
。
请记住,您定义的Node
类是通用的 - 您应该始终指定其通用参数,就像您应该始终使用List<Foo>
而不仅仅是原始List
一样。从T extends Comparable<T>
开始,编译器就会知道它满足Node
对D extends Comparable<D>
的要求。
无关:您应该考虑将Node
设为private static class
而不是public class
。 private
适用于封装,因为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.
这就是D
和T
变得相等的地方。
答案 3 :(得分:0)
就像Eugen Halca所说,你需要定义一个迭代器类;我建议稍微改变一下:不是将Node
和ListIterator
定义为列表类的内部类,而是将它们定义为独立的顶级类。我真的不确定你使用内部类除了对命名空间问题感到头疼之外是什么,所以我建议你单独定义它们(除了匿名内部类,那些都没关系。)
因此文件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>
请不要捡到像这样的坏习惯;如果我找到了一本带有代码的书,就像你给出的代码一样(除非用作几乎但不太可接受的代码的例子),我会抛弃它。如果一位教练坚持我这样做,我会放弃课程,因为教师显然不知道他们在说什么。