Coleções

Neste módulo veremos:

Introdução

Já vimos em Java que podemos armazenar um conjunto de valores escalares ou objetos utilizando arranjos, ou seja, os vetores. Estas estruturas podem ser criadas dinâmicamente com o auxílio do operador new responsável por buscar mais recursos de memória junto ao sistema. Vimos também que poderíamos criar estruturas de dados mais complexas com disciplinas de acesso através da implementação de tipos abstrados de dados como listas, pilhas e filas.

Com a proposta desta estrutura de coleções proporciada pela linguagem Java o programador fica livre de criar novas estruturas de dados e simplesmente utiliza as estruturas já definidas em API específicas. Não há preocupação em saber como foi feita a programação, o programador, conhecendo os métodos, seus atributos e a sua documentação, apenas utiliza estas coleções. Esta é uma das grandes vantagens da abordagem de Orientação a Objetos, além, é claro, da padronização destas ferramentas de software.

Na versão atual de Java, uma coleção é um objeto que pode agrupar outros objetos. Uma coleção tem por objetivo facilitar a inserção, busca e recuperação destes objetos agrupados sistematicamente.

Para ser mais completo, o que temos por baixo de uma coleção de objetos é uma collection framework, ou seja, um arcabouço lógico para este tipo abstrato de dados, que se compõe de:

Os benefícios da utilização de coleções são os já aclamados: redução do esforço de programação, redução dos custos de implememtação, aumento da eficiência da geração de códigos, interoperabilidade de codificação, redução do esforço de aprendizagem, entre outros.

Os diferentes tipos

O núcleo da interface de coleção diferencia estes tipos distintos de agrupamentos de objetos, cada um com sua interface específica:

Todas as classes e interfaces que formam este arcabouço lógico, esta estrutura de coleções, está no pacote java.util. Vejamos partes deste pacote a seguir.

A interface Collection

public interface Collection extends Iterable {
    // Basic operations
    int size();
    boolean isEmpty();
    boolean contains(Object element);
    boolean add(E element);         //optional
    boolean remove(Object element); //optional
    Iterator iterator();

    // Bulk operations
    boolean containsAll(Collection c);
    boolean addAll(Collection c);           //optional
    boolean removeAll(Collection c);        //optional
    boolean retainAll(Collection c);        //optional
    void clear();                           //optional

    // Array operations
    Object[] toArray();
    T[] toArray(T[] a);
}

Dentre as várias classes do pacote java.util destacamos os seguintes

A classe Arrays

Esta classe fornece um conjunto enorme de métodos para a manipulação de arranjos, vetores, tais como:

Estes métodos inclusive incluem métodos de ordenamento, veja sort(), e métodos de busca. Esta é uma classe muito extensa no sentido de ter vários métodos mas outras classes podem ter um apelo mais imediato.

Collection é na realidade uma Superinterface da linguagem Java, uma interface da qual várias interfaces são derivadas. Por exemplo, uma destas interfaces é List da qual várias classes concretas são originadas, classes específicas como AbstractList, ArrayList, AttributeList, entre outras. Vejamos um exemplo a seguir.

A interface List e exemplo de classe concreta

Esta interface é uma Collection ordenada que pode conter elementos duplicados. Quase como os arranjos, as listas têm o elemento inicial no índice zero e, além dos métodos herdados da interface Collection esta interface fornece métodos específicos para manipular elementos usando os índices.

Ao usar Collection devemos prestar atenção para não instanciarmos interfaces e sim classes concretas.

A interface List é implementada, entre outras, pelas classes concretas ArrayList, LinkedList e Vector. Objetos da classe ArrayList são geralmente mais rápidos que objetos instanciados de Vector pois não se fartam das vantagens e seguros da implementação sobre threads.

ArrayList oferece acesso constante a todas as posições do objeto e para usá-la o usuário não precisa alocar cada nó que precisa para cada elemento da List, como seria esperado para uma interface deste tipo.

Se o programador sentir que o seu programa acessa constantemente o primeiro e o último elemento da lista ele poderá usar a classe LinkedList que também é uma classe concreta que implementa a interface List.

Veja um exemplo de como usar a classe ArrayList no código a seguir:

/* TestArrayList.java
 * @author EESR
 */

import java.util.*;

