coleções em ordem

Upload: jhenrique35

Post on 10-Jul-2015

337 views

Category:

Documents


0 download

TRANSCRIPT

Colees em OrdemGerenciando e ordenando dados na camada de objetos Desenvolva uma aplicao web fazendo uso dos recursos de ordenao de objetos oferecidos pelas classes e interfaces da API de colees. Neste artigo, vamos abordar a API de colees Java, uma das mais teis e importantes do Java SE, explorando principalmente seus recursos para ordenao. Sero apresentados alguns tipos de colees fundamentais, bem como as classes utilitrias Arrays, Collections, Comparable e Comparator. Para exemplificar, criaremos uma aplicao web que exibe, de forma ordenada, uma listagem de clientes obtidos de uma base de dados. Clicando sobre uma das colunas da listagem, o usurio pode ordenar os clientes por vrios campos, sem a necessidade de executar novas consultas no banco de dados. Introduo ao uso de colees Em termos gerais, uma coleo pode ser entendida como um grupo de objetos com caractersticas em comum. A forma mais bsica de se trabalhar com grupos de objetos em Java por meio de arrays. Mas a manipulao de arrays com esse objetivo no uma tarefa simples especialmente nas operaes de insero, remoo e ordenao de objetos. Para a manipulao de grupos de objetos, portanto, os arrays no so prticos o suficiente. Isso motivou os criadores de Java a definir, desde o Java 1.0, colees dinmicas como Vector e Hashtable. E no Java 2, veio a definio de uma arquitetura unificada pra representar e manipular colees de objetos em Java o Java Collections Framework. Formada por interfaces, classes abstratas e implementaes focadas em vrios cenrios de uso, o framework de colees traz muitas facilidades importantes. Com ele, deixa de ser necessrio implementar mtodos de insero, remoo, ordenao e busca, por exemplo. Esses recursos j so oferecidos, com implementaes eficientes e bem testadas. Basicamente, o framework de colees composto por: Interfaces de colees, que representam os diferentes tipos de colees (Collection, Set, List, Queue, Map etc.); Implementaes das interfaces, que podem ser utilizadas pelos programadores para criar instncias das colees prontas para uso (HashSet, ArrayList, PriorityQueue etc.); Implementaes legadas, que so as classes que j existiam antes da criao do framework (Vector e Hashtable); Classes abstratas, implementaes parciais das interfaces para facilitar implementaes customizadas (AbstractList, AbstractSet, etc.); Classes utilitrias, contendo mtodos teis para manipulao de colees, tais como mtodos de ordenao e busca (ex.: Collections). As interfaces Map e Collection formam a base do framework. Collection permite a manipulao padronizada de colees de tipos variados (List, Set ou Queue). Tambm define os mtodos minimamente necessrios para todas as colees, tais como add(Object o), remove(Object o), contains(Object o), size(), entre outros. A Figura 1 apresenta um diagrama com as principais colees e classes utilitrias que fazem parte do framework. Os itens desse diagrama so descritos na Tabela 1 (interfaces) e na Tabela 2 (classes). Este artigo aborda principalmente

as interfaces descendentes de Collection. Todas as interfaces de colees, a partir do Java 5, so genricas. Isso significa que, quando se cria uma instncia de um subtipo de Collection ou de Map, possvel especificar o tipo de objeto que a coleo pode armazenar. Assim, se pode verificar se os objetos inseridos na coleo so do tipo correto em tempo de compilao. Para nos concentrar no uso e ordenao das colees, no detalhamos o recurso de tipos genricos, mas o usaremos ao definir nossas colees. Uma das vantagens oferecidas pelo framework a capacidade de iterar sobre os elementos de uma coleo (percorrer os elementos um aps o outro). A ordem em que essa iterao acontece determina se a coleo seqencial ou no-seqencial, e classificada ou no-classificada. importante conhecer essa categorizao, pois ela pode auxiliar na escolha do tipo de coleo que melhor se aplica a cada cenrio de uso.

Figura 1. Subconjunto de interfaces/classes do framework de colees

Interface java.util.Collection java.util.List java.util.Set

