java - introdução a coleções e generics

Post on 26-May-2015

865 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Java - Introdução a Coleções e Generics

Prof. Sérgio Souza Costa

Objetivo

• Prepararmos para entendermos como funciona o “framework collection” do Java.

Capítulo de hoje: Um programador C/C++ precisa lidar com coleções de dados em Java.

Para que estudar sobre o “framework collection” do Java se eu posso construir minhas próprias coleções ?

Aprendi nas aulas de estrutura de dados ☺

public class Pilha {int v[];int pos;public Pilha (int n) {

v = new int [n];pos = 0;

}public void empilha(int x) {

v[pos++] = x;}public int desempilha() {

return v[--pos] ;}

}

Olhem milha pilha. Muito fácil

public class Pilha {int v[];int pos;public Pilha (int n) {

v = new int [n];pos = 0;

}public void empilha(int x) {

v[pos++] = x;}public int desempilha() {

return v[--pos] ;}

}

Ok. Falta fazer uns testes, mas ....

public class Pilha {int v[];int pos;public Pilha (int n) {

v = new int [n];pos = 0;

}public void empilha(int x) {

v[pos++] = x;}public int desempilha() {

return v[--pos] ;}

}

Ok. Falta fazer uns testes, mas ....

Quais testes ele está se referindo ?

public class Teste {public static void main(String[] args) {

Pilha p = new Pilha (5);p.empilha(10);p.empilha(5);p.empilha(2);System.out.println(p.desempilha());System.out.println(p.desempilha());System.out.println(p.desempilha());

}}

Testando minha pilha. O que

acharam?

Para aulas de estrutura de dados está ok, mas esta tua pilha não é muito útil. Ela é restrita a um tipo de dado (

inteiro)

Sim. Isso é por que Java é uma linguagem que os métodos e variáveis tem que ter tipos

definido estaticamente.

Em C, eu usava *void para estruturas genéricas. Depois

bastava eu fazer um cast para um tipo específico.

Será que Java não tem algo similar ? O que

vocês acham ?

Yes. Como toda classe em Java herda de

Object, este poderia ser o tipo da minha pilha.

public class PilhaObjeto {Object v[];int pos;public PilhaObjeto (int n) {

v = new Object [n];pos = 0;

}public void empilha(Object x) {

v[pos++] = x;}public Object desempilha() {

return v[--pos] ;}

}

Pilha de Object

public static void main(String[] args) {PilhaObjeto p = new PilhaObjeto (5);p.empilha("Joao");p.empilha("Jose");p.empilha("Maria");String nome = (String) p.

desempilha();System.out.println("nome:"+nome);

}

Resolvido. O que acharam ?

public static void main(String[] args) {PilhaObjeto p = new PilhaObjeto (5);p.empilha("Joao");p.empilha("Jose");p.empilha(10);String nome = (String) p.

desempilha();System.out.println("nome:"+nome);

}

Mais um teste ...

public static void main(String[] args) {PilhaObjeto p = new PilhaObjeto (5);p.empilha("Joao");p.empilha("Jose");p.empilha(10);String nome = (String) p.

desempilha();System.out.println("nome:"+nome);

}

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

at TesteObjeto.main(TesteObjeto.java:12)

Mais um teste ...

public static void main(String[] args) {PilhaObjeto p = new PilhaObjeto (5);p.empilha("Joao");p.empilha("Jose");p.empilha(10);String nome = (String) p.

desempilha();System.out.println("nome:"+nome);

}

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

at TesteObjeto.main(TesteObjeto.java:12)

Esperava este erro

public static void main(String[] args) {PilhaObjeto p = new PilhaObjeto (5);p.empilha("Joao");p.empilha("Jose");p.empilha(10);String nome = (String) p.

desempilha();System.out.println("nome:"+nome);

}

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

at TesteObjeto.main(TesteObjeto.java:12)

Mas achava que estava armazenando um int. O que é este Integer?

Esta solução funciona apenas sobre objetos e não tipos

primitivos. O Integer é um objeto equivalente ao Int.

Além disso, similar ao usar *void em C, Object em Java pode gerar

problemas em tempo de execução. Devido a inconsistência

em operações.

DILEMA: Tipos garante consistência nas operações mas enrijece a definição dos meus

métodos. Como resolver?

Até 2004, antes da versão 1.5, teríamos que nos contentar com

o uso de Object.

