Java/ArrayList
A classe ArrayList
é uma implementação da interface List
que utiliza um vetor para armazenar elementos. Uma vez que vetores tem tamanho fixo em Java, a classe ArrayList
se encarrega de criar um novo vetor (internamente) com um tamanho maior e copiar seus elementos correntes para esse novo vetor sempre que for necessário.
O vetor interno da classe ArrayList
é recriado quando há remoções de elemento, adições de elemento no fim da lista além da capacidade dimensionada e adições de elementos que não no final da lista.
Como a operação de recriação do vetor é custosa, busque dimensionar previamente o tamanho da lista, para tal, utilize o construtor sobrecarregado ArrayList(int)
enviando como argumento a capacidade inicial da lista. A capacidade inicial padrão de um objeto ArrayList
é de 10 elementos.
Performance
editarMétodos não constantes na interface List
editarpackage livro_java.colecoes.listas;
import java.util.ArrayList;
public class UtilizandoArrayList {
public static void main(String[] args) {
ArrayList<NavegadorWeb> listaOriginal = new ArrayList<>(2);
ArrayList<NavegadorWeb> listaClone;
listaOriginal.ensureCapacity(15);
listaOriginal.add(new NavegadorWeb("Chrome", "Google"));
listaOriginal.add(new NavegadorWeb("Firefox", "Mozilla"));
listaOriginal.add(new NavegadorWeb("Internet Explorer", "Microsoft"));
listaOriginal.trimToSize();
listaClone = (ArrayList<NavegadorWeb>) listaOriginal.clone();
System.out.printf("%-20s %s%n", "Lista Original", listaOriginal);
System.out.printf("%-20s %s%n", "Lista Clonada", listaClone);
listaClone.get(2).setNome("Edge");
listaClone.remove(1);
System.out.println("\nApós alteração\n");
System.out.printf("%-20s %s%n", "Lista Original", listaOriginal);
System.out.printf("%-20s %s%n", "Lista Clonada", listaClone);
}
}
class NavegadorWeb {
private String nome;
private String empresa;
NavegadorWeb(String nome, String empresa) {
this.nome = nome;
this.empresa = empresa;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public String toString() {
return empresa + " " + nome;
}
}
Saída
Lista Original [Google Chrome, Mozilla Firefox, Microsoft Internet Explorer] Lista Clonada [Google Chrome, Mozilla Firefox, Microsoft Internet Explorer] Após alteração Lista Original [Google Chrome, Mozilla Firefox, Microsoft Edge] Lista Clonada [Google Chrome, Microsoft Edge]
Foi utilizado o construtor sobrecarregado ArrayList<>(int)
para definir a capacidade inicial do vetor interno. Não confunda a capacidade inicial do vetor com o tamanho da Lista. O tamanho é devolvido pelo método size()
e corresponde à quantidade de elementos armazenados já a capacidade é o tamanho do vetor interno o qual não temos acesso.
O método ensureCapacity(int)
recriou o vetor interno com o capacidade para 15 elementos.
O método trimToSize(int)
recriou novamente o vetor interno, porém agora com a capacidade igual ao tamanho da lista, no caso 3.
O método clone()
, sobrescrito de Object
e indicado pela implementação da interface Clonable
, atribuiu uma instância de ArrayList
à variável listaClone
com os mesmos elementos, que são as referências às 3 instâncias do objeto NavegadorWeb
que incluímos na variável listaOriginal
. Como o método clone()
devolve um tipo Object
, foi necessário o uso do cast com o tipo (ArrayList<Navegador>)
. Conforme evidenciado na chamada do método setNome("Edge")
o método clone()
apenas copia a lista e não cada um de seus elementos e com a chamada ao método remove(1)
percebemos que as instâncias de ArrayList
nas variáveis listaOriginal
e listaClone
são diferentes e portanto desvinculadas.
Como você pode ter concluído, o uso dos métodos ensureCapacity(int)
e trimToSize(int)
não é recomendável pois eles recriam o vetor interno do objeto ArrayList
situação em que a performance é prejudicada.
Exercício
editar- Depure o código acima e observe em que chamadas de métodos o atributo elementData é alterado.
- Os métodos
add()
eremove()
alteram a capacidade da instância deArrayList
das variáveislistaOriginal
elistaClone
?