Implementaç Implementação de Gené Genéricos, Iteradores Isabel Harb Manssour Porto Alegre, Alegre, maio de 2006 Roteiro Implementaç Implementação de Gené Genéricos Coleções Conceito de Genérico Implementação Iteradores Conceito Utilização ForEach PS: Material adaptado das aulas do Prof. Bernardo Copstein Coleções Java disponibiliza classes e interfaces que facilitam o agrupamento e processamento de objetos em conjuntos Coleções (Java Collections Framework) Estruturas de dados + algoritmos para sua manipulação Java Collections framework Arquitetura unificada para representar e manipular coleções, de forma independente dos detalhes de sua representação 1 Coleções O programador simplesmente utiliza as estruturas de dados sem se preocupar com a maneira como são implementadas Vantagens Reutilização de código (implementação mais rápida) Desempenho superior Maior velocidade de execução Menos memória Coleções Coleções De forma simplificada, são objetos capazes de armazenar conjuntos de referências para outros objetos Correspondem a classes oferecidas na biblioteca padrão de Java Trabalham com polimorfismo São implementadas com genéricos Coleções Classes e interfaces que compreendem a estrutura de coleções estão no pacote java.util Java separa a representação da coleção em: Interfaces Definem métodos que podem ser usados para manipulação dos objetos nas coleções Implementações Classes que implementam as interfaces, mas, internamente, manipulam os dados de forma diferente 2 Coleções Exemplo de coleções LinkedList, ArrayList, Vector, ... Exemplo de utilização ArrayList vetor = new ArrayList(); Cliente c1=new Cliente("Fulano","End1","1111222/22",10,5,1970); Cliente c2=new Cliente("Beltrano","End2","3181902/71",21,10,1988); Cliente c3=new Cliente("Ciclano","End1","5819162/02",4,8,1965); vetor.add(c1); vetor.add(c2); vetor.add(c3); for (int i=0; i<vetor.size(); i++) { System.out.println( ((Cliente)vetor.get(i)).getNome() ); } Conceito de Genérico No exemplo anterior, quando se recupera um elemento de uma coleção, é necessário colocar um cast Inconveniente Inseguro (o compilador não testa o cast, que pode gerar erro durante a execução do programa) for (int i=0; i<vetor.size(); i++) { System.out.println( ((Cliente)vetor.get(i)).getNome() ); } Conceito de Genérico Uma das principais modificações do Java 1.5 são os tipos genéricos Genéricos nos permitem criar abstrações sobre tipos de dados Usando genéricos evita-se escrever código maçante e, em especial, potenciais erros de execução resultante do uso excessivo de conversores de tipo (casts) 3 Conceito de Genérico Genéricos Fornecem uma maneira de comunicar o tipo de uma coleção ao compilador Quando o compilador conhece o tipo do elemento da coleção, ele pode verificar se a mesma está sendo usada corretamente e pode inserir os casts corretos nos valores recuperados da coleção Verificação em tempo de compilação Implementação Exemplo de implementação de um genérico simples: import java.util.*; public class Lista<E> { private ArrayList<E> lista; public Lista(){ lista = new ArrayList<E>(); } public void add(E elemento){ lista.add(elemento); } } public class TestaListaGenericaSimples{ public static void main(String args[]){ Lista<Cliente> lp = new Lista<Cliente>(); lp.add(new new Cliente("Fulano","End1","1111222/22",10,5,1970)); lp.add(new Cliente("Beltrano","End2","3181902/71",21,10,1988)); lp.add(new Cliente("Ciclano","End1","5819162/02",4,8,1965)); } } Implementação Convenção Usam-se letras maiúsculas individuais para especificar parâmetros de tipo. Tipicamente: <E> element (elemento de uma coleção) <T> type (tipo) Outras letras próximas a T Herança Se Aluno é subclasse de Pessoa, isso não significa que Lista<Aluno> seja subclasse de Lista<Pessoa> 4 Implementação Restrições sobre genéricos É possível criar genéricos limitados a uma certa “familia” de classes Exemplo: public class Lista<E extends Produto>{ ... } O exemplo define uma classe Lista que pode conter quaisquer elementos cujo tipo seja um subtipo de Produto (subclasse ou implementação) Este tipo de restrição é chamado de “limte superior” (upper bounds) Não importando se Produto é uma classe ou interface usa-se a palavra reservada extends Implementação Restrições sobre genéricos É possível criar também restrições de limite inferior (lower bounds) que são de utilização mais rara Exemplo: public class Lista<E super Enlatado>{ ... } O exemplo apresenta uma lista cujos elementos devem ser supertipos de Enlatado Por exemplo, se Enlatado é derivado de Produto, então Produto é um tipo de elemento aceito na coleção Implementação Java não cria um tipo específico para cada “instanciamento” de uma estrutura genérica Durante a compilação as anotações entre “<“ e “>” são apagadas e ocorre uma tradução para código Java tradicional com os casts adequados. 5 Roteiro Implementação de Genéricos Coleções Conceito de Genérico Implementação Iteradores Conceito Utilização ForEach Conceito Quando se trabalha com coleções, surge a necessidade de manipular os objetos um a um Neste caso, utiliza-se um mecanismo de iteração Definido pela interface Iterator A partir de uma instância da classe que representa a coleção, cria uma “maneira de visualizar” os objetos contidos na coleção Conceito Um iterador é um padrão de projeto de software que abstrai o processo de busca sobre uma coleção de elementos Consiste de: Uma seqüência S Uma posição corrente sobre S Uma forma de avançar para a próxima posição em S, tornando-a posição corrente 6 Utilização A interface Iterator declara três métodos de interesse boolean hasNext(): retorna true se a lista de iteração ainda contêm elementos Object next(): retorna o próximo objeto da lista de iteração void remove(): não recebe argumentos e remove o último elemento retornado pela coleção que foi usada para a sua criação Utilização Pode-se obter uma instância de classe que implementa a interface Iterator usando o método iterator() da coleção Resumindo Iterators Provêm uma forma única de se acessar uma coleção Definido em um dado momento sobre uma coleção, permite navegar (através de uma instância) de forma padrão sobre aquela coleção independente da estrutura interna da mesma As classes de coleções, em geral, possuem um método chamado iterator() que devolve uma referência para um objeto da classe Iterator Utilização Exemplo: LinkedList<Cliente> l = new LinkedList<Cliente>(); l.add(new Cliente("Fulano","End1","1111222/22",10,5,1970)); l.add(new Cliente("Beltrano","End2","3181902/71",21,10,1988)); l.add(new Cliente("Ciclano","End1","5819162/02",4,8,1965)); Cliente c; ListIterator<Cliente> iterator = l.listIterator(); while ( iterator.hasNext() ) { c = iterator.next(); // pega o elemento System.out.println(c.toString()); } 7 ForEach Nova sintaxe do comando for Facilita a iteração sobre vetores e coleções Funciona sobre qualquer coleção que implemente a interface Iterable public interface Iterable<T>{ Iterator<T> iterator(); } Esta interface define um método que retorna um iterador sobre a coleção É uma interface genérica. ForEach Exemplo: LinkedList<Cliente> l = new LinkedList<Cliente>(); l.add(new Cliente("Fulano","End1","1111222/22",10,5,1970)); l.add(new Cliente("Beltrano","End2","3181902/71",21,10,1988)); l.add(new Cliente("Ciclano","End1","5819162/02",4,8,1965)); Cliente c; Lê-se: para c em l for ( Cliente c : l ) { System.out.println(c.toString()); } Referências HORSTMANN, Cay S. “Big Java”. Porto Alegre: Bookman, 2004. 1125 p. GOODRICH, M. TAMASIA, R. “Estrutura de dados e algoritmos em Java”. Ed. Bookman, 2002. GOODRICH, M. TAMASIA, R. “Data structures and algorithms in Java”. Ed. IE Wiley, 2005, 4a ed. 8