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 ☺
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 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] ;
}
}
Testando minha
pilha. O que
acharam?

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());
}
}
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.
Pilha de Object
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] ;
}
}
Resolvido. O que
acharam ?

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);
}
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);
}
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?
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)
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.
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;
public PilhaGeneric (int n) {
v = new T [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.
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] ;
}
}
Agora podemos usar.

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

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;
}
Fácil, não é só
escrever o seguinte
método? O que
acham?

Será que o operador (>)
pode ser aplicado em
qualquer objeto?
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;
}
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”
Excelente apresentação sobre
Collections e Generics

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

  • 1.
    Java - Introduçãoa Coleções e Generics Prof. Sérgio Souza Costa
  • 2.
    Objetivo • Prepararmos paraentendermos como funciona o “framework collection” do Java.
  • 3.
    Capítulo de hoje:Um programador C/C++ precisa lidar com coleções de dados em Java.
  • 4.
    Para que estudarsobre o “framework collection” do Java se eu posso construir minhas próprias coleções ? Aprendi nas aulas de estrutura de dados ☺
  • 5.
    Olhem milha pilha. Muitofá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] ; } }
  • 6.
    Ok. Falta fazeruns 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] ; } }
  • 7.
    Ok. Falta fazeruns testes, mas .... Quais testes ele está se referindo ? 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] ; } }
  • 8.
    Testando minha pilha. Oque acharam? 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()); } }
  • 9.
    Para aulas deestrutura de dados está ok, mas esta tua pilha não é muito útil. Ela é restrita a um tipo de dado ( inteiro)
  • 10.
    Sim. Isso épor que Java é uma linguagem que os métodos e variáveis tem que ter tipos definido estaticamente.
  • 11.
    Em C, euusava *void para estruturas genéricas. Depois bastava eu fazer um cast para um tipo específico.
  • 12.
    Será que Javanão tem algo similar ? O que vocês acham ?
  • 13.
    Yes. Como todaclasse em Java herda de Object, este poderia ser o tipo da minha pilha.
  • 14.
    Pilha de Object publicclass 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] ; } }
  • 15.
    Resolvido. O que acharam? 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); }
  • 16.
    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); }
  • 17.
    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)
  • 18.
    Esperava este erro public staticvoid 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)
  • 19.
    Mas achava queestava armazenando um int. O que é este Integer? 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)
  • 20.
    Esta solução funcionaapenas sobre objetos e não tipos primitivos. O Integer é um objeto equivalente ao Int.
  • 21.
    Além disso, similarao usar *void em C, Object em Java pode gerar problemas em tempo de execução. Devido a inconsistência em operações.
  • 22.
    DILEMA: Tipos garante consistêncianas operações mas enrijece a definição dos meus métodos. Como resolver?
  • 23.
    Até 2004, antesda versão 1.5, teríamos que nos contentar com o uso de Object.
  • 24.
    Porem com aversão 1.5 o Java passou a suportar classes genéricas, também conhecido como polimorfismo paramétrico.
  • 25.
  • 26.
    Generics em Javaé similar a templates em C++.
  • 27.
  • 28.
    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] ; } }
  • 29.
    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] ; } }
  • 30.
    Java utiliza um mecanismochamado 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] ; } }
  • 31.
    Por enquanto saiba queo Java não sabe mapear um construtor 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] ; } }
  • 32.
    Solução é construir Object[]e depois fazer um Cast. 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] ; } }
  • 33.
    Agora podemos usar. PilhaGeneric<Integer>p = new PilhaGeneric <Integer> (5); p.empilha(10); p.empilha("joao"); Causa um erro. A pilha é do tipo Integer. Mantem consistência.
  • 34.
    Além do arraynativo da linguagem Java, existem coleções.
  • 35.
    Esta tua classepilha 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) ; } }
  • 36.
    Então poderíamos usar daseguinte maneira. PilhaGeneric2<Integer> p = new PilhaGeneric2 <Integer> (); p.empilha(10); p.empilha(20); System.out.println(p.desempilha()); System.out.println(p.desempilha());
  • 37.
    E se suapilha tivesse que retornar o maior valor?
  • 38.
    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; }
  • 39.
    Fácil, não ésó escrever o seguinte método? O que acham? Será que o operador (>) pode ser aplicado em qualquer objeto? 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; }
  • 40.
    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; }
  • 41.
    Em C++, bastaeu 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; }
  • 42.
    Java não possui sobrecargade operadores, somente de métodos.
  • 43.
    Existe um métodoque equivale a comparação: compareTo
  • 44.
    Posso usar este métododa 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; }
  • 45.
    Porém preciso dizerque a minha pilha funciona com qualquer T, desde que ele “extenda” a classe Comparable public class PilhaGeneric3 <T extends Comparable<T>> { … }
  • 46.
    A classe pilhaficaria 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; } }
  • 47.
    Na verdade, oJava provê um framework completo para lidar com coleções de dados.
  • 48.
    Entendi. Melhor aprender usaro “framework collection”
  • 49.