Java LinkedList ListIterator 行为
Java LinkedList ListIterator behavior
我在 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
但是顺序是这样的:
iterator.next is 1
iterator.next is 2
iterator.prev is 2
iterator.next is 2
我不敢相信这是它的工作方式,所以我创建了一个测试,但它产生了相同的输出。
所以我仔细查看了 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.
所以实施是正确的,但我仍然有一个问题,为什么他们选择了这种行为?我得到它的方式不是更直观吗?
测试代码如下:
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());
}
}
可以想象 Java 中的迭代器从不指向特定元素,而是指向第一个元素之前、两个元素中间或最后一个元素之后。
所以,当创建迭代器时,它看起来像
1 2 3 4
^
当您调用 next
时,1
被 return 编辑并且迭代器向前移动:
1 2 3 4
^
当您再次调用 next
时,2
被 return 编辑并且迭代器向前移动:
1 2 3 4
^
当您调用 prev
时,2
被 returned 并且迭代器向后移动:
1 2 3 4
^
因此下一次调用 next
将 return 2
。
请注意,无法获取迭代器的 "current" 值。获取值的唯一方法是移动迭代器。
我们可以在 C++ 中看到的另一种实现迭代器的方法。要使用 C++ 迭代器,我们需要三个独立的操作:检索当前值、检查是否有要检索的移动值和移动迭代器。虽然 java 方法只需要两个操作:检查是否有要检索的移动值和获取值和移动迭代器。所以在 Java 中实现自定义迭代器比在 C++ 中更简单。
我在 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
但是顺序是这样的:
iterator.next is 1
iterator.next is 2
iterator.prev is 2
iterator.next is 2
我不敢相信这是它的工作方式,所以我创建了一个测试,但它产生了相同的输出。 所以我仔细查看了 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.
所以实施是正确的,但我仍然有一个问题,为什么他们选择了这种行为?我得到它的方式不是更直观吗?
测试代码如下:
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());
}
}
可以想象 Java 中的迭代器从不指向特定元素,而是指向第一个元素之前、两个元素中间或最后一个元素之后。
所以,当创建迭代器时,它看起来像
1 2 3 4
^
当您调用 next
时,1
被 return 编辑并且迭代器向前移动:
1 2 3 4
^
当您再次调用 next
时,2
被 return 编辑并且迭代器向前移动:
1 2 3 4
^
当您调用 prev
时,2
被 returned 并且迭代器向后移动:
1 2 3 4
^
因此下一次调用 next
将 return 2
。
请注意,无法获取迭代器的 "current" 值。获取值的唯一方法是移动迭代器。
我们可以在 C++ 中看到的另一种实现迭代器的方法。要使用 C++ 迭代器,我们需要三个独立的操作:检索当前值、检查是否有要检索的移动值和移动迭代器。虽然 java 方法只需要两个操作:检查是否有要检索的移动值和获取值和移动迭代器。所以在 Java 中实现自定义迭代器比在 C++ 中更简单。