Descrio Define mtodos que permitem manipular qualquer uma das colees Set, List ou Queue. Coleo seqencial baseada em ndices. Pode conter elementos duplicados e nulos. No classificada. No seqencial nem classificada. No permite a incluso de objetos duplicados e aceita apenas um objeto nulo. Coleo classificada em funo da ordem de processamento dos objetos: a ordem mais comum a FIFO (First In, First Out), mas outras ordenaes tambm so possveis. Mapa de pares chave/valor. No permite chaves com valores duplicados e aceita apenas um chave nula. No seqencial, nem classificada. Verso classificada das colees Set. Faz uso das interfaces Comparable e Comparator. Verso classificada das colees Map. Tambm faz uso das interfaces Comparable e Comparator. Usadas para ordenar colees.

java.util.Queue

java.util.Map

java.util.SortedSet java.util.SortedMap java.lang.Comparable e java.util.Comparator

Tabela 1. Algumas interfaces de colees

Classe java.util.ArrayList

Descrio Implementao de List, usando arrays como base. Tem rpida iterao e a ordem previsvel (seqencial). Similar a ArrayList, mas os mtodos de acesso aos objetos so thread-safe (ou seja, podem ser usados em aplicaes multithreaded sem riscos de problemas de concorrncia mas com perda de performance). Lista duplamente ligada que implementa as interfaces List e Queue. Especialmente rpida para inseres e remoes. Coleo Set que utiliza cdigo hash para determinar a igualdade dos objetos e para recuper-los. Eficincia depende da implementao do mtodo hashCode() dos objetos. Verso seqencial de HashSet que mantm ligao dupla entre os objetos armazenados. A iterao sobre a coleo acontece de acordo com a ordem de insero dos objetos. Coleo Set classificada. A iterao sobre a coleo acontece de acordo com a ordem natural dos objetos ou com base em comparadores. Implementao da interface Queue. Pode fazer uso das interfaces Comparable e Comparator para ordenar os elementos de acordo com sua prioridade. Coleo Map classificada. Utiliza cdigo hash para determinar a igualdade dos objetos chave e para recuper-los. Depende da boa implementao do mtodo hashCode() dos objetos usados como chave nos pares chave/valor. Similar a HashMap, mas os mtodos de acesso aos objetos so thread-safe. Verso seqencial de HashMap que mantm ligao dupla entre as chaves. A iterao sobre essa coleo acontece com base na ordem de insero das chaves. Coleo Map classificada. A iterao sobre essa coleo acontece de acordo com a ordem natural das chaves ou com base em comparadores das chaves. Classe utilitria para a manipulao de colees. Possui mtodos para ordenao, busca, inverso de

java.util.Vector

java.util.LinkedList

java.util.HashSet

java.util.LinkedHashSet

java.util.TreeSet

java.util.PriorityQueue

java.util.HashMap

java.util.Hashtable java.util.LinkedHashMap

java.util.TreeMap

java.util.Collections

ordem etc. java.util.Arrays Tabela 2. Algumas classes de colees Colees seqenciais Uma coleo dita seqencial quando a iterao sobre seus elementos tem resultado previsvel. Ou seja, como os elementos so mantidos de forma organizada, geralmente em funo de ndices ou da ordem de insero, podemos presumir que a ordem do resultado ser a mesma para vrias iteraes seguidas (sem modificar os objetos da coleo). O exemplo mais conhecido desse tipo de coleo a interface List e sua implementao ArrayList. J numa coleo no-seqencial, a ordem dos resultados pode ser diferente a cada iterao, mesmo que a coleo no tenha sido modificada. Isso acontece porque, apesar de existir uma organizao interna dos elementos na coleo (em geral com base no cdigo de hash dos objetos), essa organizao no influencia na ordem da iterao, da a variao nos resultados. O exemplo mais comum desse tipo de coleo a interface Set e sua implementao HashSet. Colees classificadas Uma coleo classificada (ou ordenada) aquela que mantm os elementos organizados de acordo com regras de ordenao especficas. Essas regras no esto diretamente relacionadas com ndices nem com ordem de insero, mas sim com as propriedades dos objetos armazenados. O resultado da iterao sobre uma coleo classificada, alm de ser previsvel, tambm ordenado em funo dos seus objetos, sendo que a regra de ordenao fornecida pelas prprias classes desses objetos (utilizando as interfaces Comparable e Comparator detalhadas a seguir). Por exemplo, se iterarmos sobre uma coleo classificada que armazena objetos String, teremos, como resultado, os objetos na ordem alfabtica. TreeSet e TreeMap so exemplos de colees classificadas; ArrayList uma coleo no-classificada. Toda coleo classificada tambm uma coleo seqencial, pois o resultado da iterao sobre seus elementos previsvel. Interfaces Comparable e Comparator Para ordenar uma coleo de acordo com propriedades dos objetos nela armazenados, precisamos utilizar pelo menos uma das duas interfaces de comparao do Java SE: java.lang.Comparable ou java.util.Comparator. java.lang.Comparable A interface Comparable utilizada para estabelecer a ordem natural dos objetos. Ela define apenas um mtodo int compareTo(Object o). Esse mtodo implementado para fornecer a regra de comparao do prprio objeto com um outro, e determina como feita a ordenao dos objetos na coleo. Vrias classes, como Integer, Double e String, j implementam a interface Comparable. O mtodo compareTo() retorna zero, se os dois objetos so iguais; um inteiro Classe utilitria, semelhante classe Collections, para facilitar a manipulao de arrays.

