Показать сообщение отдельно
Старый 15.01.2015, 14:56   #21
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Смесь: Неочевидное + Оптимизация

Решил переделать циклы перебора списков.

Было так:
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 != nullnode 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 != nullnode = 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.
(Offline)
 
Ответить с цитированием