Как использовать итератор в этом случае? - PullRequest
0 голосов
/ 24 сентября 2010

Я должен перебрать аррайлиста таким образом.

ArrayList<Integer> li = new ArrayList<Integer>();
li.add(20);
li.add(30);
li.add(40);
li.add(50);
li.add(70);

for (int i = 0; i < li.size() - 1; i++)
    System.out.println(li.get(i) + " " + li.get(i + 1));

Выход:

20 30
30 40
40 50
50 70

Как сделать то же самое с помощью итератора?

Ответы [ 4 ]

6 голосов
/ 24 сентября 2010

Используйте два итератора.Я проверил это, и это сработало для меня.

    Iterator<Integer> first = li.listIterator();

    // Will raise IndexOutOfBoundsException if list is empty.
    Iterator<Integer> second = li.listIterator(1);

    while (second.hasNext()) {
        System.out.println(first.next() + " " + second.next());
    }

Редактировать : Нет необходимости во внутреннем if.Дурак я.

Объяснение: метод listIterator(index) возвращает итератор, который начинается с указанной позиции в списке, где listIterator() возвращает итератор, который начинается с нулевой позиции.

Поэтому итератор first начинается с 0, а second начинается с 1.Тогда это просто вопрос печати next() на обоих.Это будет работать независимо от того, является ли количество элементов в списке нечетным или четным.

Редактировать 2

Моя логика фу сегодня очень слабая.Спасибо @ barjak за указание на случай с пустым списком и ненужными first.hasNext().

1 голос
/ 24 сентября 2010

Слегка измененное решение Sagar V, чтобы оно заработало.Для этого достаточно одного итератора.

Iterator iter = li.iterator();
        Integer int1 = null;

        while (iter.hasNext()) {
            if (int1 == null) {
                int1 = (Integer) iter.next();
            }

            System.out.print(int1 + " ");
            if (iter.hasNext()) {
                Integer int2 = (Integer) iter.next();
                System.out.println(int2);
                int1 = int2;
            } else {
                break;
            }
        }
    }
1 голос
/ 24 сентября 2010

Это немного сложнее:

Iterator<Integer> iter = li.iterator();
if (iter.hasNext()) {
    for (int y = iter.next(), x; iter.hasNext(); y = x) {
        x = iter.next();
        System.out.println(y + " " + x);
    }
}

или:

if (iter.hasNext()) {
    for (int x = iter.next(); iter.hasNext();) {
        System.out.println(x + " " + (x = iter.next()));
    }
}
0 голосов
/ 24 сентября 2010

Существует множество решений, которые могут подойти в зависимости от ваших потребностей.

Решение 1: просмотр в фиксированном размере

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

List<Integer> l = // initialization code

int limitIndex = Math.max(l.size()-1, 0); // needed for empty list
for (int v : l.subList(0, limitIndex)) {
    // your code
}

Обратите внимание, что я использовал цикл 'foreach', который является удобным способом использования итераторов. Это строго эквивалентно этому коду:

Iterator<Integer> it = l.subList(0, limitIndex).iterator();
while(it.hasNext()) {
    int v = it.next();
    // your code
}

Также обратите внимание, что метод subList не создает новый список: он только создает «представление» в исходном списке. Содержимое исходного списка не копируется, и все изменения, внесенные в исходный список, видны из списка, созданного subList.

Решение 2: пользовательский Iterator / Iterable

Если все, что вам нужно, это итератор, который всегда повторяет от 0 до n-1, вы можете определить новый Iterable с учетом этой конкретной потребности.

public class NoLastIterable<T> implements Iterable<T> {

    private final List<T> backend;

    public NoLastIterable(List<T> backend) {
        this.backend = backend;
    }

    public Iterator<T> iterator() {
        return new Iterator<T>() {

            private int nextIndex;

            public boolean hasNext() {
                return nextIndex < backend.size() -1;
            }

            public T next() {
                return backend.get(nextIndex++);
            }

            public void remove() {
                throw new UnsupportedOperationException("not implemented");
            }

        };
    }
}

Этот класс используется так:

for (int v : new NoLastIterable<Integer>(l)) {
    // your code
}

Раствор 3

Вы даже можете создать свой собственный вид List, как и subList, но с большей гибкостью.

public class NoLastList<T> extends AbstractList<T> {

    private final List<T> backend;

    public NoLastList(List<T> backend) {
        this.backend = backend;
    }

    @Override
    public T get(int index) {
        if (index >= size()) {
            throw new IndexOutOfBoundsException();
        }
        return backend.get(index);
    }

    @Override
    public int size() {
        return Math.max(0, backend.size()-1);
    }

}

То же использование, что и в других решениях:

for (int v : new NoLastList<Integer>(l)) {
    // your code
}

Преимущества этого решения можно увидеть в следующей ситуации:

  1. исходный список создан и инициализирован
  2. создается экземпляр NoLastList (в виде исходного списка)
  3. некоторые элементы добавлены в исходный список

В этой ситуации повторение по NoLastList будет учитывать элементы, которые были добавлены в последнее время. NoLastList всегда представляет представление элементов от 0 до n-1, даже если n (размер) изменяется.

...