Porem com a versão 1.5 o Java passou a suportar classes

genéricas, também conhecido como polimorfismo

paramétrico.

Ok. Vou pesquisar.....

Generics em Java é similar a templates

em C++.

Basicamente substituo tipos por

um T genérico.

public class PilhaGeneric <T> {T v[];int pos;public PilhaGeneric (int n) {

v = new T [n];pos = 0;

}public void empilha(T x) {

v[pos++] = x;}public T desempilha() {

return v[--pos] ;}

}

Não funcionou como esperado. Java não

reconheceu o construtor genérico

public class PilhaGeneric <T> {T v[];int pos;public PilhaGeneric (int n) {

v = new T [n];pos = 0;

}public void empilha(T x) {

v[pos++] = x;}public T desempilha() {

return v[--pos] ;}

}

Por que será ?

public class PilhaGeneric <T> {T v[];int pos;public PilhaGeneric (int n) {

v = new T [n];pos = 0;

}public void empilha(T x) {

v[pos++] = x;}public T desempilha() {

return v[--pos] ;}

}

Java utiliza um mecanismo chamado Erasure para gerar os

códigos finais.

public class PilhaGeneric <T> {T v[];int pos;public PilhaGeneric (int n) {

v = new T [n];pos = 0;

}public void empilha(T x) {

v[pos++] = x;}public T desempilha() {

return v[--pos] ;}

}

Por enquanto saiba que o Java não sabe

mapear um construtor T genérico.

public class PilhaGeneric <T> {T v[];int pos;@SuppressWarnings("unchecked")public PilhaGeneric (int n) {

v = (T[]) new Object [n];pos = 0;

}public void empilha(T x) {

v[pos++] = x;}public T desempilha() {

return v[--pos] ;}

}

Solução é construir Object[] e depois

fazer um Cast.

PilhaGeneric<Integer> p = new PilhaGeneric <Integer> (5);p.empilha(10);p.empilha("joao");

Agora podemos usar.

Causa um erro. A pilha é do tipo Integer. Mantem consistência.

Além do array nativo da linguagem Java, existem coleções.

Esta tua classe pilha poderia usar uma

coleção ao invés de um array.

public class PilhaGeneric2 <T> {private List<T> v; public PilhaGeneric2 () {

v = new ArrayList<T>();}public void empilha(T x) {

v.add(x);}public T desempilha() {

return v.remove(v.size()-1) ;}

}

Então poderíamos usar da seguinte

maneira.

PilhaGeneric2<Integer> p = new PilhaGeneric2 <Integer> ();

p.empilha(10);p.empilha(20);System.out.println(p.desempilha());System.out.println(p.desempilha());

E se sua pilha tivesse que retornar o maior

valor?

Fácil, não é só escrever o seguinte

método? O que acham?

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i) > maior)maior = v.get(i);

}return maior;

}

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i) > maior)maior = v.get(i);

}return maior;

}

Fácil, não é só escrever o seguinte

método? O que acham?

Será que o operador (>) pode ser aplicado em qualquer objeto?

Verdade, este método não é tão genérico. O objeto preciso saber

comparar.

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i) > maior)maior = v.get(i);

}return maior;

}

Em C++, basta eu sobrecarregar o

operador (>). E em Java?

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i) > maior)maior = v.get(i);

}return maior;

}

Java não possui sobrecarga de

operadores, somente de métodos.

Existe um método que equivale a

comparação: compareTo

Posso usar este método da seguinte

maneira

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i).compareTo(maior) > 0)

maior = v.get(i);}return maior;

}

Porém preciso dizer que a minha pilha funciona com qualquer T, desde que ele

“extenda” a classe Comparable

public class PilhaGeneric3 <T extends Comparable<T>> {

…}

A classe pilha ficaria da seguinte maneira

public class PilhaGeneric3 <T extends Comparable<T>> {

private List<T> v; public PilhaGeneric3 () {

v = new ArrayList<T>();}public void empilha(T x) {

v.add(x);}public T desempilha() {

return v.remove(v.size()-1) ;}

public T maior () {T maior = v.get(0);for (int i=0; i< v.size(); i++) {

if (v.get(i).compareTo(maior) > 0)

maior = v.get(i);}return maior;

}}

Na verdade, o Java provê um framework completo

para lidar com coleções de dados.

Entendi. Melhor aprender usar o

“framework collection”

top related