2016-11-07 9 views
2

Я работал с java.util.ListIterator на java.util.LinkedList ожидая, что она работает, как в этом псевдокоде:Java LinkedList 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()); 
    } 
} 
+2

Можете ли вы включить фактический код, с которым вы столкнулись, чтобы прийти к этим выводам? –

+0

извините, здесь. – Agyss

+0

Когда вы вызываете следующий второй раз (2), он переместит курсор на 3, так что предыдущий будет 2. Кажется логичным. –

ответ

5

полезно представить себе, что итераторы в Java никогда не указывает на конкретный элемент, но либо перед первым элементом, в середине между двумя элементами или просто после последнего элемента.

Таким образом, при создании итератора, он выглядит как

1 2 3 4 
^ 

При вызове next, 1 возвращается и итераторы движется вперед:

1 2 3 4 
^ 

Когда вы снова звоните next, 2 возвращается и итераторы перемещаются вперед:

1 2 3 4 
    ^

При вызове prev, 2 возвращается и итераторы движется в обратном направлении:

1 2 3 4 
^ 

Поэтому следующий вызов next вернется 2.

Обратите внимание, что теперь есть возможность получить «текущее» значение итератора. Единственный способ получить значение - переместить итератор.

Другой способ реализации итераторов, которые мы могли видеть на C++. Для использования итератора C++ нам нужно три отдельных действия: получить текущее значение, проверить, есть ли значения перемещения для извлечения и перемещения итератора. Хотя java-подход требует только двух действий: проверьте, есть ли значения перемещения для извлечения и get-value-and-move-iterator. Таким образом, проще реализовать пользовательский итератор в Java, чем в C++.

+0

ok хорошее объяснение того, как оно, по крайней мере, облегчает изображение. Но почему они это сделали? До тех пор, пока это может быть более интуитивно, почему бы не сделать это? – Agyss

+0

Добавлено обоснование. – kgeorgiy

Смежные вопросы