Java LinkedList ListIterator行为

And*_*nel 2 java linked-list list listiterator

我正在使用java.util.LinkedList上的java.util.ListIterator,期望它像在这个伪代码中一样工作:

list = (1,2,3,4)
iterator.next should be 1
iterator.next should be 2
iterator.prev should be 1
iterator.next should be 2
Run Code Online (Sandbox Code Playgroud)

但顺序是这样的:

iterator.next is 1
iterator.next is 2
iterator.prev is 2
iterator.next is 2
Run Code Online (Sandbox Code Playgroud)

我无法相信这是它的工作方式,因此我创建了一个测试,但它产生相同的输出.所以我仔细研究了ListIterator的定义,当然是:

next()
Returns the next element in the list and advances the cursor position.
previous()
Returns the previous element in the list and moves the cursor position backwards.
Run Code Online (Sandbox Code Playgroud)

所以实现是正确的,但我仍然怀疑为什么他们选择了这种行为?我得到它的方式不会更直接吗?

这是测试的代码:

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import java.util.LinkedList;
import java.util.ListIterator;

public class LinkedListTest {
    ListIterator<Integer> iterator;

    @Before
    public void setUp() throws Exception {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 1; i < 5; i++) {
            list.add(i);
        }
        iterator = list.listIterator();
    }

    @Test
    public void successfullTest() throws Exception
    {
        assertEquals(1, (int) iterator.next());
        assertEquals(2, (int) iterator.next());
        assertEquals(2, (int) iterator.previous());
        assertEquals(2, (int) iterator.next());
        assertEquals(3, (int) iterator.next());
        assertEquals(4, (int) iterator.next());
    }

    @Test
    public void failingTest() throws Exception
    {
        assertEquals(1, (int) iterator.next());
        assertEquals(2, (int) iterator.next());
        assertEquals(1, (int) iterator.previous());
        assertEquals(2, (int) iterator.next());
        assertEquals(3, (int) iterator.next());
        assertEquals(4, (int) iterator.next());
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 5

可以想象Java中的迭代器永远不会指向特定元素,而是指向第一个元素之前,两个元素之间的中间或最后一个元素之后.

因此,当迭代器创建时,它看起来像

 1 2 3 4
^
Run Code Online (Sandbox Code Playgroud)

当你调用时next,1返回并且迭代器向前移动:

 1 2 3 4
  ^    
Run Code Online (Sandbox Code Playgroud)

当你next再次调用时,2返回并且迭代器向前移动:

 1 2 3 4
    ^
Run Code Online (Sandbox Code Playgroud)

当你调用时prev,2返回并且迭代器向后移动:

 1 2 3 4
  ^    
Run Code Online (Sandbox Code Playgroud)

所以接下来的电话next会回来2.

请注意,现在有办法获取迭代器的"当前"值.获取值的唯一方法是移动迭代器.

我们可以在C++中看到实现迭代器的另一种方法.要使用C++迭代器,我们需要三个单独的操作:检索当前值,检查是否有移动值来检索和移动迭代器.虽然java方法只需要两个动作:检查是否有要移动的移动值和get-value-and-move-iterator.因此,在Java中实现自定义迭代器比在C++中实现更简单.