negativo, se o objeto est antes do objeto passado como argumento; e um inteiro positivo, se o objeto est depois do que foi passado como argumento. O trecho de cdigo a seguir ilustra o uso de Comparable para definir a ordem natural de uma classe Cliente. Nesta classe, a regra de ordenao implementada no mtodo compareTo() define a ordem natural com base no nome do cliente, um String. Como a classe String possui ordem natural alfabtica, se iterarmos sobre uma coleo classificada de objetos Cliente, teremos os clientes ordenados pelo nome. package globalcode.model; public class Cliente implements Comparable private String nome; public Cliente(String nome, String, Telefone, String email, int id) { } // construtor public int compareTo(Cliente c) { // String j implementa Comparable para ordem alfabtica return this.nome.compareTo(c.getNome()); } } Uma recomendao importante que a implementao do mtodo compareTo() deve ser coerente com a do mtodo equals(). Por exemplo, na classe Cliente, o mtodo equals() deve retornar verdadeiro quando os nomes dos clientes forem iguais. As colees Java usam esses mtodos de forma diferente. Por exemplo, a coleo HashMap usa o mtodo equals() para determinar se dois objetos so iguais, enquanto a coleo TreeSet usa o compareTo(). Se esses mtodos no so coerentes, cada tipo de coleo pode apresentar um comportamento diferente. Situao semelhante pode acontecer com os mtodos equals() e hashcode(). java.util.Comparator Alm da ordem natural, tambm possvel definir regras diferentes de ordenao baseando-se na comparao entre dois objetos. Para isso, utilizamos a interface Comparator do pacote java.util. A regra de ordenao definida no mtodo int compare (Object o1, Object o2), como ilustrado no trecho de cdigo a seguir. Esse mtodo retorna zero se o primeiro objeto passado igual ao segundo; um inteiro negativo, se o primeiro objeto est antes do segundo; e um inteiro positivo, se o primeiro objeto est depois do segundo. package globalcode.comparator;

iimport java.util.Comparator; public class ComparatorClienteEmail implements Comparator { public int compare(Cliente c1, Cliente c2) { return c1.getEmail().compareTo(c2.getEmail()); } } Note que a interface Comparator implementada por uma classe que compara dois objetos Cliente, considerando o e-mail como critrio de ordenao. Se iterarmos sobre uma coleo classificada de clientes utilizando esse comparador, teremos os clientes ordenados por seus e-mails. No h limites para o nmero de comparadores que podemos criar para comparar uma mesma classe; por exemplo, para a classe Cliente ainda podemos definir um comparador para a propriedade id e um para a propriedade nome. Quando usar Comparable e quando usar Comparator? Quando precisamos fazer a ordenao utilizando apenas o critrio de ordem natural, podemos utilizar a interface Comparable. Quando existe a necessidade de ordenar a coleo por mais de um critrio, como por exemplo, ordenar os clientes por nome, por e-mail, ou por empresa na qual trabalham, precisamos utilizar a interface Comparator para criar os vrios comparadores. Tambm podemos combinar o uso das duas interfaces para permitir a ordenao natural ou a baseada em comparadores. SortedSet e SortedMap Uma vez definidas as regras de ordenao, podemos comear a explorar o uso das colees classificadas. Elas so definidas pelas interfaces SortedSet e SortedMap, cujas implementaes principais so TreeSet e TreeMap. Essas colees nos permitem utilizar tanto a ordem natural dos objetos (atravs da implementao de Comparable) quanto comparadores (atravs da implementao de Comparator) para ordenar os objetos no momento da insero na coleo. A coleo TreeSet mantm em ordem todos os seus elementos, diferentemente da coleo TreeMap, que mantm ordenadas apenas as chaves dos pares chave/valor. Quando uma dessas colees instanciada sem nenhum comparador especfico (objeto Comparator), o mtodo compareTo() do objeto utilizado para estabelecer a ordem dos elementos. Se a coleo for instanciada utilizando um comparador, a regra para ordenao a que foi estabelecida no mtodo compare() do comparador utilizado. Objetos de classes que no implementam Comparable no podem ser inseridos numa coleo TreeSet instanciada sem um comparador especfico. O mesmo vale para as chaves das colees TreeMap. Isso acontece porque numa coleo classificada que no tenha um comparador, a mquina virtual tenta usar o mtodo compareTo() para ordenar os objetos, lanando uma exceo quando no o encontra.

