Тестирование 4-го объекта итератора - Java - PullRequest
0 голосов
/ 25 мая 2018

Можно ли утверждать значение only 4-го объекта в итераторе?

Я видел примеры людей, перебирающих список с помощью Iterator, но я нехочу получить объекты, хранящиеся в индексах от 0 до 2, но только в индексах 3 ...

Я знаю, что всегда могу сделать .next().next().next(), но это выглядит немного... глупоЕсть ли способ, которым я могу сделать что-то вроде .next(4), чтобы идти прямо?

Ответы [ 4 ]

0 голосов
/ 25 мая 2018

Использование гуавы Итераторы

В Гуаве есть общие служебные классы для этой цели.Точный ответ в этих терминах будет следующим:

В этом примере есть некоторый риск встретить IndexOutOfBoundsException , если предоставлено position, это предварительный итератор за пределами границ .

@Test
public void getNthElement() {
    List<String> alphabet = Arrays.asList("a", "b", "c", "d");
    Iterator<String> iterator = alphabet.iterator();

    int position = 3;
    String forthElement = Iterators.get(iterator, 3);

    assertEquals("d", forthElement);
}

Итераторы имеют удобную перегрузку для метода get(Iterator<T>, int), поэтому вы никогда не получите IndexOutOfBoundsException .

@Test
public void getNthElementWithDefaultValue() {
    List<String> alphabet = Arrays.asList("a", "b", "c", "d");
    Iterator<String> iterator = alphabet.iterator();
    int position = 10;
    final String actual = Iterators.get(iterator, position, "default");

    assertEquals("default", actual);
}

Еслинеобходимо просто пропустить или добраться до определенной позиции, но здесь идет упомянутое дело @ Nikolas.Здесь вы можете легко получить NoSuchElementException

@Test
public void advance() {
    List<String> alphabet = Arrays.asList("a", "b", "c", "d", "e", "f");
    Iterator<String> iterator = alphabet.iterator();

    // will return the number of skipped elements
    int advance = Iterators.advance(iterator, 3);

    assertEquals(3, advance);
    assertEquals("d", iterator.next());
}

@Test(expected = NoSuchElementException.class)
public void advanceBeyond() {
    List<String> alphabet = Arrays.asList("a", "b", "c");
    Iterator<String> iterator = alphabet.iterator();

    int advance = Iterators.advance(iterator, 3);

    // throws the exception because we advanced iterator to end
    iterator.next();
}

Если вы не можете или не хотите зависеть от гуавы

Вот очень просто (образовательная) реализация для достижения позиции итератора.

public static <T> T get(Iterator<T> iterator, int pos) {
    if (pos < 0) {
        throw new IllegalArgumentException("Position is negative!");
    }

    int i = 0;

    while (i++ < pos) {
        iterator.next();
    }

    return iterator.next();
}
0 голосов
/ 25 мая 2018

Если вы не ограничены итератором, вы можете использовать Java 8 Streams, чтобы сделать нечто подобное:

Object opt = collection.stream().skip(3).findFirst().orElse(null);
//opt will be null if there were 3 or fewer items in the collection
if(opt!=null) {}

//or to operate on the rest of the Stream
collection.stream().skip(3).forEach(...)
0 голосов
/ 25 мая 2018

Вы можете использовать AssertJ , чтобы кратко утверждать это:

Iterator<Integer> it = List.of(2, 4, 6, 8, 10).iterator();

assertThat(it).element(3).isEqualTo(8);
0 голосов
/ 25 мая 2018

Итераторы не работают с индексом и не знают, по какому индексу появляется последний элемент.Их единственная цель - перебирать элементы, пока не будет достигнут конец.

Это означает, что если вы хотите работать с 4-м элементом, вам нужно четыре раза позвонить Iterator::next().Может возникнуть ситуация, когда в итераторе всего 3 или меньше элементов, поэтому вам нужно проверить по Iterator::hasNext(), в противном случае, когда больше нет элемента и вы снова вызываете next(), NoSuchElementException выбрасывается.


В качестве альтернативы, начиная с Java-8, вы можете использовать метод Iterator::forEachRemaining(Consumer<? super E> action), который выполняет данное действие для каждого из оставшихся элементов.Кроме того, вам нужно использовать трюк с массивом, чтобы избежать эффективного ограничения переменных final в лямбда-выражении.К сожалению, этот метод не принимает BiConsumer<T,U> в качестве аргумента для потребления не только элемента, но и его индекса - вот почему этот трюк.

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int index[] = new int[]{0};

// Prints 4 and 8
Iterator<Integer> iterator = list.iterator();
iterator.forEachRemaining(i -> {
    if ((index[0]+1)%4 == 0) {
        // Here you work both with the element `i` and its index `index[0]`
        System.out.println(i);     
    }
    index[0]++;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...