Решил переделать циклы перебора списков.
Было так:
for(list.start() ; list.hasElement() ; list.next()) {
CustomObject item = (CustomObject)list.item();
//что-то делаем с объектом item
}
т.е. тут есть завязка на внутренний бегунок current внутри списка, который движется от начала списка first, до конца списка current == null.
такой код потенциально опасен - если в цикле обхода списка вызывается функция, которая должна пробегать по этому же списку, то бегунок current становится неправильным.
для решения я сделал (залипуху/костыль/______) в виде дополнительной переменной storedCurrent и два метода store/restore, полагая, что более глубокой вложенности не будет.
глубже вложенности пока нет, но нафиг надо. лишнее поле, работающее не универсально (вот если бы был стек сохраняемых бегунков, то другое дело), и нужное лишь для одного места в коде.
Стало так:
for(ListNode node = list.first(); node != null; node = node.next) {
CustomObject item = (CustomObject)node.item;
//что-то делаем с объектом item
}
что тут скажешь - классика.
проход в обратном порядке делается аналогично, node = list.last();
node.next, node.item - да, они public
Примечание: иногда нужно пропустить очередной next, в этом случае можно либо писать так:
for(ListNode node = list.first(); node != null; /**/) {
CustomObject item = (CustomObject)node.item;
//что-то делаем с объектом item
if(condition) continue;
node = node.next;
}
или с помощью вспомогательных функций next и skipNext.
for(ListNode node = list.first(); node != null; node = list.next(node)) {
CustomObject item = (CustomObject)node.item;
//что-то делаем с объектом item
if(condition) list.skipStep();
}
......
//LinkedList.java
public void skipStep() {
isNeedSkipStep = true;
}
public ListNode next(final ListNode node) {
if(isNeedSkipStep) {
isNeedSkipStep = false;
return node;
}
return node.next;
}
Доселе я в некоторых местах использовал skip.
Теперь хочу отказаться от этого, чтобы не было путаницы.
пример: вызываешь в цикле метод list.skipStep(), надеешься что он не подведёт,
а в условии цикла про это забываешь, делая простой node = node.next;
UPD: большинство списков требуют только однопаправленный проход.
Есть мысль сделать односвязный список и юзать его по максимуму.
Неудобство - функция удаления узла, т.к. из текущего узла никак не выцепить предыдущий, чтобы перекинуть дальше его ссылку next.
Скорее всего сделаю этот список, в функцию удаления буду передавать два узла - подлежащий_удалению и предыдущий_для_него.
Удалений элементов не слишком много, все они в цикле, т.е. можно легко хранить внешний указатель на prev.