Para exemplificar os dois tipos de ordenao, vamos utilizar uma coleo TreeSet classificada por ordem natural e tambm com base em um comparador: // Ordem natural TreeSet comOrdemNatural = new TreeSet (); comOrdemNatural.add(new Cliente( "Yara", "11558899", "[email protected]",21)); comOrdemNatural.add(new Cliente( "Elaine", "22334455", "[email protected]",40)); for (Cliente cli : comOrdemNatural) System.out.println(cli.getNome()); System.out.println (----); // Usando comparador para cdigo ComparatorClienteCodigo c = new ComparatorClienteCodigo(); TreeSet comComparador = new TreeSet(c); comComparador.add(new Cliente( "Yara", "11558899", "[email protected]", 21)); comComparador.add(new Cliente( "Elaine", "22334455", "[email protected]",40)); for (Cliente cli : comComparador) System.out.println(cli.getId() + - + cli.getNome()); O resultado da execuo desse trecho de cdigo o seguinte: 40 - Elaine 21 - Yara ---21 - Yara 40 - Elaine. Note que no primeiro caso os clientes foram impressos na ordem alfabtica, que a ordem natural da classe Cliente. No segundo, como utilizamos um comparador baseado no cdigo do cliente, a cliente Yara foi impressa antes de Elaine que tinha o cdigo (id) menor. (A classe Integer, utilizada para o cdigo do cliente, possui ordem natural baseada na ordem numrica.) Vale lembrar que colees Set no aceitam objetos iguais e que colees Map no permitem chaves iguais. Portanto, se tentarmos inserir dois objetos Cliente que tenham o mesmo nome em uma coleo TreeSet, um deles ser rejeitado, pois o mtodo equals() define igualdade para dois clientes de mesmo nome. Na coleo

TreeMap, se a chave for igual a alguma outra chave j inserida, o objeto armazenado como valor da chave ser substitudo com o objeto valor que estiver sendo inserido para a chave existente. Classes Arrays e Collections Apesar do framework de colees fornecer colees naturalmente classificadas, como TreeSet e TreeMap, tambm podemos ordenar colees no-classificadas como as implementaes de List (e tambm arrays). Para isso, temos duas classes utilitrias: Arrays e Collections. A classe Arrays oferece mtodos estticos para manipular arrays, e Collections traz mtodos semelhantes para trabalhar com colees. Alguns exemplos de mtodos para busca e ordenao de elementos oferecidos por essas classes so apresentados nas Tabelas 3 e 4. O trecho de cdigo a seguir ilustra a utilizao das classes Arrays e Collections para a ordenao de colees List e arrays usando o comparador ComparatorClienteCodigo ilustrado anteriormente: Comparator c = new ComparatorClienteCodigo(); List clientes = ClienteDAO.getInstance().getAll(); Collections.sort(clientes, c); Object[] arrayClientes = clientes.toArray(); Arrays.sort(arrayClientes, c); As classes Arrays e Collections tambm oferecem outros mtodos utilitrios para trabalhar com arrays e colees (incluindo Set e Map). Para mais informaes a respeito dessas classes, consulte a API do Java SE. Mtodo void (Object[] a) void (Object[] a, Comparator c) Descrio Ordena um array usando a ordem natural dos objetos no array ou um comparador. Permite buscar objetos num array que j foi classificado. necessrio usar a assinatura que corresponde ao tipo de ordenao realizada (ordem natural ou com comparador). Retorna o ndice (>=0) do objeto buscado ou um valor negativo que, se convertido usando a frmula (-(valor retornado) -1) indica a posio de insero do objeto na lista de forma que continue classificada. Converte um array em uma coleo List.

