Neste artigo vou apresentar algumas características da classe ArrayList do Java e demonstrar a utilização de alguns dos métodos mais utilizados.
Por que utilizar a classe ArrayList?
Quando utilizamos o array padrão do Java, precisamos determinar qual será o seu tamanho no momento de sua criação. Esse tamanho é fixo e, uma vez criado, não conseguimos alterar o número de elementos. Se por exemplo, precisarmos adicionar mais um elemento, é necessário criar um novo array e copiar todos os elementos que estão no antigo array para o novo. Essa prática acaba sendo muito trabalhosa e também provoca uma perda de desempenho.
A classe ArrayList serve justamente para solucionar esse problema, pois ela permite que sejam criados arrays dinâmicos, ou seja, se precisarmos adicionar mais um elemento, o ArrayList faz esse redimensionamento de forma automática.
Hierarquia da Classe ArrayList
A classe ArrayList faz parte do Java Collections, que pertence ao pacote java.util. O ArrayList é uma implementação da interface List, que por sua vez estende a interface Collection. No diagrama abaixo, as linhas cheias representam “extends” e as linhas pontilhadas “implements”:
Além dos métodos herdados de Collection, a interface List fornece métodos que permitem a manipulação de elementos com base na posição (ou índice) em que eles se encontram. Assim como nos vetores, o índice começa em zero.
Alguns dos principais métodos
- add(item) -> adiciona um novo elemento ao ArrayList. O elemento é inserido no final da lista;
- add(posição, item) -> insere o elemento em uma posição específica da lista;
- remove(posição) -> remove o elemento de uma determinada posição da lista;
- set(posição, item) -> substitui um elemento em uma posição específica;
- get(posição) -> retorna o elemento da posição especificada;
- indexOf(item) -> retorna a posição da primeira ocorrência do elemento especificado;
- contains(item) -> retorna verdadeiro caso a lista contenha o elemento especificado. Caso contrário, retorna falso;
- clear() -> remove todos os elementos da lista;
- isEmpty()-> retorna verdadeiro se a lista estiver vazia. Caso contrário retorna falso;
- size()-> retorna a quantidade de elementos da lista.
Formas de inicializar um ArrayList
Podemos inicializar o ArrayList sem especificar o tipo dos elementos que a lista conterá, como mostrado a seguir:
ArrayList lista = new ArrayList();
Esse formato permite que adicionemos elementos de qualquer tipo na lista. No exemplo abaixo, repare que os tipos dos dados inseridos estão misturados:
import java.util.ArrayList;
public class TesteArrayList {
public static void main(String[] args) {
ArrayList lista = new ArrayList();
lista.add("Ana");
lista.add(123);
lista.add("Maria");
lista.add(12.34);
lista.add("Paulo");
System.out.println(lista);
}
}
Saída:
[Ana, 123, Maria, 12.34, Paulo]
Se por exemplo, precisássemos armazenar o elemento de determinada posição em uma variável, seria necessário fazer o type cast, indicando o tipo do Objeto. No exemplo abaixo, estamos tentando armazenar o elemento da posição 1 na String nome, no entanto esse elemento é um valor inteiro(123), o que acabará causando um “run time exception” no momento da execução.
import java.util.ArrayList;
public class TesteArrayList {
public static void main(String[] args) {
ArrayList lista = new ArrayList();
lista.add("Ana");
lista.add(123);
lista.add("Maria");
lista.add(12.34);
lista.add("Paulo");
// vai causar run time exception,
// pois o elemento da posição 1 é um inteiro(123)
String nome = (String) lista.get(1);
System.out.println(lista);
}
}
Saída:
java.lang.ClassCastException
class java.lang.Integer cannot be cast to class java.lang.String
Portanto, para evitar problemas, o ideal é não permitirmos que o ArrayList armazene elementos com tipos misturados. Para limitar o ArrayList podemos usar o Generics, inserindo o tipo de objeto que a lista irá armazenar.
Obs.: Não são aceitos tipos primitivos. Por exemplo, para inserir valores inteiros, usamos Integer ao invés de int.
ArrayList<Integer> lista = new ArrayList<>();
Veja um exemplo em que criamos uma lista de elementos inteiros.
import java.util.ArrayList;
public class TesteArrayList {
public static void main(String[] args) {
ArrayList<Integer> lista = new ArrayList<>();
lista.add(1);
lista.add(2);
lista.add(3);
System.out.println(lista);
}
}
Saída:
[1, 2, 3]
Podemos também utilizar o polimorfismo e declarar uma referência da interface List e instanciar a classe ArrayList.
List<Integer> lista = new ArrayList<>();
A vantagem de declararmos o ArrayList desta maneira é que podemos a qualquer momento, caso seja necessário, alterar a classe que implementa a interface List. Por exemplo, ao invés de utilizar a classe ArrayList podemos optar por usar a LinkedList ou a Vector, pois ambas implementam a interface List.
List<Integer> lista = new LinkedList<>();
Caso já saibamos quantos elementos o array terá, podemos passar a capacidade inicial por parâmetro no construtor. Isso é muito recomendado nestes casos, pois evitamos desperdício de memória. No exemplo abaixo, estamos iniciando nosso ArrayList com 5 posições. Caso seja necessário adicionar mais elementos posteriormente, o redimensionamento é feito de forma automática.
List<String> lista = new ArrayList<>(5);
Podemos ainda criar uma lista a partir de outra já existente. Basta passarmos a lista base por parâmetro no construtor:
List<String> lista = new ArrayList<>(5);
lista.add("Maria");
lista.add("Pedro");
List<String> novaLista = new ArrayList<>(lista);
Exemplo de como utilizar ArrayList
No exemplo a seguir, será demonstrado como usar alguns dos métodos fornecidos pela classe ArrayList.
- Primeiro, vamos instanciar uma lista;
- Depois, vamos adicionar cinco cidades usando o método add(item);
- Percorreremos a lista e exibiremos essas cidades usando o for. Aqui serão utilizados os métodos get(posição) e size();
- Com o método remove(posição), removeremos a cidade da posição 3 (Manaus);
- Com o método add(posição, item), adicionaremos a cidade “Florianópolis” na posição zero;
- Vamos percorrer novamente a lista usando for-each;
- Agora usaremos o indexOf(item) para retornar a posição da cidade “Recife” e, com o método set(posição, item) substituiremos “Recife” por “Salvador”;
- Agora vamos percorrer a lista novamente, mas usando Iterator. (O Iterator é um padrão de projeto que permite iterar entre os elementos dentro da coleção).
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class TesteArrayList {
public static void main(String[] args) {
// 1) Primeiro, vamos instanciar uma lista;
List<String> cidades = new ArrayList<>();
// 2) Depois, vamos adicionar cinco cidades
// usando o método add(item);
cidades.add("São Paulo");
cidades.add("Rio de Janeiro");
cidades.add("Recife");
cidades.add("Manaus");
cidades.add("Curitiba");
// 3) Percorreremos a lista e exibiremos
// essas cidades usando o for.
// Aqui serão utilizados os métodos get(posição) e size()
System.out.println("Percorrendo a lista usando for:");
for(int i = 0; i < cidades.size(); i++){
System.out.println("Posição " + i + " - " + cidades.get(i));
}
// 4) Com o método remove(posição),
// removeremos a cidade da posição 3 (Manaus);
cidades.remove(3);
// 5) Com o método add(posição, item),
// adicionaremos a cidade “Florianópolis” na posição zero;
cidades.add(0, "Florianópolis");
// 6) Vamos percorrer novamente a lista usando for-each;
System.out.println("==================");
System.out.println("Percorrendo a lista usando for-each:");
int i = 0;
for(String cidade : cidades){
System.out.println("Posição " + i + " - " + cidade);
i++;
}
// 7) Agora usaremos o indexOf(item) para retornar
// a posição da cidade “Recife” e, com o método
// set(posição, item) substituiremos "Recife"
// por “Salvador”;
int posicaoCidade = cidades.indexOf("Recife");
cidades.set(posicaoCidade, "Salvador");
// 8) Agora vamos percorrer a lista novamente,
// mas usando Iterator.
System.out.println("==================");
System.out.println("Percorrendo a lista usando Iterator:");
i = 0;
Iterator<String> iterator = cidades.iterator();
// o método hasNext() verifica se existe
// um próximo elemento para ser iterado
while (iterator.hasNext()){
// o método next() retorna o próximo elemento
System.out.println("Posição " + i + " - " + iterator.next());
i++;
}
}
}
A saída após executar a aplicação será:
Percorrendo a lista usando for:
Posição 0 - São Paulo
Posição 1 - Rio de Janeiro
Posição 2 - Recife
Posição 3 - Manaus
Posição 4 - Curitiba
==================
Percorrendo a lista usando for-each:
Posição 0 - Florianópolis
Posição 1 - São Paulo
Posição 2 - Rio de Janeiro
Posição 3 - Recife
Posição 4 - Curitiba
==================
Percorrendo a lista usando Iterator:
Posição 0 - Florianópolis
Posição 1 - São Paulo
Posição 2 - Rio de Janeiro
Posição 3 - Salvador
Posição 4 - Curitiba
Vantagens e Desvantagens do ArrayList
O uso do ArayList é mais indicado quando queremos apenas adicionar elementos em uma lista para posteriormente fazer a iteração. Adicionar elementos ao final de uma lista é bastante simples (isso caso a capacidade de armazenamento do array não tenha sido ultrapassado). O acesso a qualquer elemento do array pelo seu índice também é feito de forma bastante eficiente, ou seja, quando usamos o método get(posição), o tempo para acessar um elemento que esteja no início, ou no meio, ou no fim é praticamente o mesmo, independente do tamanho do vetor.
No entanto, o ArrayList na verdade usa o array padrão internamente, ou seja, quando a capacidade do array acaba, ele precisa criar um novo array com capacidade maior e copiar os elementos do antigo para o novo.
Quando usamos, por exemplo, o método add(posição, item) para adicionar um elemento no início ou no meio do vetor, primeiramente será necessário deslocar cada elemento uma posição para a direita, fazendo com que a posição desejada seja liberada, e só assim adicionar o novo item nesta posição. Caso o array seja muito grande, isso pode consumir muita memória.
Remover elementos no meio ou no início de um array também pode ser muito crítico, pois não é permitido existir “buracos” no vetor, sendo necessário deslocar todos os elementos para a esquerda.
Considerações Finais
Neste artigo foram abordadas algumas características do ArrayList. Vimos que esta classe implementa a interface List e faz parte do pacote java.util. Também conhecemos alguns dos seus métodos mais utilizados e entendemos um pouco do seu funcionamento, bem como suas vantagens e desvantagens.
Dependendo do contexto, talvez outras implementações sejam mais apropriadas, como LinkedList (que também implementa a interface List), ou HashSet (que implementa a interface Set). Mas isso é assunto para um próximo artigo.
Top comments (0)