Eu estive pensando sobre isso por algum tempo e não encontrei uma boa resposta para isso ainda no SO.
O que eu quero fazer é encontrar um elemento em uma lista ligada e excluí-lo imediatamente. Se eu construí a lista ligada no meu próprio, seria fácil, pois Ijust percorrer a lista duplamente ligada:
-> N1 <-> N2 <-> N3 <-> N4 <-> N5 <-
e quando você encontrar por exemplo N3, você alterar os ponteiros node.previous e node.next de tal forma que:
-> N1 <-> N2 <-> N4 <-> N5 <-
Se o elemento no meio, isso exigiria cerca de n / 2 etapas.
Existe uma abordagem adequada para fazer isso em java.util.LinkedList<Integer>
?
Uma abordagem que é insuficiente para mim é:
Integer found = null;
for(Integer elem : list){
if(hasCertainProperty(elem)){
found = elem;
}
}
if(found != null){
list.remove(found);
}
Se o elemento é o elemento do meio na lista (lista dupla ligada, de modo procurar a partir da extremidade da lista é teoricamente possível se o índice é conhecido) seria necessário um máximo de cerca de n / 2 + n / 2 = n passos. Considerando que, no travessia self-made ele só precisaria n / 2 etapas.
Eu sei que os outros 2 e abordagens estão em O (n), mas você sabe, às vezes que n / 2 faz a diferença na prática.
Obrigado pela ajuda.
Java 8 vai fazer isso por você.
list.removeIf(x -> hasCertainProperty(x));
Este laços internamente através da lista, os cheques para cada item x
se satisfaz a sua condição hasCertainProperty
, e remove o item. Eu acho que você não deve se preocupar com o desempenho. Java vai lidar com isso para você.
Além disso, você deve usar ListIterator
que foi exatamente feito para esse fim. Você obtê-lo usando LinkedList # ListIterator :
ListIterator<Integer> listIter = list.listIterator(0);
while (listIter.hasNext()) {
Integer element = listIter.next();
if (hasCertainProperty(element)) {
listIter.remove();
break;
}
}
A sua remove
não precisa de qualquer pesquisa, uma vez que mantém um ponteiro para o nó enquanto a iteração. Por isso, tem as mãos sobre o nó que você deseja remover.