int (Object[] a, Object chave) int (Object[] a, Object chave, Comparator c)

List (Object[] a)

Tabela 3. Mtodos utilitrios da classe Arrays Mtodo void (List list) Descrio Ordena uma coleo List usando ordem

void (List list, Comparator c)

natural ou um comparador. Permite buscar objetos numa coleo List da mesma forma que para arrays. Tambm necessrio usar a assinatura equivalente ao tipo de ordenao realizada (ordem natural ou com comparador). Os valores de retorno so os mesmos da classe Arrays. Inverte a ordem dos elementos na coleo.

int (List list, Object chave) int (List list, Object chave, Comparator c)

void reverse(List list)

Tabela 4. Mtodos utilitrios da classe Collections A aplicao de exemplo Para ilustrar a utilizao de colees, especialmente os recursos de ordenao, criamos uma aplicao web de exemplo que permite ordenar uma coleo de clientes usando diferentes critrios (os dados so recuperados de um banco de dados). Essa aplicao permite ao usurio escolher o tipo de coleo que pretende visualizar (SortedSet, List ou array). Alm disso, a partir da primeira listagem de clientes, o usurio pode escolher em que ordem prefere visualizar os dados por cdigo, nome, e-mail ou telefone. A aplicao de exemplo foi desenvolvida utilizando servlets e pginas JSP para a implementao da lgica de negcio e de apresentao, e o pattern DAO (Data Access Object) para a obteno dos dados dos clientes. Arquitetura O diagrama de seqncia da Figura 2 ilustra a interao entre os objetos da aplicao ao fazer uma ordenao de uma coleo List. Na primeira interao com a aplicao, que acontece via uma pgina JSP principal, o usurio escolhe o tipo de coleo que pretende visualizar sem informar a ordenao desejada. Neste caso, a aplicao usa a ordem natural (nome do cliente). Nas demais interaes para o tipo de coleo escolhida, o usurio pode selecionar a ordem desejada clicando nas colunas de dados. Por exemplo, se o usurio clicar sobre a coluna email, a listagem de clientes ser classificada por email. Foram implementados trs servlets que so responsveis por realizar a ordenao de cada tipo de coleo. Todos retornam suas respostas para uma mesma pgina JSP de apresentao de dados. Isso possvel porque a pgina que lista os clientes usa tags JSTL que permitem manipular colees e arrays sem ter que definir seu tipo. Se no utilizssemos esse recurso, teramos que criar pelo menos duas pginas JSP diferentes para tratar as colees: uma para tratar o array e outra para tratar as colees List e SortedSet (subtipos de Collection).

Figura 2. Interao entre elementos da aplicao de exemplo Camada do modelo: Cliente Os clientes so representados por objetos da classe globalcode.model.Cliente. Essa classe tem como atributos um cdigo, que corresponde chave primria no banco de dados, um nome, um e-mail e um telefone, correspondendo aos dados do cliente que so armazenados. A classe Cliente implementa a interface Comparable, com ordem natural definida em funo dos nomes dos clientes. Alm disso, os mtodos equals(), hashCode() e compareTo() so coerentes entre si, conforme pode ser visto na Listagem 1. Listagem 1. Cliente.java : classe de modelo que armazena os dados do cliente

package globalcode.model; import java.io.Serializable; public class Cliente implements Comparable { private Integer id; private String nome; private String telefone; private String email; public Cliente() {} public Cliente(String nome, String telefone, String email, int id) { this.nome = nome; this.telefone = telefone; this.email = email; this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } // Dois clientes so considerados a mesma pessoa quando possuem nomes iguais. public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; boolean result = false; if (o instanceof Cliente) { Cliente outro = (Cliente) o; result = this.getNome() != null && this.getNome().equals(outro.getNome()); }

return result; } // Coerente com o mtodo equals() public int hashCode() { int result = getNome() != null ? getNome().hashCode() : 41; return result; } //Mtodo da interface Comparable usando o recurso de generics. // Coerente com o mtodo equals() public int compareTo(Cliente c) { // String j implementa Comparable para ordem alfabtica return this.nome.compareTo(c.getNome()); } }

