O documento discute como um programador C/C++ pode lidar com coleções de dados em Java. Inicialmente, o programador propõe construir suas próprias coleções, mas logo percebe as limitações disso. Ele então explora o uso de generics em Java, que permite criar coleções genéricas capazes de armazenar qualquer tipo de dado. Finalmente, é introduzido o framework de coleções do Java, que fornece implementações prontas para uso.
3. Capítulo de hoje: Um programador C/C++ precisa
lidar com coleções de dados em Java.
4. 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 ☺
5. 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] ;
}
}
6. 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] ;
}
}
7. 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] ;
}
}
8. 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());
}
}
9. Para aulas de estrutura 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, eu usava *void para
estruturas genéricas. Depois
bastava eu fazer um cast para
um tipo específico.
12. Será que Java não tem
algo similar ? O que
vocês acham ?
13. Yes. Como toda classe
em Java herda de
Object, este poderia ser
o tipo da minha pilha.
14. 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] ;
}
}
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 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)
19. 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)
20. Esta solução funciona apenas
sobre objetos e não tipos
primitivos. O Integer é um objeto
equivalente ao Int.
21. 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.
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
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] ;
}
}
31. 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] ;
}
}
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 array nativo
da linguagem Java,
existem coleções.
35. 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) ;
}
}
36. 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());
37. E se sua pilha 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++, 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;
}
44. 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;
}
45. 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>> {
…
}
46. 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;
}
}
47. Na verdade, o Java provê
um framework completo
para lidar com coleções de
dados.