public class TestArrayList {

    public static void main(String args[]) {
        ArrayList<String> lista;
	lista = new ArrayList<String>();
	System.out.println ("tamanho: "+lista.size());

	lista.add("Primeiro");
	lista.add("Segundo");
	lista.add("Terceiro");
	System.out.println ("tamanho: "+lista.size());

	String ret = lista.get(2);
	System.out.println ("elem[3]: "+ret);
	lista.add(2,"novo");
	System.out.println (lista);
    }
}

Veja o resultado da execução:

amanho: 0
tamanho: 3
elem[3]: Terceiro
[Primeiro, Segundo, novo, Terceiro]

Genéricos

Neste exemplo temos uma novidade na linguagem Java desde Java 1.5 que é o uso de Generics, uma facilidade acrescentada a linguagem para dar maior garantias ao compilador de qual tipo de objeto a Collection está manipulando.

Vejamos as linhas abaixo:

    public static void main(String args[]) {
        ArrayList<String> lista;
	lista = new ArrayList<String>();

Veja que na declaração de lista pela imposição da declaração da classe ArrayList existe a necessidade de se declarar qual o tipo de objeto ocupará esta lista.

Do mesmo modo, na instanciação da classe, existe a necessidade de se declarar para quais obejtos ArrayList será usado.

Veja mais sobre genéricos clicando aqui.

Outro exemplo

Outra possibilidade está no uso da classe ArrayList, semelhante a classe Vector. Vejamos um exemplo:

import java.util.*;

public class UsoArrayList {
  private String nomes[] = {"fulano", "cicrano", "beltrano"};
  private ArrayList<String> lista;
  
  public UsoArrayList()
  {
    lista = new ArrayList<String>();
    for (int i=0; i<nomes.length; i++)
      lista.add(nomes[i]);
    lista.add("meu_nome");
    lista.add("seu_nome");
  }
  
  public void imprime()
  {
      Iterator it;

      it = lista.iterator();
      while(it.hasNext())
	  System.out.println(it.next());
  }
  
  public static void main(String args[])
  {
      UsoArrayList uso;
      uso = new UsoArrayList();
      uso.imprime();
  }
}
//UsoArrayList

Veja que a interface Collection fornece um método que devolve um Iterator, objeto responsável por buscar novos elementos nas coleções. O Iterator é na verdade uma interface.

Algoritmos

A estrutura de coleções fornece diversos algoritmos implementados que facilitam a programação. Estes algoritmos são implementados como métodos static. Os seguintes algoritmos operam sobre listas:

Veja o programa abaixo:

import java.util.*;

public class Algos {
  private String nomes[] = {"ala", "hospital", "enfermaria", "consultorio"};
  private ArrayList<String> lista;
  
  public Algos()
  {
      List<String> l = Arrays.asList(nomes);
      lista = new ArrayList<String> (l);

  }
  
  public void imprime()
  {
      int resultado;

      System.out.println("Originais: "+lista);

      Collections.sort(lista, Collections.reverseOrder());
      System.out.println("Inversamente ordenados: "+lista);

      Collections.shuffle(lista);
      System.out.println("Embaralhados: "+lista);

      Collections.sort(lista);
      System.out.println("Ordenados: "+lista);

      System.out.println("Busca por: "+nomes[1]);
      resultado = Collections.binarySearch(lista, nomes[1]);
      System.out.println(resultado >=0 ? "achou em "+resultado:
                                         "nao achou "+ resultado);
  }
  
  public static void main(String args[])
  {
    new Algos().imprime();
  }
}
//Algos

E o resultado deste programa seria:

Originais: [ala, hospital, enfermaria, consultorio]
Inversamente ordenados: [hospital, enfermaria, consultorio, ala]
Embaralhados: [enfermaria, hospital, consultorio, ala]
Ordenados: [ala, consultorio, enfermaria, hospital]
Busca por: hospital
achou em 3

Vimos aqui um exemplo útil e interessante da interfaces e de coleções. Existem outras classes abstratas que implementam Collection e que são muito úteis, tais como as tabelas hash e os conjuntos.

Leia mais nesta página.

Última modificação feita em: 18 de novembro de 2008
Evandro Eduardo Seron Ruiz, PhD (evandro at usp ponto br)