Camada de persistncia: ClientesDAO O acesso aos dados persistidos para os clientes realizado por meio da classe globalcode.dao.ClienteDAO, que oferece mtodos para obter e fechar a conexo com o banco de dados e para listar todos os clientes que estiverem armazenados, sem determinar a ordem na consulta SQL. O cdigo da classe ClienteDAO pode ser visto na Listagem 2. Listagem 2. ClienteDAO.java : classe DAO para recuperar clientes do banco de dados package globalcode.dao; import java.sql.*; import java.util.*; import globalcode.model.Cliente; public class ClienteDAO { private static ClienteDAO instance = new ClienteDAO(); protected ClienteDAO() {} public static ClienteDAO getInstance() { return instance; } /** Lista todos os clientes do banco de dados */

public List getAll() throws Exception { Connection conn = null; Statement st = null; ResultSet rs = null; List clientes = new ArrayList(); try { conn = getConnection(); st = conn.createStatement(); // Nenhuma instruo de ordenao utilizada rs = st.executeQuery("select * from clientes"); while (rs.next()) { Cliente cliente = new Cliente( rs.getString("nome"), rs.getString("telefone"), rs.getString("email"), new Integer(rs.getInt("id"))); clientes.add(cliente); } return clientes; }catch (Exception e){ e.printStackTrace(); throw e; // Tratamento da exc. ao fazer uma consulta. }finally { closeResources(conn, st, rs); } } /** Abre conexo com o banco de dados */ public Connection getConnection() throws Exception { String databaseURL = "jdbc:mysql://localhost:3306/ordenacao"; String databaseUser = "root"; String databasePassword = ""; Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(databaseURL, databaseUser,

databasePassword); } catch (Exception e) { e.printStackTrace(); throw e; } return conn; } /** Fecha conexo com o banco de dados */ public void closeResources(Connection conn, Statement st, ResultSet rs) { try { if (rs != null) rs.close(); if (st != null) st.close(); if (conn != null) conn.close(); } catch (SQLException e) {...} } } Camada de apresentao: JSP H duas pginas JSP na aplicao: uma principal (index.jsp Listagem 3), apenas para selecionar qual tipo de coleo o usurio quer ordenar e outra para apresentao dos dados dos clientes (lista.jsp Listagem 4). A pgina lista.jsp obtm a coleo de clientes, retornada pelo servlet que processou a requisio, e imprime os dados de cada cliente utilizando tags (para iterao em colees e arrays). usada tambm a tag da biblioteca core do JSTL. A pgina tambm imprime o tipo de coleo visualizada e o critrio de ordenao usado. Quando nenhuma ordenao especfica selecionada, a coleo ordenada por nome (ordem natural). Listagem 3. index.jsp : pgina JSP que permite escolher o tipo de lista que se pretende visualizar < contentType="text/html"%> < pageEncoding="UTF-8"%>

Ordenando colees... Esta aplicao mostra como usar o recurso de ordenao de colees.
Ordenando uma coleo List
Ordenando um array de objetos
Utilizando a coleo classificada SortedSet Listagem 4. lista.jsp : pgina JSP que exibe os dados dos clientes ordenados < contentType="text/html"%> < pageEncoding="UTF-8"%> Ordenando colees de objetos... Exemplo utilizando Critrio de ordenao utilizado:
Cdigo Nome Email Telefone Para visualizar o efeito da calssificao dos clientes, clique sobre uma das colunas de informao: Cdigo, Nome, Email ou Telefone. Voltar pgina principal

