Qual é a diferença entre ArrayList.clear () e ArrayList.removeAll ()?

283

Supondo que arraylistseja definido como ArrayList<String> arraylist, é arraylist.removeAll(arraylist)equivalente a arraylist.clear()?

Em caso afirmativo, posso assumir que o clear()método é mais eficiente para esvaziar a lista de matrizes?

Existem advertências no uso em arraylist.removeAll(arraylist)vez de arraylist.clear()?

ateiob
fonte
Um possível corolário para esta pergunta: quando um pode ser usado em vez do outro?
Corey Ogburn #
3
@ Corey: quando alguém pode querer usar arraylist.removeAll(arraylist)? Não vejo absolutamente nenhuma razão para fazer isso.
Joachim Sauer
@Joachim Sauer Isso é exatamente o que eu queria verificar. Obrigado +2. Mas é a diferença entre elementData[i] = nulle e.remove()significativo?
ateiob 11/08/11
Não há razão sadia para fazer em arrList.removeAll(arrList)vez de arrList.clear(). arrList1.removeAll(arrList2)é uma questão diferente.
11741 Vlad
3
Se apenas a implementação do removeAll () começou com esta linha, toda essa discussão poderia ter sido muito mais divertida !!! if (c == this && !isEmpty()) { clear(); return true; }. Vou ter que enviar isso para o OpenJDK como um patch! ;-)
Julius Musseau

Respostas:

396

O código fonte para clear():

public void clear() {
    modCount++;

    // Let gc do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

O código-fonte para removeAll()(conforme definido em AbstractCollection):

public boolean removeAll(Collection<?> c) {
    boolean modified = false;
    Iterator<?> e = iterator();
    while (e.hasNext()) {
        if (c.contains(e.next())) {
            e.remove();
            modified = true;
        }
    }
    return modified;
}

clear() é muito mais rápido, pois não precisa lidar com todas essas chamadas de método extras.

E, como aponta Atrey, c.contains(..)aumenta a complexidade do tempo removeAllpara O (n 2 ) em oposição ao clearO (n).

Jeffrey
fonte
29
Uma observação que c.contains(...)compara a complexidade de tempo da operação tornaria essa resposta completa.
Atreys
8
A fonte é forte neste. (Para todas as outras respostas: use a fonte, Luke.) Observe como claro () poderia ser implementado como apenas uma linha, tamanho = 0; mas a coleta de lixo não saberia coletar os elementos nas partes inacessíveis da matriz.
Julius Musseau
2
e.remove () é muito mais complexo! O e.remove () também compara a complexidade, assim como o c.contains (...). Em um ArrayList, e.remove () chama ArrayList.remove (int index), que deve mudar o restante da matriz em um.
Julius Musseau
1
@ateiob e.remove () é duas chamadas extras método, uma verificação de intervalo, e um retorno de objeto (interna AbstractList.Itr.remove()e ArrayList.remove(int)), também
Atreys
2
@ julius Se fizesse isso: size = 0; elementData = new Object[10];todo o resto seria coletado como lixo, pois a matriz de backup não tem referências externas.
precisa saber é o seguinte
51

A complexidade temporal de ArrayList.clear()é O(n)e de removeAllé O(n^2).

Então, sim, ArrayList.clearé muito mais rápido.

Geoff
fonte
15

O clear()método remove todos os elementos de um único ArrayList. É uma operação rápida, pois apenas define os elementos da matriz null.

O removeAll(Collection)método, que é herdado AbstractCollection, remove todos os elementos que estão na coleção de argumentos da coleção em que você chama o método. É uma operação relativamente lenta, pois precisa pesquisar em uma das coleções envolvidas.

Ernest Friedman-Hill
fonte
Eu pensei que apenas define todos, não alguns elementos para null. Se não for o caso, como decidiu quais elementos devem ser definidos como nulos?
Farid
2
@ Farid desculpe, meu inglês é muito informal aqui. Eu realmente quis dizer que define todos os elementos como nulos. Eu resolvo isso!
Ernest Friedman-Hill
7

A menos que haja uma otimização específica que verifique se o argumento passado removeAll()é a própria coleção (e duvido muito que essa otimização esteja lá), será significativamente mais lento que um simples .clear().

Além disso (e pelo menos igualmente importante): arraylist.removeAll(arraylist)é apenas um código obtuso e confuso. É uma maneira muito atrasada de dizer "limpe esta coleção". Que vantagem teria sobre o muito compreensível arraylist.clear() ?

Joachim Sauer
fonte
7

Eles servem a propósitos diferentes. clear()limpa uma instância da classe, removeAll()remove todos os objetos fornecidos e retorna o estado da operação.

lucapette
fonte
você pode fornecer um recurso para ler sobre o assunto acima para consulta futher
Kasun Siyambalapitiya
1
@KasunSiyambalapitiya E a resposta aceita , que contém o código fonte dos dois?
Abdul
5

clear() percorrerá a matriz subjacente e definirá cada entrada como nula;

removeAll(collection)passará pelo ArrayList verificando a coleção e remove(Object), se existir.

Eu imagino que clear()é muito mais rápido do que removeAll, porque não está comparando, etc.

Nicholas
fonte
2

A limpeza é mais rápida porque não faz loop sobre os elementos a serem excluídos. Este método pode assumir que TODOS os elementos podem ser excluídos.

Remove allnão significa necessariamente excluir todos os elementos da lista, apenas aqueles fornecidos como parâmetros DEVEM ser excluídos. Portanto, é necessário mais esforço para manter aqueles que não devem ser excluídos.

ESCLARECIMENTO

Por 'loop', quero dizer que não é necessário verificar se o elemento deve ser mantido ou não. Pode definir a referência nullsem pesquisar nas listas de elementos fornecidas a serem excluídas.

ClearÉ mais rápido que deleteall.

Jérôme Verstrynge
fonte
1
Tenho certeza de que isso ArrayList.clear()também deve se repetir.
Joachim Sauer
@JVerstry Você quer dizer que clear () não exclui os elementos que remove da ArrayList?
ateiob 11/08/19
1
Errado, limpar faz loop sobre a matriz interna e define todas as referências como nulas para permitir que o coletor de lixo faça seu trabalho.
devconsole
1
@ Joachim, @ devconsole: Eu acho que ele quis dizer que não terá que repetir / repetir a lista fornecida como parâmetro. target.removeAll(param)iterará parame depois chamará o target.contains(...)que itera target.
Vlad
2
-3 é um pouco duro. Se JVerstry quisesse, ele poderia escrever sua própria implementação Java a partir do zero, que não se repetia. clear () pode ser implementado em O (1), sem loop, enquanto removeAll () DEVE ter algum tipo de algoritmo O (n), não há como satisfazer o contrato da API removeAll () sem examinar todos os elementos.
Julius Musseau
1

clear () será muito mais eficiente. Simplesmente removerá todos os itens. O uso de removeAll (arraylist) exigirá muito mais trabalho, pois verificará todos os itens do arraylist para ver se ele existe no arraylist antes de removê-lo.

CDelaney
fonte
-8

Matriz => depois que o espaço é alocado para uma variável Matriz no tempo de execução, o espaço alocado não pode ser estendido ou removido.

ArrayList => Este não é o caso no arraylist. ArrayList pode aumentar e diminuir no tempo de execução. O espaço alocado pode ser minimizado ou maximizado no tempo de execução.

Arun Kumar
fonte
Isso não responde à pergunta que é a diferença entre ArrayList.clear () e ArrayList.removeAll (), não a diferença entre um Array e um ArrayList.
9284 Pierre
Esta resposta é desnecessária. Não é disso que se trata.
Serafim Costa