• Nenhum resultado encontrado

Listas: java.util.List

No documento caelum-java-objetos-fj11 (páginas 186-189)

Um primeiro recurso que a API de Collections traz são listas. Uma lista é uma coleção que permite elementos duplicados e mantém uma ordenação específica entre os elementos.

Em outras palavras, você tem a garantia de que, quando percorrer a lista, os elementos serão encontrados em uma ordem pré-determinada, definida na hora da inserção dos mesmos.

Ela resolve todos os problemas que levantamos em relação ao array (busca, remoção, tamanho “infinito”,...). Esse código já está pronto!

A API de Collections traz a interface java.util.List, que especifica o que uma classe deve ser capaz de fazer para ser uma lista. Há diversas implementações disponíveis, cada uma com uma forma diferente de representar uma lista.

A implementação mais utilizada da interface List é aArrayList, que trabalha com um array interno para gerar uma lista. Portanto, ela é mais rápida na pesquisa do que sua concorrente, a LinkedList, que é mais rápida na inserção e remoção de itens nas pontas.

ArrayList não é um array!

É comum confundirem umaArrayListcom um array, porém ela não é um array. O que ocorre é que, internamente, ela usa um array como estrutura para armazenar os dados, porém este atributo está propriamente encapsulado e você não tem como acessá-lo. Repare, também, que você não pode usar[]com umaArrayList, nem acessar atributolength. Não há relação!

Para criar umArrayList, basta chamar o construtor: ArrayList lista = new ArrayList();

É sempre possível abstrair a lista a partir da interfaceList: List lista = new ArrayList();

Para criar uma lista de nomes (String), podemos fazer:

List lista = new ArrayList(); lista.add("Guilherme"); lista.add("Paulo"); lista.add("Sérgio");

A interfaceListpossui dois métodosadd, um que recebe o objeto a ser inserido e o coloca no final da lista, e um segundo que permite adicionar o elemento em qualquer posição da mesma.

Note que, em momento algum, dizemos qual é o tamanho da lista; podemos acrescentar quantos elementos quisermos, que a lista cresce conforme for necessário.

Toda lista (na verdade, toda Collection) trabalha do modo mais genérico possível. Isto é, não há uma ArrayListespecífica paraStrings, outra para Números, outra para Datas etc. Todos os métodos trabalham comObject.

Assim, é possível criar, por exemplo, uma lista de Contas Correntes: ContaCorrente c1 = new ContaCorrente();

c1.deposita(100);

ContaCorrente c2 = new ContaCorrente(); c2.deposita(200);

ContaCorrente c3 = new ContaCorrente(); c3.deposita(300);

List contas = new ArrayList(); contas.add(c1);

contas.add(c3); contas.add(c2);

Para saber quantos elementos há na lista, podemos usar o métodosize(): System.out.println(contas.size());

Há, ainda, um métodoget(int)que recebe como argumento o índice do elemento que se quer recuperar. Através dele, podemos fazer umforpara iterar na lista de contas:

for(int i = 0; i < contas.size(); i++) {

contas.get(i); // código não muito útil.... }

Mas como fazer para imprimir o saldo dessas contas? Podemos acessar o getSaldo() diretamente após fazercontas.get(i)? Não podemos; lembre-se que toda lista trabalha sempre comObject. Assim, a referência devolvida pelo get(i)é do tipo Object, sendo necessário o cast paraContaCorrentese quisermos acessar o getSaldo():

for(int i = 0; i < contas.size(); i++) {

ContaCorrente cc = (ContaCorrente) contas.get(i); System.out.println(cc.getSaldo());

}

// note que a ordem dos elementos não é alterada

Há ainda outros métodos como remove() que recebe um objeto que se deseja remover da lista; e contains(), que recebe um objeto como argumento e devolve true ou false, indicando se o elemento está ou não na lista.

A interfaceListe algumas classes que a implementam podem ser vistas no diagramaUML a seguir:

Acesso aleatório e percorrendo listas com get

Algumas listas, como a ArrayList, têm acesso aleatório aos seus elementos: a busca por um elemento em uma determinada posição é feita de maneira imediata, sem que a lista inteira seja percorrida (que chamamos de acesso sequencial).

Neste caso, o acesso através do métodoget(int)e é muito rápido. Caso contrário, percorrer uma lista usando umforcomo esse que acabamos de ver, pode ser desastroso. Ao percorrermos uma lista, devemos usarsempre umIteratorouenhanced for, como veremos.

Uma lista é uma excelente alternativa a um array comum, já que temos todos os benefícios de arrays, sem a necessidade de tomar cuidado com remoções, falta de espaço etc.

A outra implementação muito usada (LinkedList), fornece métodos adicionais para obter e remover o pri- meiro e último elemento da lista.

Vale ressaltar a importância do uso da interface List: quando desenvolvemos, procuramos sempre nos referir a ela, e não as implementações específicas. Por exemplo, se temos um método que vai buscar uma série de contas no banco de dados, poderíamos fazer assim:

class ContaDAO {

public ArrayList<Conta> buscaTodasContas() {

ArrayList<Conta> contas = new ArrayList<Conta>(); // para cada conta do banco de dados, contas.add

return contas; }

}

Porém, pra que precisamos retornar a referência específica a umaArrayList? Para que ser tão específico? Dessa maneira, o dia que optarmos por devolver umaLinkedListem vez deArrayList, as pessoas que estão usando o métodobuscaTodasContaspoderão ter problemas, pois estavam fazendo referência a umaArrayList. O ideal é sempre trabalhar com a interface mais genérica possível:

class ContaDAO {

// modificacao apenas no retorno:

public List<Conta> buscaTodasContas() {

ArrayList<Conta> contas = new ArrayList<Conta>(); // para cada conta do banco de dados, contas.add

return contas; }

}

Assim como no retorno, é boa prática trabalhar com a interface em todos os lugares possíveis: métodos recebem List em vez de uma implementação em específico. Também declaramos atributos como List em vez de nos comprometer como uma ou outra implementação. Dessa forma obtemos umbaixo acoplamento: podemos trocar a implementação, já que estamos programando para a interface!

Vector

Outra implementação é a tradicional classeVector, presente desde o Java 1.0, que foi adaptada para uso com o framework de Collections, com a inclusão de novos métodos.

Ela deve ser tratada com cuidado pois lida de uma maneira diferente com processos correndo em paralelo e será mais lenta que umaArrayListquando não houver acesso simultâneo aos dados.

No documento caelum-java-objetos-fj11 (páginas 186-189)

Documentos relacionados