Comparadores Como a aplicao permite a ordenao dos clientes por vrios campos (e no s pela ordem natural), temos que definir comparadores para as demais formas de ordenao. As Listagens 5, 6 e 7 contm os cdigos dos trs comparadores criados para a aplicao de exemplo. Listagem 5. ComparatorClienteCodigo.java: implementa Comparator para ordenao de clientes por cdigo package globalcode.comparator; import globalcode.model.Cliente; import java.util.Comparator; public class ComparatorClienteCodigo implements Comparator { /** Este mtodo diz que dois objetos clientes so iguais quando o id de ambos so iguais. A comparao por id. **/ public int compare(Cliente c1, Cliente c2) { return c1.getId().compareTo(c2.getId()); } } Listagem 6. ComparatorClienteEmail.java : implementa Comparator para ordenao de clientes por e-mail //... public class ComparatorClienteEmail implements Comparator { public int compare(Cliente c1, Cliente c2) { return c1.getEmail().compareTo(c2.getEmail()); } } Listagem 7. ComparatorClienteTelefone.java : implementa Comparator para ordenao de clientes por telefone //... public class ComparatorClienteTelefone implements Comparator { public int compare(Cliente c1, Cliente c2) { return c1.getTelefone().compareTo(c2.getTelefone()); }

} Ordenando um array de objetos Para demonstrar a ordenao de arrays, criamos o servlet ListaClientesArray (Listagem 8). Esse servlet tenta obter a lista de clientes da sesso HTTP, e caso no consiga, obtm os dados do banco atravs da classe ClienteDAO e os armazena na sesso HTTP. Posteriormente, ele converte a lista de clientes em um array de objetos Cliente e, a partir da ordem escolhida pelo usurio, efetua a ordenao do array utilizando Arrays.sort(). Se o usurio escolher ordenar a coleo por nome, utilizada a ordem natural da classe Cliente (essa ordem tambm utilizada quando o usurio escolhe o tipo de coleo). Caso contrrio, a ordenao acontece com base em comparadores especficos (por e-mail, cdigo e telefone). Listagem 8. ListaClientesArray.java : servlet que ordena um array de clientes package globalcode.servlet; import globalcode.comparator.ComparatorClienteCodigo; import globalcode.comparator.ComparatorClienteEmail; import globalcode.comparator.ComparatorClienteTelefone; import globalcode.dao.ClienteDAO; import globalcode.model.Cliente; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; /** Esta classe demonstra a ordenao de um array de objetos utilizando a classe Arrays. */ public class ListaClientesArray extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List clientes; Object[] clientesArray; String criterioOrdenacao; Comparator c = null; try{ // Obtm a lista de clientes da sesso HTTP clientes = (List) request.getSession().getAttribute("lista_clientes"); if (clientes == null){

clientes = ClienteDAO.getInstance().getAll(); request.getSession().setAttribute("lista_clientes", clientes); } clientesArray = clientes.toArray(); // transforma a lista em Array criterioOrdenacao = request.getParameter("criterioOrdenacao"); if (criterioOrdenacao.equals("email")) c = new ComparatorClienteEmail(); // Comparador por email else if (criterioOrdenacao.equals("telefone")) c = new ComparatorClienteTelefone(); // Comparador por telefone else if (criterioOrdenacao.equals("codigo")) c = new ComparatorClienteCodigo(); // Comparador por cdigo do cliente if (c != null){ // ordena de acordo com o critrio escolhido Arrays.sort(clientesArray, c); }else{ // ordena por ordem natural da classe Cliente Arrays.sort(clientesArray); } // coloca objetos na request para serem utilizados na pgina request.setAttribute("clientes",clientesArray); request.setAttribute("ordenacao", criterioOrdenacao); request.setAttribute("tipoColecao", "Array"); getServletContext().getRequestDispatcher( "/lista.jsp").forward(request,response); }catch (Exception e) { //... Tratar exceo } } } O servlet ListaClientesArray redireciona a requisio para a pgina lista.jsp. Veja a listagem de clientes ordenada por cdigo na Figura 3.

Figura 3. Interface da aplicao mostrando a lista de clientes ordenada por cdigo numa coleo TreeSet. Ordenando uma coleo List A ordenao de uma coleo List demonstrada por meio do servlet ListaClientesList, que, depois de obter a lista de clientes da sesso HTTP (ou da classe ClienteDAO, se os dados ainda no tiverem sido armazenados na sesso) efetua a ordenao da coleo utilizando Collections.sort(), como visto na Listagem 9. A regra para a classificao (ordem natural ou com comparadores) definida da mesma forma que no servlet ListaClientesArray. Listagem 9. ListaClientesList.java : servlet que ordena uma coleo List de clientes package globalcode.servlet; //... imports /** Esta classe demonstra a ordenao de uma coleo List utilizando a Classe Collections. */ public class ListaClientesList extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

