Индексирование массива
Если у вас есть массивоподобная структура данных (например, фактический массив или что-то вроде ArrayList
), то ссылки на i
, i-1
, i+1
будут давать хорошую производительность так что тут ничего особенного. (Хотя необходимость превращать цикл For-Each в индекс, подсчитывающий цикл For, не очень забавная и является одним из немногих предостережений.)
Ответ, предложенный Сергеем, делает что-то вроде этого.
Универсальный ListIterator
Если вы можете взять в руки ListIterator
(что на самом деле является довольно большим предположением), ответа, предложенного Сураджем, может быть достаточно. Но обратите внимание, что next()
и previous()
перемещают позицию итератора . Поэтому, если вы сделали что-то вроде следующего для каждой итерации цикла: prev = previous(); current = next(); next = next(); previous()
, вы в конечном итоге будете выполнять примерно 4 итерационные операции за цикл. Это не составляет большой проблемы, если итерация дешевая , и, к счастью, это часто имеет место для структур данных, которые предлагают ListIterator
.
Универсальный раствор
Общее решение для любого Iterable
(или Iterator
) не должно делать случайных поисков (как это возможно с массивом) или делать предположения относительно производительности next()
, которую следует вызывать не более N раз, где N - количество доступных элементов.
Вот одна из таких реализаций:
final Iterator<E> it = iterable.iterator();
for (E next = (it.hasNext() ? it.next() : null), current = null; next != null;) {
E previous = current;
current = next;
next = it.hasNext() ? it.next() : null;
// Do something using 'current', 'previous' and 'next'.
// NB: 'previous' and/or 'next' are null when 'current' is
// the first and/or last element respectively
}
Имейте в виду, эта реализация имеет свои собственные предостережения:
- Это сломается, если
Iterable
содержит null
элементов.
- Ни
current
, ни next
не являются эффективно-окончательными , поэтому не могут быть использованы непосредственно в них с разбитыми лямбдами Java 8.