Primeiro faça funcionar direito, depois pense em desempenho.
Isto posto, se você souber o que está fazendo, naturalmente a sua solução correta terá bom desempenho também.
De qualquer maneira, essa história de “em um ArrayList, remover um objeto ainda mantém uma referência para o mesmo” é meio esquisita. Duas coisas:
a) Um ArrayList normal não deve ser usado como uma fila - para filas, use alguma classe que implemente a interface Queue;
b) Tanto o método remove (int) quanto o método remove (Object), em java.util.ArrayList, são implementados anulando-se a posição correspondente no array. Deve ser algum antigo bug do ArrayList que foi corrigido no Java 1.2 mas que as pessoas até hoje acham que ainda existe.
Veja o comentário “let gc do its work”.
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}