ListIterator 的 Previous() 方法 class
Previous() method of the ListIterator class
我的输出打印 null
以及不应该打印的元素。例如,
MyList<String> l = new MyList<String>();
l.add("A");
l.add("B");
l.add("C");
l.add("D");
l.add("E");
ListIterator<String> iter = l.listIterator(l.size());
while(iter.hasPrevious()){
Object element = iter.previous();
System.out.print(element + " ");
}
结果是:
null E D C B A
previous() 方法有什么问题,我该如何解决它才能不打印 null
?
protected Node<T> beginMarker; // Dummy node marking the front of the list
protected Node<T> endMarker; // Dummy node marking the back of the list
....................
public class AListIterator implements ListIterator<T>{
protected Node<T> current;
protected Node<T> lastVisited = null;
protected int expectedModCount = modCount;
public boolean hasPrevious( ){
if( expectedModCount != modCount )
throw new ConcurrentModificationException( );
return current != beginMarker;
}
public T previous( ){
if( expectedModCount != modCount )
throw new ConcurrentModificationException( );
if(!hasPrevious( ))
throw new RuntimeException("Already at beginning of list");
T prevItem = current.data;
current = current.prev;
return prevItem;
}
两端不需要虚拟标记。这是因为对于长度为 n
的 List
的 ListIterator
只有 n + 1
个可能的光标位置(在每个 n
元素之前和最后一个元素之后element
)。因此你只需要一个虚拟节点。
我会去掉 endMarker
并将其替换为对最后一个节点的引用。然后,当您调用 l.listIterator(l.size())
时,您将获得一个迭代器,其中 current
最初是最后一个节点,因此您不会在迭代开始时获得 null
。
你的问题的原因是current的初始化不正确。当迭代开始时(在构建之后),current 应该指向最后一个元素(当指定的位置是列表的大小时),或者 null 如果没有前面的元素(位置 0,或空列表)。
您不需要开始标记。在最后一次调用 previous
后,Current 将变为 null,因此您可以改用简单的 null 检查。
您也不需要结束标记(无论如何在发布的代码中都没有使用它)。
顺便说一句,在超出末尾的情况下抛出的常见异常是 NoSuchElementException。
我的输出打印 null
以及不应该打印的元素。例如,
MyList<String> l = new MyList<String>();
l.add("A");
l.add("B");
l.add("C");
l.add("D");
l.add("E");
ListIterator<String> iter = l.listIterator(l.size());
while(iter.hasPrevious()){
Object element = iter.previous();
System.out.print(element + " ");
}
结果是:
null E D C B A
previous() 方法有什么问题,我该如何解决它才能不打印 null
?
protected Node<T> beginMarker; // Dummy node marking the front of the list
protected Node<T> endMarker; // Dummy node marking the back of the list
....................
public class AListIterator implements ListIterator<T>{
protected Node<T> current;
protected Node<T> lastVisited = null;
protected int expectedModCount = modCount;
public boolean hasPrevious( ){
if( expectedModCount != modCount )
throw new ConcurrentModificationException( );
return current != beginMarker;
}
public T previous( ){
if( expectedModCount != modCount )
throw new ConcurrentModificationException( );
if(!hasPrevious( ))
throw new RuntimeException("Already at beginning of list");
T prevItem = current.data;
current = current.prev;
return prevItem;
}
两端不需要虚拟标记。这是因为对于长度为 n
的 List
的 ListIterator
只有 n + 1
个可能的光标位置(在每个 n
元素之前和最后一个元素之后element
)。因此你只需要一个虚拟节点。
我会去掉 endMarker
并将其替换为对最后一个节点的引用。然后,当您调用 l.listIterator(l.size())
时,您将获得一个迭代器,其中 current
最初是最后一个节点,因此您不会在迭代开始时获得 null
。
你的问题的原因是current的初始化不正确。当迭代开始时(在构建之后),current 应该指向最后一个元素(当指定的位置是列表的大小时),或者 null 如果没有前面的元素(位置 0,或空列表)。
您不需要开始标记。在最后一次调用 previous
后,Current 将变为 null,因此您可以改用简单的 null 检查。
您也不需要结束标记(无论如何在发布的代码中都没有使用它)。
顺便说一句,在超出末尾的情况下抛出的常见异常是 NoSuchElementException。