Slides de la sexta clase del curso de Java SCJP dictado en la Universidad Nacional de Centro de La Provincia de Buenos Aires.
Contenido:
1. Collections
1. SCJP 6
Clase 6 – Collections e
introducción a generics
Ezequiel Aranda
Sun Microsystems Campus
Ambassador
2. Disclaimer & Acknowledgments
> Even though Ezequiel Aranda is a full-time employee of Sun
Microsystems, the contents here are created as his own
personal endeavor and thus does not reflect any official
stance of Sun Microsystems.
> Sun Microsystems is not responsible for any inaccuracies in
the contents.
> Acknowledgments – The slides of this presentation are made
from “SCJP Unit 6” by Warit Wanwithu and Thanisa
Kruawaisayawan and SCJP Workshop by P. Srikanth.
> This slides are Licensed under a Creative Commons
Attribution – Noncommercial – Share Alike 3.0
> http://creativecommons.org/licenses/by-nc-sa/3.0/
4. Métodos de la clase Object
> nt hashcode()
i
> oolean equals (Object obj)
b
> tring toString()
S
> oid finalize()
v
> inal void notify()
f
> inal void notifyAll ()
f
> inal void wait()
f
5. Sobrescribir toString()
> l pasar una referencia a un objeto como
A
parámetro al método toString(),el método
toString de dicho objeto es llamado.
> i ejecutamos algo como:
S
HardToRead h = new HardToRead()
System.out.println(h);
> btendremos algo como:
O
HardToRead@a47e0
6. class Bob {
int shoeSize;
String nickName;
Bob(String nickName, int shoeSize) {
this.shoeSize = shoeSize;
this.nickName = nickName;
}
public String toString() {
return (quot;I am a Bob, but you can call me quot; +
nickName +quot;. My shoe size is quot; + shoeSize);
}
}
// Pregunta
// Bob f = new Bob(quot;GoBobGoquot;, 19);
// System.out.println(f);
7. Sobreescribir equals()
public class EqualsTest {
public static void main (String [] args) {
Metre one = new Metre(8);
Metre two = new Metre(8);
if (one.equals(two))
System.out.println(quot;one and two are equalquot;);
}
}
class Metre {
private int value; Metre(int val) {
value = val;
}
}
// ¿“One” es igual a “two”?
8. class Metre {
private int value;
Metre(int val) {value = val;}
public int getValue() {
return value;
}
public boolean equals(Object o) {
if ((o instanceof Metre) &&
(((Metre)o).getValue() ==
this.value)) {
return true;
}
else { return false; }
}
}
9. Sobrescribir hashCode()
> i bien puede pensarse que es un
S
identificador de objetos, no necesariamente
es único.
> ebemos saber cuales collections lo utilizan
D
(son las que tienen el prefijo “hash” en el
nombre, así que no debería ser
particularmente difícil).
> ambién debemos poder reconocer las
T
implementaciones apropiadas de hashCode().
11. Entendiendo hashCode()
> i dos objetos son iguales, sus hashcodes
S
deben ser iguales.
> ero si dos objetos tienen el mismo hashcode,
P
no necesariamente son iguales.
> n el examen no se evalúa que sepamos
E
rankear las eficiencias de distintos hashcodes.
> ero debemos saber cuales funcionarán y
P
cuales no (es decir, cuales nos permitirán
encontrar un objeto en la colección)
12. class SaveMe implements Serializable {
transient int x;
int y;
SaveMe(int xVal, int yVal) {
x = xVal; y = yVal;
}
public int hashCode() {
return (x ^ y);
}
public boolean equals(Object o) {
SaveMe test = (SaveMe)o;
if (test.y == y && test.x == x) {
return true;
}
else { return false; }
}
}
13. Implementando hashCode()
> a variable transient volverá (luego de
L
serializar el objeto) con un valor por defecto,
en vez del valor que tenía la variable al
momento de guardarla.
> n conclusión: las variables transient pueden
E
dar problemas en las implementaciones de
equals() y hashCode().
14. Contratos
> En Java, un contrato es un
conjunto de reglas que
deberían ser seguidas si
queremos que nuestras
implementaciones
funcionen de la forma
esperada.
> En otras palabras, si no seguimos los contratos,
nuestro código posiblemente compile y corra,
pero podría fallar inesperadamente en su
ejecución.
15. El contrato de equals
> s reflexivo. Para cualquier referencia por
E
ejemplo x, x.equals(x) debería devolver true.
> s simétrico. Para cualquier par de
E
referencias, por ejemplo x e y, si x.equals(y)
es true si y solo si y.equals(x) devuelve true.
> s transitivo. Para cualquier conjunto de
E
referencias, por ejemplo 'x', 'y' y 'z', si
x.equals(y) devuelve true y para y.equals(z)
devuelve true, entonces z.equals(x) debe
devolver true.
16. El contrato de equals (II)
> Es consistente. Para cualquier pareja de referencias,
por ejemplo x e y, hacer x.equals(y)
consistentemente devuelve true o consistentemente
devuelve false, ninguna información usada en
comparaciones equals modifican al objeto.
> Para cualquier referencia no nula, por ejemplo x,
x.equals(null) debe devolver false.
> Adicionalmente, equals y hashCode están unidos por
un contrato conjunto que dice que si dos objetos son
“equals”, deben tener hashCodes idénticos.
17. El contrato de hashCode
> iempre que es invocado con el mismo objeto
S
más de una vez durante la ejecución de una
aplicación Java, el hashCode () debe devolver
constantemente el mismo número entero,
siempre y cuando la información utilizada
para las comparaciones equals() no
modifiquen el objeto. Este entero no es
necesario que mantenga la coherencia de la
ejecución en una aplicación a otra ejecución
de la misma aplicación.
18. El contrato de hashCode (II)
> Si dos objetos son iguales de acuerdo con el método
equals(java.lang.Object), entonces se pide que el
método hashCode() en cada uno de los dos objetos
debe devolver el mismo resultado entero.
> No es necesario que si dos objetos son desiguales en
función del método equals(Java.lang.Object),
entonces se pide que hashCode () en cada uno de los
dos objetos debe devolver como resultado dos
enteros distintos. Sin embargo, el programador
debe ser consciente de que la producción de
distintos resultados enteros para los objetos puede
mejorar el rendimiento de tablas hash.
19. El contrato de hashCode (III)
> ebemos recordar lo siguiente:
D
Condición Requisito Permitido (aunque no
requerido)
x.equals(y) == true x.hashCode() ==
y.hashCode()
x.hashCode() == x.equals(y) == true
y.hashCode()
x.equals(y) == Sin requerimientos
false de hashCode().
x.hashCode() != x.equals(y) ==
y.hashCode() false
20. 1. public class Test
2. {
3. private int num;
4. private String data;
5. public boolean equals(Object obj)
6. {
7. if(this == obj)
8. return true;
9. if((obj == null) || (obj.getClass() != this.getClass()))
10. return false;
11. // A esta altura, obj es de tipo Test
12. Test test = (Test)obj;
13. return num == test.num &&
14. (data == test.data || (data != null &&
data.equals(test.data)));
15. }
21. 17. public int hashCode()
18. {
19. int hash = 7;
20. hash = 31 * hash + num;
21. hash = 31 * hash + (null == data ? 0 :
data.hashCode());
22. return hash;
23. }
24.
25. // otros métodos
26. }
22. Collections
> l API “comienza” con la definición de varias
E
interfaces, de las cuales debemos conocer las
siguientes para el examen:
> ollection
C
> ist
L
> ueue
Q
> et
S
> ap
M
> ortedSet
S
> ortedMap
S
23. Collections (II)
> ay un gran número de clases concretas,
H
para el examen alcanzará con conocer las
siguientes 13:
Maps Sets Lists Queues Utilities
HashMap HashSet ArrayList PriorityQueue Collections
Hashtable LinkedHashSet Vector Arrays
TreeMap TreeSet LinkedSet
LinkedHashMap
24. La palabra “collection”
> s fácil confundir “Collection” con
E
“Collections”, y viceversa.
> ollections es una clase, con métodos
C
utilitarios.
> ientras que Collection es una interfaz con
M
declaraciones de métodos comunes a la
mayoría de las colecciones, incluyendo add(),
remove(), contains(), size() e iterator().
25. La palabra “collection” (II)
> collection (‘c’ minúscula), representa una de las
estructuras de datos en las cuales se almacenan los
objetos para luego iterar sobre ellos.
> Collection (‘C’ mayúscula), es la interfaz
java.util.Collection, la cual extienden Set, List y
Queue (no existen implementaciones directas de
Collection).
> Collections (‘C’ mayúscula, termina en ‘s’), es la
clase java.util.Collections, que contiene gran
cantidad de métodos estáticos para utilizar en
colecciones.
26.
27. Colecciones
> ists, listas de cosas (implementan List).
L
> ets, conjuntos de cosas de cardinalidad 1
S
(implementan Set).
> aps, cosas con IDs únicos (implementan
M
Map)
> ueues, cosas ordenadas en la forma en que
Q
serán procesadas.
29. “Ordenada”
> uando una colección está ordenada,
C
significa que podemos recorrer sus elementos
en un orden especifico.
> na Hashtable, no está ordenada.
U
> n ArrayList es exactamente como un array.
U
> unca podremos llamar al método “sort” en
N
una colección no ordenada.
30. Sorted
> ignifica que el orden de una colección esta
S
establecido por una regla.
> na regla para ordenar un conjunto de palabras
U
podría ser colocarlas en orden alfabético.
> ara números enteros, podríamos ordenar de
P
mayor a menor de acuerdo a su valor.
> Y como podemos hacer con objetos? No hay una
¿
regla para la clase Foo, salvo que el desarrollador
de esa clase provea una, utilizando la interfaz
Comparable.
31. Interfaz List
> as listas tienen índices.
L
> e hecho, la única cosa que diferencia a algo
D
que es una List de algo que no lo es, es un
conjunto de métodos relacionados con el
índice (por ej.: get(int index), indexOf(Object
o), add(int index, Object obj))
> as tres implementaciones de List están
L
ordenadas por el valor del índice.
32. ArrayList
> a forma de ver esta implementación es que
L
es un array que puede crecer.
> sta ordenada, pero no es “sorted” (sólo está
E
ordenada por el índice).
> e utiliza cuando necesitamos iterar
S
rápidamente, pero no necesitamos agregar o
borrar elementos.
33. Vector
> n vector es básicamente lo mismo que un
U
ArrayList, pero sus métodos están
sincronizados.
> n general, es preferible utilizar ArrayList en
E
vez de Vector, dado que los métodos
sincronizados reducen la performance de
nuestro programa.
> ector y ArrayList son las únicas clase que
V
implementan RandomAccess.
34. LinkedList
> stá ordenada por el índice, pero a diferencia
E
de ArrayList, los elementos están doblemente
vinculados.
> inkedList itera más lento que un ArrayList,
L
pero las inserciones y los borrados son más
rápidos.
> oporta los métodos peek(), poll() y offer() (a
S
partir de Java 5, porque implementa Queue).
35. Interfaz Set
> n Set no permite
U
duplicados.
> e utiliza equals()
S
para determinar si
dos objetos son
identicos.
36. HashSet
> o esta orden, ni utiliza una regla de
N
ordenamiento.
> tiliza el hashcode del elemento para
U
localizarlo. Cuanto mejor la implementación,
mejor performance en el acceso.
> e utiliza cuando el único requisito es no
S
tener duplicados y no importa el orden al
iterarlo.
37. LinkedHashSet
> s una versión ordenada de HashSet.
E
> antiene una lista doblemente vinculada de
M
los elementos.
> l orden de iteración se corresponde con el de
E
inserción de los elementos.
38. TreeSet
> unto con TreeMap, son las únicas
J
colecciones con regla de ordenamiento.
> or defecto, usa el orden natural, pero tiene
P
un constructor que permite establecer la
regla de ordenamiento.
> sa una estructura de árbol Red-Black que
U
asegura que los elementos se encuentren en
orden ascendente.
39. Interfaz Map
> n mapa posee identificadores únicos.
U
> e mapea una clave única (ID) a un valor
S
especifico. Ambos, clave y valor, son objetos.
> as implementaciones de Map permiten
L
buscar un valor dada la clave.
40. HashMap
> ashMap es una colección sin orden ni regla
H
de ordenamiento.
> e utiliza cuando no nos importa el orden al
S
iterar sobre los elementos, sino encontrar
siempre el valor dada la clave.
> ermite un null en la claves, y múltiples nulls
P
entre los valores de la colección.
41. Hashtable
> s la versión sincronizada de HashMap.
E
> l igual que el Vector, conviene utilizarlo solo
A
cuando es necesario que los métodos sean
sincronizados, de otra forma, estaremos
reduciendo la performance de nuestro
programa en forma innecesaria.
> n Hashtable no acepta ningún null.
U
42. LinkedHashMap
> antiene el orden de inserción.
M
> sto hace que sea algo más lento que
E
HashMap para agregar y remover elementos.
> in embargo, la iteración a través de los
S
elementos es más rápida.
44. Interfaz Queue
> n Queue está diseñado para contener una
U
lista de to-dos o cosas que deben procesarse
de alguna forma.
> i bien es posible darle otros ordenamientos,
S
en general se piensa en un queue como un
FIFO (first in, first out).
> oportan todos los métodos estándar de las
S
colecciones y añaden métodos para agregar y
quitar elementos y evaluar los elementos del
queue.
45. PriorityQueue
> Incluida en Java
5.
> Su propósito es
crear una cola
ordenada por
prioridad en vez
de utilizar el
enfoque FIFO.
> Sus elementos se ordenan con una regla de
ordenamiento.
47. ArrayList
> rece dinámicamente.
C
> rovee mejores mecanismos de inserción y
P
búsquedas que los arrays.
List myList = new ArrayList();
> partir de Java 5, podemos utilizar genéricos:
A
List<String> myList = new
ArrayList<String>();
48. ArrayList (II)
> rrayList<String> es similar en muchas formas
A
a String[].
> in embargo, ArrayList<String> es más
S
versátil.
> or ejemplo:
P
List<String> list = new
ArrayList<String>();
String[] list = new String[xxx];
//xxx debe ser un valor específico
49. Autoboxing en colecciones
> n general, las colecciones no pueden
E
contener tipos primitivos.
myInts.add(new Integer(42)); // pre
Java 5.0
> partir de Java 5, los tipos primitivos deben
A
convertirse a objetos equivalentes (utilizando
sus respectivos wrappers). Sin embargo, el
autoboxing realiza esta conversión
automáticamente.
myInts.add(42); // Java 5.0
51. Ordenando Colecciones (II)
> Podemos hacer esto?
¿
ArrayList<DVDInfo> dvdList = new
ArrayList<DVDInfo>();
Collections.sort(dvdList);
> í, dado que sort() toma como argumento
S
una lista.
> in embargo, sólo funcionará cuando los
S
elementos de la lista implementen
Comparable.
52. Forma de implementar Comparable
class DVDInfo implements
Comparable<DVDInfo> { // #1
public int compareTo(DVDInfo d) {
return
title.compareTo(d.getTitle()); // #2
}
}
> #1: implementamos Comparable de tal forma que
un objeto DVDInfo se compare con otros objetos
DVDInfo.
> #2 Implementamos el método compareTo.
53. Comparable
class DVDInfo implements
Comparable<DVDInfo> {
public int compareTo(DVDInfo d) {
return title.compareTo( d.getTitle() );
}
}
> egativo si thisObject < anotherObject
N
> ero si thisObject == anotherObject
C
> ositivo si thisObject > anotherObject
P
54. Comparable (II)
> s importante recordar que cuando
E
sobrescribimos equals(), debemos tomar un
argumento de tipo Object.
> in embargo, cuando sobrescribimos
S
compareTo(), debemos tomar un argumento
del tipo que estamos ordenando.
55. Ordenando con Comparator
> diferencia de Comparable, un Comparator
A
no fuerza la modificación de la clase que
queremos oredenar.
import java.util.*;
class GenreSort implements
Comparator<DVDInfo> {
public int compare(DVDInfo one, DVDInfo
two) {
return
one.getGenre().compareTo(two.getGenre());
}
}
56. Comparable Vs. Comparator
java.lang.Comparable java.util.Comparator
int objOne.compareTo(objTwo) int compare(objOne, objTwo)
Retorna Lo mismo que Comparable
NegaGvo si objOne < objTwo
Cero si objOne == objTwo
PosiGvo si objOne > objTwo
Hay que modificar la clase cuyas Se construye una clase separada de
instancias queremos ordenar aquella cuyas instancias queremos
ordenar.
Solo puede crearse una secuencia de Varias secuencias pueden crearse
ordenamiento
Implementada en las APIs de Java Pensado para ser implementado en
frecuentemente (String, Wrappers, Date, ordenamientos creados por terceros
Calendar)
57. Usando Listas
> asNext() retorna true si hay al menos un
h
elemento mas en la colección que estamos
recorriendo.
> nvocar hasNext no nos posiciona en el elemento
I
siguiente.
> ext() retorna el siguiente elemento en la
n
colección.
> nvocar next nos posiciona el elemento que se
I
encuentra a continuación del que acabamos de
retornar.
58. Usando Listas (II)
Iterator<Dog> i3 = d.iterator();
// creamos un iterador para “Dog”
while (i3.hasNext()) {
Dog d2 = i3.next(); // no requiere cast
System.out.println(d2.name);
}
// O podemos hacer:
Iterator i3 = d.iterator();
Dog d2 = (Dog)i3.next();
59. Usando Sets
> ecuerden que los Sets son sin duplicados.
R
boolean[] ba = new boolean[5]
//definición de s
ba[0] = s.add(”homerquot;);
ba[1] = s.add(new Integer(42));
ba[2] = s.add(quot;bartquot;);
ba[3] = s.add(”homerquot;);
ba[4] = s.add(new Object());
60. Usando Sets (II)
> et s = new HashSet();
S
> rue true true false true
t
> omer java.lang.Object@e09713 42 bart
h
> et s = new TreeSet();
S
> xception in thread quot;mainquot;
E
java.lang.ClassCastException: java.lang.String
61. Usando Sets (III)
> l orden de los objetos impresos no es
E
predecible. HashSet y LinkedHashSet no
garantizan ningún orden.
> a cuarta invocación falla, puesto que
L
intentamos agregar un elemento que ya era
parte del conjunto.
> Por qué aparece la excepción?
¿
62. Usando Maps
Map<Object, Object> m = new
HashMap<Object,Object>();
m.put(quot;k1quot;, new Dog(quot;aikoquot;));
// agregamos pares clave/ valor
m.put(quot;k2quot;, Pets.DOG);
m.put(Pets.CAT, quot;CAT keyquot;);
Dog d1 = new Dog(quot;cloverquot;);
m.put(d1, quot;Dog keyquot;);
m.put(new Cat(), quot;Cat keyquot;);
63. Usando PriorityQueue
> riorityQueue, a diferencia de las estructuras
P
FIFO, ordena sus elementos utilizando una
regla de ordenamiento definida por el
usuario.
> n PriorityQueue puede ordenarse utilizando
U
un Comparator, que nos permite definir el
ordenamiento como deseemos.
> as Queues tienen métodos que no se
L
encuentran en otras subinterfaces de
Collection: peek, poll y offer.
64. Usando PriorityQueue (II)
int[] ia = {1,5,3,7,6,9,8 };
PriorityQueue<Integer> pq1 = new
PriorityQueue<Integer>();
for(int x : ia)
pq1.offer(x);
for(int x : ia)
System.out.print(pq1.poll() + quot; quot;);
> offer() agrega elementos.
> peek() retorna el elemento de mayor prioridad sin
removerlo de la colección.
> poll() retorna el elemento de mayor prioridad en la
colección, y lo remueve de la misma.
65. Pregunta
String[] sa = {quot;>ff<quot;, quot;> f<quot;, quot;>f <quot;,
quot;>FF<quot; };
PriorityQueue<String> pq3 = new
PriorityQueue<String>();
for(String s : sa)
pq3.offer(s);
for(String s : sa)
System.out.print(pq3.poll() + quot; quot;);
> Cuál es el resultado?
¿