List clientes; String criterioOrdenacao; Comparator c = null; try{ // ... Recuperao da lista de clientes da sesso HTTP ou via ClienteDAO // ... Instanciao do comparador de acordo com o critrio escolhido if (c!=null){ // ordena de acordo com o critrio escolhido Collections.sort(clientes, c); }else{ // ordena por ordem natural da classe Cliente Collections.sort(clientes); } // coloca objetos na request para serem utilizados na pgina // c request.setAttribute("clientes",clientes); request.setAttribute("ordenacao", criterioOrdenacao); request.setAttribute("tipoColecao", "List"); getServletContext().getRequestDispatcher("/lista.jsp").forward(request,response); }catch (Exception e) { //... Tratar exceo } } } Utilizando a coleo classificada SortedSet Para exemplificar o uso de uma coleo j classificada, criamos o servlet ListaClientesTreeSet. Da mesma forma que os demais, esse servlet obtm a lista de clientes da sesso HTTP (ou da classe ClienteDAO) e copia todos os clientes da coleo List para uma instncia da coleo TreeSet. Ao contrrio das colees List e dos arrays, colees classificadas como TreeSet e TreeMap no precisam ser ordenadas via mtodo sort() da classe Collections. Isso porque elas j estabelecem a ordem no momento da insero dos objetos (ordem natural quando a coleo instanciada sem comparador ou baseada em comparadores quando a coleo instanciada utilizando um comparador especfico). O cdigo do servlet ListaClientesTreeSet pode ser visto na Listagem 10. Listagem 10. ListaClientesTreeSet.java : servlet que utiliza uma coleo ordenada para armazenar os clientes

package globalcode.servlet; // ... imports /** Esta classe demonstra a ordenao de uma coleo TreeSet. */ public class ListaClientesTreeSet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { SortedSet treeSet; List clientes; String criterioOrdenacao; Comparator c = null; try{ // ...Recuperao da lista de clientes da sesso http ou via ClienteDAO // ... Instanciao do comparador de acordo com o critrio escolhido if (c != null){ // define um TreeSet usando o critrio de ordenao escolhido treeSet = new TreeSet(c); }else{ // define um TreeSet usando ordem natural da classe cliente treeSet = new TreeSet(); } for (Cliente cliente: clientes){ treeSet.add(cliente); // Adiciona os clientes no TreeSet } // coloca objetos na request para serem utilizados na pgina request.setAttribute("clientes", treeSet); request.setAttribute("ordenacao", criterioOrdenacao); request.setAttribute("tipoColecao", "TreeSet"); getServletContext().getRequestDispatcher( "/lista.jsp").forward(request,response); } catch (Exception e) { //... Tratar exceo }

} } Instalando a aplicao Para executar a aplicao de exemplo sem mudanas, o leitor precisa ter instalado no seu computador o JDK 5.0 ou 6.0 e o NetBeans 5.0 ou superior (a aplicao de exemplo um projeto web desenvolvido nessa IDE). Tambm ser necessrio ter acesso a um servidor de banco de dados com uma base de dados de nome ordenacao (a aplicao est preparada para o MySQL). Se estiver utilizando um servidor de banco de dados diferente do MySQL, ser necessrio adicionar ao projeto o driver JDBC compatvel com seu banco. Clique com o boto direito sobre o projeto, escolha Properties>Libraries e adicione o JAR do driver JDBC. Depois de fazer o download do arquivo ZIP e descompact-lo, abra o NetBeans e selecione File>Open Project; escolha o diretrio da aplicao e escolha a opo Open Project Folder. Crie as tabelas da base de dados utilizando o script script_ordenacao.dump, tambm includo no ZIP, no mesmo nvel do diretrio do projeto. Tambm edite a classe dao.ClienteDAO para configurar os dados da sua conexo de banco de dados. Agora s ir ao menu Run e escolher a opo Run Main Project (ou pressionar F6) e fazer o teste da aplicao que ser aberta no browser padro. Concluses Neste artigo, apresentamos alguns conceitos importantes de colees, mostrando como podemos ordenar uma coleo de objetos sem a necessidade de usar instrues SQL diretamente no banco de dados. A vantagem dessa abordagem que podemos visualizar um conjunto de informaes ordenadas de diversas formas com apenas uma instruo de consulta no banco de dados. Se tivssemos que fazer a classificao no nvel de banco, a cada requisio teramos que efetuar uma consulta passando o critrio de ordenao desejado. Tambm vimos um exemplo que mostra, em um ambiente realista, como utilizar os recursos de ordenao em vrios tipos de colees e em arrays.