You are on page 1of 30

5.

Colecciones
5.1

Introduccin

En un programa que utilice los conceptos de orientacin a objetos, lo ms comn es crear


muchos objetos de diferentes clases, y luego realizar operaciones con ellos. Para un
programa extremadamente sencillo se pueden tener variables que referencien cada uno
de los objetos creados, pero a medida que aumenta la cantidad de objetos que se
necesitan, es muy difcil mantener esta forma de referenciarlos.
De ah nace la necesidad de contar con elementos que permitan agrupar los objetos de
alguna forma, y faciliten su creacin, bsqueda, e incluso su eliminacin. La primera
forma de agrupar los objetos es utilizar un arreglo1. Los arreglos son estructuras que
permiten tener elementos de un mismo tipo, y que son referenciados por una variable; en
ellos se puede tener acceso a un elemento especfico a travs de un ndice.
Una de las grandes desventajas de los arreglos, adems del hecho de que no puede
modificarse su tamao una vez se ha definido, es que todo el procesamiento adicional
que se requiere para administrar adecuadamente los elementos que contiene, depende
del programador. Por ejemplo, si se desea que los elementos del arreglo no se repitan se
debe recorrer todo el arreglo cada vez que se vaya a insertar un nuevo objeto para hacer
esta verificacin, o si se desea ordenar los elementos, hay que idear un mecanismo para
lograrlo.
Lo ideal, entonces, es contar con estructuras para agrupar objetos, pero que adems
ofrezcan otros servicios al programador, como la posibilidad de ordenar los elementos
automticamente o de verificar si ya existe el elemento que desea insertar. Java ofrece
estas estructuras en lo que se conoce como el Marco de trabajo de Colecciones, o
Collection Framework, que se presentar en este captulo.

5.2

Definicin

Una coleccin, o como a veces se le llama: contenedora, es un objeto que est en


capacidad de contener referencias individuales a muchos objetos. Las colecciones
permiten, bsicamente, organizar de alguna manera los objetos que se usarn en el
programa, adems de ofrecer algunos servicios adicionales para facilitar el manejo de
estos objetos. Existen diferentes tipos de colecciones que permiten ofrecer diversos
servicios, por ejemplo, algunas ordenan los objetos que contienen, pero pueden ser lentas
al insertarlos, mientras que otras insertan los objetos muy rpidamente, pero no de
manera organizada.
En el paquete java.util de Java se han definido varias clases e interfaces para el manejo
de colecciones. Estas clases e interfaces incluyen colecciones que se pueden usar
1

Debe conocerse el concepto de arreglo y su manejo en Java.

directamente en los programas, pero tambin permiten la creacin de colecciones


propias, si no hay ninguna coleccin que se ajuste a lo requerido por el programador.
El marco de trabajo para las colecciones incluye:
- Un conjunto de interfaces que definen los mtodos bsicos que deben tener las
colecciones.
- Clases abstractas que implementan los mtodos bsicos definidos por las interfaces,
pero incluyendo algunos servicios adicionales. Cuando se desea hacer una coleccin
propia puede elaborarse una clase que herede de estas clases abstractas, en lugar de
implementar directamente la interfaz o interfaces necesarias.
- Clases concretas, es decir, colecciones listas para usar en los programas.
- Otros elementos (interfaces, clases y mtodos) que proporcionan servicios
adicionales.
La Figura 9 muestra las principales interfaces del marco de trabajo de colecciones.

<< interfaz >>


Collection

<< interfaz >>


List

<< interfaz >>


Map

<< interfaz >>


Set

<< interfaz >>


SortedMap

<< interfaz >>


Iterator

<< interfaz >>


ListIterator

<< interfaz >>


SortedSet
Figura 1 Interfaces del marco de trabajo de colecciones

5.3

Jerarqua Collection

La interfaz Collection define la forma general como se comportan todas las colecciones
que de ella se derivan y que hacen mucho ms fcil la elaboracin de los programas,
pues slo debe conocerse el encabezado del mtodo para utilizarlo, aunque internamente
cada clase de la jerarqua implemente el servicio de manera diferente.
En esta interfaz se definen los mtodos bsicos de toda coleccin, entre los cuales se
encuentran:
boolean add(Object): Permite adicionar un objeto a la coleccin. Observe que se
recibe un parmetro de tipo Object, es decir, cualquier objeto puede guardarse en una
coleccin, pero no tipos bsicos. Este mtodo retorna true cuando el objeto se pudo
adicionar exitosamente a la coleccin.

boolean remove(Object): Permite retirar un objeto de la coleccin, y retorna true si se


pudo retirar. Si un objeto se encuentra varias veces en la coleccin, ste mtodo retira
la primera referencia a l.
boolean contains(Object): Determina si el objeto que se recibe como parmetro se
encuentra o no en la coleccin.
int size(): Indica cuntos objetos hay actualmente en la coleccin.
boolean isEmpty(): Retorna true si no hay objetos en la coleccin.
Iterator iterator(): Retorna un objeto iterador asociado a la coleccin. Este objeto se
explicar posteriormente.
Object[] toArray(): Realiza una copia de los objetos de la coleccin y retorna dichas
copias organizadas en un arreglo.

No todas las colecciones de la jerarqua permiten realizar todas las operaciones definidas
en la interfaz Collection (o en Map, como se ver ms adelante). Si alguna operacin no
es permitida se lanza una java.lang.UnsupportedOperationException.
Preguntas

Para qu sirven los mtodos addAll y removeAll de la interfaz Collection?


Existe algn mtodo que permita retirar todos los elementos de una coleccin?

Como se puede observar, no es necesario que el programador realice operaciones


adicionales para adicionar o retirar un elemento de la coleccin, como se requera con los
arreglos. Basta con invocar el mtodo add o remove de la coleccin para lograr este
propsito.
Sin embargo, no existen mtodos para recorrer la coleccin, o para obtener una
referencia a uno de los objetos que contiene, sin retirarlo de la lista. Esto se debe a que
cada clase tiene formas diferentes de obtener los diferentes elementos que la conforman.
Para estandarizar la forma de recorrer las colecciones se define la interfaz Iterator que se
revisar en detalle ms adelante.
5.3.1

Colecciones tipo lista

Las listas son agrupaciones de objetos que cuentan con las siguientes caractersticas:
- Los elementos se encuentran organizados uno despus de otro (en secuencia).
- Es posible conocer en cualquier momento la posicin donde est ubicado un elemento
dentro de la lista.
- Permite elementos repetidos.
- No se requiere que los elementos almacenados se encuentren ordenados por algn
criterio particular.
Dado que una lista permite elementos repetidos, no se realiza ninguna verificacin al
momento de adicionar un objeto. Una lista, por lo tanto, es til cuando no hay necesidad
de identificar de manera nica los elementos.

Para ofrecer el comportamiento de las colecciones tipo lista, el framework de colecciones


cuenta con interfaces y clases que definen este comportamiento, todas ellas derivadas de
la interfaz Collection.
5.3.1.1 Interfaz List
Esta interfaz define un comportamiento que permite tener control sobre la posicin donde
un elemento es insertado en la lista, permite el acceso a cada elemento a travs del
ndice de su posicin y realizar bsquedas de elementos sobre la lista. Adicionalmente
provee un iterador especial de tipo ListIterator para hacer el recorrido sobre los elementos
de la coleccin. Este iterador se ver en detalle ms adelante.

Figura 10 Mtodos definidos en la interfaz List

Como se observa en la figura 10, la interfaz List, adems de los mtodos que hereda de
Collection, define, entre otros, los siguientes mtodos:
add(int, Object): Adiciona un objeto en la posicin indicada en la lista (desplazando los
elementos posteriores a esta posicin, hacia la derecha).
Object remove(int): Retira el objeto que hay en la posicin dada, y retorna una
referencia a este.
int indexOf(Object): Busca el objeto en la coleccin y retorna la posicin de su primera
aparicin. Si el elemento no est en la coleccin retorna 1.

Object get(int): Retorna una referencia al objeto que se encuentra en la posicin que
se da en el parmetro.
ListIterator listIterator(): Retorna un objeto ListIterator asociado a la lista. Esta interfaz
se explica posteriormente.
ListIterator listIterator(int): Retorna un objeto ListIterator que comienza en la posicin
indicada.

Puede observarse que la interfaz List define mtodos que permiten adicionar, eliminar u
obtener una referencia a un objeto a travs de su posicin. Sin embargo, estos mtodos
no siempre son eficientes, y en su lugar se recomienda recorrer la lista utilizando un
iterador.
5.3.1.2 Clase AbstractList
Esta clase, de tipo abstracto, implementa a la interfaz List, y define cierta funcionalidad
bsica para las clases que hereden de ella, es decir, ya contiene el cdigo para algunos
de los mtodos definidos en List. Es especialmente til cuando se requiere elaborar una
coleccin propia con el comportamiento de una lista, en cuyo caso la coleccin hereda de
AbstractList , evitando el tener que implementar directamente a la interfaz List.

Figura 11 Mtodos definidos en la clase AbstractList

Pregunta:
Cules son los mtodos cuyo cdigo ya fue elaborado en la clase AbstracList?

5.3.1.3 Clase ArrayList


Esta clase, de tipo concreto, hereda de la clase AbstractList. Un ArrayList es muy
parecido a un arreglo, pero su tamao crece dinmicamente, a medida que se necesita.
Al igual que los arreglos, un ArrayList no es muy til para insertar o eliminar elementos en
lugares diferentes al final del mismo, pero es muy fcil de recorrer y muy rpido para
encontrar un elemento dada su posicin.
Los constructores de esta clase son:
ArrayList(): Crea un ArrayList vaco.
ArrayList(Collection): Crea un ArrayList que tiene los elementos que estn en la
coleccin dada.
ArrayList(int): Crea un ArrayList con la capacidad inicial que se indica en el parmetro.
Este valor puede cambiar a medida que se adicionan elementos a la lista.
Ejemplo:
Se tiene un ArrayList donde se almacenan los libros disponibles para la venta en una
Librera, y se requiere verificar si, dado el ttulo de un libro, este existe en la librera para
entregarlo al cliente y retirarlo de la coleccin.
Cdigo (apartes):

public class Libro{


private String ttulo;
private int pginas;
private String autor;
public Libro(String elTtulo, int lasPginas, String elAutor){
ttulo=elTtulo;
pginas=lasPginas;
autor=elAutor;
}
public Libro(String elTtulo){
ttulo=elTtulo;
}
//Define que dos libros son iguales si tienen el mismo ttulo
public boolean equals(Object obj){
if (obj instaceof Libro){
Libro nuevo=(Libro) obj;
If (ttulo.equals(nuevo.getTtulo())
return true;
return false;
}
return false;
}
}
import java.util.*;
public class Librera{
private static ArrayList libros;
public static Libro venderLibro(String ttulo){
Libro pedido=new Libro(ttulo);
int posicin=libros.indexOf(pedido);

continuacin
if (posicin != -1){
Libro vendido=libros.get(posicin);
libros.remove(vendido);
return vendido;
}
return null;
}
public static void main (String args[ ]){
.
Libro libro=venderLibro(ttulo);
if (libro!=null){
System.out.println(Libro vendido);
else
System.out.println(El libro no se encuentra disponible);

}
}

5.3.1.4 LinkedList
Esta clase, de tipo concreto, hereda de la clase AbstractSequentialList, que implementa a
la interfaz List. Las colecciones de tipo LinkedList ocupan espacios diferentes de la
memoria por cada objeto que all se almacena, de manera que cada elemento encadena
a su sucesor y antecesor para mantener la lista. Esta forma de implementacin hace que
el adicionar o remover elementos de cualquier parte de la lista sea muy fcil, sin embargo,
dificulta el acceso a un elemento dada su posicin, pues requiere recorrer la cadena de
enlaces entre sus elementos.
Adems de los mtodos definidos en la interfaz List, una LinkedList define:
addFirst(Object): Adiciona un objeto al comienzo de la lista.
addLast(Object): Adiciona un objeto al final de la lista.
Object removeFirst(): Retira el primer elemento de la lista, y retorna una referencia a
este.
Object removeLast(): Retira el ltimo elemento de la lista, y retorna su referencia.
Ejemplo:
En un banco se requiere que cada vez que llegue un nuevo cliente a la caja, ste sea
agregado al final de la fila de clientes, y cuando alguien deba pasar a la caja para ser
atendido, se retire del principio de la fila.
Cdigo (apartes):

public class Cliente{


private String identificacin;
private String nombre;

.
}

public Cliente(String id, String name){


identificacin=id;
nombre=name;
}

import java.util.*;
public class Banco{
private LinkedList fila;
public Cliente pasarACaja(){
Cliente atendido= (Cliente) fila.removeFirst();
return atendido;
}

.
}

5.3.2

public void llegarAFila(Cliente){


fila.addLast(Cliente);
}

Colecciones tipo conjunto

Los conjuntos son agrupaciones de objetos donde no se pueden tener elementos


duplicados. Este tipo de coleccin es til cuando los elementos que se desean agrupar
deben identificarse de manera nica, por ejemplo, el conjunto de estudiantes de una
universidad.
A continuacin se revisarn aquellas interfaces y clases que definen a las colecciones tipo
conjunto.
5.3.2.1 Interfaz Set
Esta interfaz no define mtodos adicionales a los ya definidos en Collection, pero s
determina un comportamiento distinto para algunos de sus mtodos. Por ejemplo,
aquellas clases que implementen la interfaz Set, deben elaborar el mtodo add de manera
que se indique en el retorno si el elemento pudo ser agregado (true) o no (false) a la
coleccin, validando la existencia del mismo en el grupo de elementos.
Cabe anotar que para los datos de tipo referenciado (objetos) la igualdad se determina de
acuerdo lo establecido en el mtodo equals. Si se requiere determinar la igualdad bajo
un criterio distinto al establecido en la clase Object (dos objetos son iguales si ocupan el
mismo espacio de memoria), entonces es necesario sobrescribir dicho mtodo en la clase
que se quiere comparar.

Adicional al mtodo equals, la clase Object define el mtodo hashCode, el cual retorna un
valor entero diferente para cada objeto existente en memoria. Se recomienda que al
sobrescribir el mtodo equals, tambin se sobrescriba el mtodo hashCode, de manera
que para dos objetos que se definen como iguales, el valor entero retornado por dicho
mtodo sea el mismo para ambos objetos, independiente de que los dos ocupen espacios
diferentes en la memoria.
La clase String contiene el mtodo equals sobrescrito indicando que dos objetos de este
tipo son iguales si la cadena que contienen es la misma. Adicionalmente, en la clase se
ha sobrescrito el mtodo hashCode para que el valor retornado sea el mismo para dos
cadenas iguales.
Ejemplo: Se desea tener un conjunto de estudiantes, cmo se determina que un
estudiante ya existe, y por lo tanto no se adiciona de nuevo a la coleccin? Puede
definirse que la forma de identificar de manera nica a un estudiante es a travs de un
cdigo, por lo que la definicin de la clase Estudiante quedara as:
class Estudiante {
private String cdigo;
private String nombre;

public boolean equals(Object objeto) {


if (objeto instanceof Estudiante){
Estudiante otroEstudiante = (Estudiante)objeto;
return (cdigo.equals(otroEstudiante.cdigo));
}
return false;
}
public int hashCode() {
return cdigo.hashCode();
}
public Estudiante(String cdigo, String nombre) {
this.cdigo = cdigo;
this.nombre = nombre;
}
public Estudiante(String cdigo){
this.cdigo=cdigo;
nombre=null;
}

public String toString() {


return [+cdigo + - +nombre + ];
}

De esta forma, si se intenta adicionar un estudiante a un conjunto y ya hay un estudiante


con ese cdigo, al validar la igualdad con el mtodo equals retornar true, y a su vez, el
mtodo add no lo adicionar en el conjunto, retornando false.

Pregunta: Para qu se define el segundo constructor de Estudiante nicamente con el


atributo cdigo?
5.3.2.2 Interfaz SortedSet
Esta interfaz define el comportamiento del conjunto como un grupo de elementos
ordenado de manera ascendente, por lo tanto, agrega mtodos que deben dar acceso a
los elementos de acuerdo al orden en que se encuentran.
Algunos de los mtodos que define esta interfaz son:
Object first(): Retorna el primer elemento del conjunto, es decir, el menor de todos.
Object last(): Retorna el ltimo elemento (el mayor) del conjunto.
Comparator comparator(): Devuelve el objeto comparator (se explica posteriormente)
que se utiliza para ordernar los elementos. En caso de no contar con un objeto
comparator retorna null.

Figura 12 Mtodos definidos en la interfaz SortedSet

Existen dos formas para determinar cundo un objeto es mayor que otro, y de esta forma
poder ordenarlos en el conjunto. La primera forma es hacer que las clases cuyos objetos
se insertarn en el conjunto implementen la interfaz java.lang.Comparable, y la segunda
forma es usar un objeto que implemente la interfaz java.util.Comparator. Estas interfaces
se explicarn en detalle a continuacin.
Interfaz Comparable
Esta interfaz permite definir lo que se denomina el orden natural (natural order) de los
objetos. La interfaz define un nico mtodo:

int compareTo(Object): Debe retornar un entero positivo cuando el parmetro es


menor que el objeto actual, un entero negativo cuando el parmetro es mayor que el
objeto actual, y cero si son iguales. Se recomienda que este mtodo sea compatible
con la definicin que se haga del mtodo equals, es decir, si se retorna cero al
comparar dos objetos con compareTo, debe retornarse true al compararlos con
equals.
Todas las clases Wrapper implementan esta interfaz, al igual que las clases Date
y String.

Por ejemplo, se desea tener un conjunto ordenado de revistas, donde la mayor es la que
tiene mayor nmero de pginas. Defina la clase Revista de manera que se permita el
ordenamiento de los objetos de este tipo al momento de ingresarlos a un conjunto
ordenado.
Solucin: De acuerdo al enunciado se requiere:
- Definir la clase Revista, que debe implementar la interfaz Comparable.
- Sobreescribir el mtodo compareTo para establecer el orden de las revistas.
- Sobreescribir los mtodos equals y hashCode, de manera que sean compatibles con
la definicin dada en compareTo.
class Revista implements Comparable {
private String nombre;
private int pginas;

public Revista(String nombre, int pginas) {


this.nombre = nombre;
this.pginas = pginas;
}
public int compareTo(Object objeto) {
Revista otraRevista = (Revista)objeto;
return (pginas - otraRevista.pginas);
}
// Define que dos revistas son iguales si tienen el mismo nmero de pginas
public boolean equals(Object objeto) {
Revista otraRevista = (Revista)objeto;
return (pginas == otraRevista.pginas);
}
public int hashCode() {
return pginas;
}
public String toString() {
return (nombre+"-"+pginas);
}

Con la definicin de Revista dada, se podran agregar objetos de este tipo a una coleccin
de tipo SortedSet, quedando ordenadas de menor a mayor cantidad de pginas.
Interfaz Comparator
Adems del orden natural de los objetos, es posible definir tambin otro tipo de
ordenamiento llamado orden parcial (partial orden). Esta forma de definir el orden de los
objetos se utiliza cuando hay clases que no implementan la interfaz Comparable, o ya
tienen un orden natural definido, pero se desea crear otra coleccin que los ordene de
manera diferente.

Para definir el orden parcial es necesario tener una clase que implemente la interfaz
Comparator, y luego usar alguno de sus objetos, que se denomina objeto comparador,
como un auxiliar para comparar dos objetos (de otra clase), que se desean ordenar. La
interfaz Comparator define el siguiente mtodo:

compare(Object, Object): Retorna un entero negativo si el primer objeto es menor que


el segundo, un entero positivo si el primer objeto es mayor que el segundo, y cero si
son iguales.

Ejemplo: Modifique el ejemplo anterior, de manera que las revistas no se ordenen por el
nmero de pginas, sino por su nombre.
Solucin:
Teniendo en cuenta que no se quiere modificar el orden natural por el cual se determina si
una revista es mayor que otra (cantidad de pginas), se crear un objeto de tipo
Comparator que defina el orden parcial solicitado, con base en el orden alfabtico del
nombre de las revistas:
import java.util.*;
class ComparaRevista implements Comparator {
public int compare(Object objeto1, Object objeto2) {
// La clase Revista debe tener un mtodo getNombre
String nombreRevista1 = ((Revista)objeto1).getNombre();
String nombreRevista2 = ((Revista)objeto2).getNombre();
//Se usa el mtodo compareTo de String para determinar cul de las dos
//cadenas del nombre es mayor
return nombreRevista1.compareTo(nombreRevista2);
}
}

Al instanciar la clase ComparaRevista, se obtiene un objeto comparador que puede ser


utilizado para agregar objetos de tipo Revista a una coleccin de tipo SortedSet,
quedando ordenadas de menor a mayor segn su nombre.
Por defecto las colecciones que implementan SortedSet usan el orden natural de los
objetos (usando el mtodo compareTo() del objeto a agregar) para agregar elementos de
forma ordenada, a no ser que explcitamente se le pida a la coleccin que utilice el orden
parcial (usando el mtodo compare() del objeto Comparator) para hacer el ordenamiento.
Para usar el orden parcial, lo normal es que la coleccin que implementa la interfaz
SortedSet tenga un constructor que recibe un parmetro de tipo Comparator. Si se
instancia la coleccin usando este constructor, entonces se usar el orden que define el
comparador para ordenar los objetos, pero si no se usa este constructor, entonces se
usar el orden natural de los objetos.

Si se utiliza un comparador para ordenar los objetos en un SortedSet, es


recomendable que el mtodo equals de estos objetos sea compatible con la
forma de ordernar de dicho comparador.

5.3.2.3 Clase HashSet


Esta clase, de tipo concreto, hereda de la clase AbstractSet, que a su vez implementa la
interfaz Set. De acuerdo a esto, la clase HashSet define una coleccin que permite
almacenar elementos nicos, pero adems, utiliza el cdigo hash de cada objeto a
almacenar obtenido a partir del mtodo hashCode(), para ubicarlos en una tabla
especial, denominada tabla hash. Esta forma de almacenar los objetos permite que se
realicen bsquedas muy rpidas, ya que el cdigo hash se traduce a una posicin en la
tabla para llegar directamente al elemento. Dado que los elementos se almacenan de
acuerdo a su cdigo hash, no se encuentran ordenados dentro de la coleccin.

Figura 13 Mtodos definidos en la clase HashSet

Adems del constructor por defecto, esta clase tiene los siguientes constructores:
HashSet(Collection): Crea un HashSet que contiene los elementos que hay en la
coleccin dada.
HashSet(int): Crea un HashSet con la capacidad inicial indicada. Esta capacidad inicial
no corresponde al nmero de elementos sino al nmero de entradas en la tabla hash,

que es la estructura que facilita la adicin y bsqueda de elementos mediante el


cdigo hash.
HashSet(int, float): Construye un HashSet con una tabla hash de la capacidad inicial
indicada, y que incrementa su tamao cuando se encuentra un porcentaje mayor o
igual al que se recibe en el segundo parmetro.

Ejemplo: Elabore una aplicacin que permita almacenar estudiantes, de acuerdo a la


clase Estudiante definida en el apartado 5.3.2.1. La aplicacin debe permitir verificar la
existencia de un estudiante indicando su cdigo, y si existe, eliminarlo de la coleccin.
import java.util.*;
public class Universidad {
private static HashSet conjuntoEstudiantes = new HashSet( );
public static void adicionarEstudiante(String cdigo, String nombre) {
Estudiante estudiante = new Estudiante(cdigo,nombre);
conjuntoEstudiantes.add(estudiante);
}

public static boolean eliminarEstudiante(string cdigo){


Estudiante temporal=new Estudiante(cdigo);
if (conjuntoEstudiantes.contains(temporal)){
return conjuntoEstudiantes.remove(temporal);
}
return false;
}
public static void main(String args[]) {
adicionarEstudiante("01","Vincent");
adicionarEstudiante("02", "Marie");
adicionarEstudiante("01","Albert");
System.out.println(eliminarEstudiante(02);
System.out.println(elminarEstudiante(05);
}

Al terminar de adicionar al tercer estudiante, quedara en la coleccin


[02-Marie]
[01-Vincent]
Como se puede observar, no se adicion el ltimo estudiante, pues ya exista otro con el
mismo cdigo en el conjunto. Tambin se puede notar que, a diferencia de las listas, los
elementos no tienen una posicin predeterminada en el conjunto, ni estn almacenados
en forma ordenada.
El resultado de las dos eliminaciones sera:
true
false

5.3.2.4 Clase TreeSet


Esta clase, de tipo concreto, tambin hereda de la clase AbstractSet, pero adems
implementa la interfaz SortedSet, lo cual le permite ser una coleccin ordenada.
El nombre de la clase se debe a la estructura de tipo rbol que utiliza internamente para
mantener ordenados los elementos. La explicacin de esta estructura est ms all del
alcance de este libro, pero se puede indicar que su utilizacin hace que sean rpidos los
tiempos de bsqueda de los objetos dentro de la coleccin.

Figura 14 Mtodos definidos en la clase TreeSet

Esta clase tiene varios constructores adems del constructor por defecto, entre los que se
encuentran:
TreeSet(Comparator): Crea un TreeSet que ordena los elementos con ayuda del
objeto comparador que recibe como parmetro. Esto permite modificar la forma de
ordenamiento establecida por defecto (dada por el orden natural de los
elementos).
TreeSet(Collection): Recibe por parmetro una coleccin de cualquier tipo (de la
jerarqua de Collection) y retorna un TreeSet con los elementos ordenados de
acuerdo a su orden natural.

Ejemplo:
Elabore una aplicacin que permita almacenar las revistas, de acuerdo a la definicin de
la clase Revista dada en el apartado 5.3.2.2, de manera que no se almacenen revistas
repetidas (con igual cantidad de pginas), y que queden ordenadas de acuerdo a su
cantidad de pginas, de menor a mayor.
import java.util.*;
public class Revistero {
public static void main(String args[]) {
TreeSet revistasOrdenadas = new TreeSet();
revistasOrdenadas.add(new Revista("Web",50));
revistasOrdenadas.add(new Revista("Caricaturas",40));
revistasOrdenadas.add(new Revista("Inventos",80));
revistasOrdenadas.add(new Revista("Java",50));
revistasOrdenadas.add(new Revista("Literatura",35));
System.out.println(revistasOrdenadas);
}
}

La salida es:
[Literatura-35, Caricaturas-40, Web-50, Inventos-80]
Esta salida nos muestra cmo las revistas quedaron ordenadas por el nmero de pginas,
y adems no se tienen dos revistas con el mismo nmero de pginas.

5.4

Iteradores

Los iteradores son clases a partir de las cuales se crean objetos que permiten recorrer
una coleccin. El recorrido involucra que se vaya pasando uno a uno por los elementos
que contiene la coleccin, sin importar de qu tipo es la estructura interna utilizada para
definirla (arreglo, lista encadena, rbol, tabla hash, etc). En algunos colecciones, el
iterador tambin puede eliminar un elemento de la coleccin.
A continuacin se revisar la interfaz que define a los iteradores.
5.4.1

Interfaz Iterator

Esta interfaz define el comportamiento de un objeto iterador, ofreciendo mtodos que


permiten moverse a travs de los objetos, obtener una referencia a cada objeto e incluso
eliminarlos.

Figura 15 Mtodos definidos en la interfaz Iterator

boolean hasNext(): Retorna true si hay ms elementos por recorrer en la coleccin.


Object next(): Retorna una referencia al siguiente elemento en la coleccin. Al llegar al
final de la coleccin puede lanzar una java.util.NoSuchElementException.
remove(): Elimina el ltimo objeto que fue retornado con la invocacin al mtodo next.
Si se intenta llamar este mtodo sin haber llamado previamente a next se lanzar una
java.lang.IllegalStateException. No todas las colecciones soportan esta operacin.

El dibujo ilustra el comportamiento de un objeto iterador al recorrer una coleccin de tres


objetos (Ver Figura 16).

Figura 16 Uso de un iterator


Se obtiene el iterador:
iterador = coleccin.iterator();

uno

dos

tres

dos

tres

iterador

Se obtiene una referencia al


primer elemento:
ref = iterador.next();

uno

iterador
ref

Se obtiene una referencia al


segundo elemento:
ref = iterador.next();

uno

dos

tres

iterador
ref

Se retira el segundo el
elemento de la coleccin:
iterador.remove();

uno

tres

iterador
ref

dos

Si se intenta llamar de nuevo a remove() se lanzar una IllegalStateException!

Se obtiene una referencia al


siguiente elemento (tres):
ref = iterador.next();

uno

tres

ref

iterador

Todas aquellas colecciones que desean ofrecer el recorrido de los elementos que
contienen usando un iterador, implementan a la interfaz Iterable. En esta interfaz est
definido el encabezado del mtodo iterator(), el cual retorna el objeto iterador. Dado que
la interfaz Collection implementa a Iterable, todas las interfaces que hereden de ella o las
clases que la implementen, debern contar con el mtodo iterator().
Pregunta:
Qu diferencias observa en la forma como se define el mtodo para remover objetos en
la interfaz Collections frente a como lo define la interfaz Iterator?
Ejemplo:
Una constructora tiene varias casas para la venta, que son objetos que se encuentran en
una coleccin. Cuando un cliente desea ver las casas se recorre la coleccin para
mostrarle la informacin de las mismas, y si desea comprarla se retira de la coleccin.
Diagrama de clases simplificado:
Casa
rea
precio
descripcin
Casa()

Constructora

*
mostrarCasas()
adicionarCasa()
retirarCasa()

Cdigo (apartes):
public class Casa {
private double rea;
private double precio;
private String descripcin;
public Casa(double rea, double precio, String descripcin) {
this.rea = rea;
this.precio = precio;
this.descripcin = descripcin;
}
public String toString() {
return (descripcin + " Area: "+rea);
}
}
import java.util.*;
public class Constructora {
private Collection coleccinCasas = new ArrayList( );
public void adicionarCasa(double rea, double precio, String descripcin) {
coleccinCasas.add(new Casa(rea,precio, descripcin));
}

public void mostrarCasas() {


Iterator iterador = coleccinCasas.iterator();
while (iterador.hasNext()) {
Casa casa = (Casa)iterador.next();
System.out.println(casa);
String comprar = Console.readLine("Desea comprar la casa? (S/N)");
if (comprar.equalsIgnoreCase("s")) {
iterador.remove();
}
}
}

Debe tenerse cuidado con las operaciones que retiran o adicionan elementos a la lista
despus de creado el iterador, puesto que los iteradores pueden presentar problemas si
se modifica la coleccin que estn recorriendo. En estos casos se lanza una
ConcurrentModificationException.
Pregunta
Qu sucede si en lugar de la instruccin iterador.remove(), en el cdigo anterior, se
utiliza coleccinCasas.remove(casa)?
5.4.2

Interfaz ListIterator

Esta interfaz define el comportamiento de un iterador especial para las colecciones de tipo
Lista. El tipo de recorrido ofrecido por un objeto de tipo ListIterator permite recorrer la lista
en dos direcciones, hacia adelante o hacia atrs.

Figura 17 Mtodos definidos en la interfaz ListIterator

Adems de los mtodos definidos en Iterator, ListIterator define entre otros:

boolean hasPrevious(): Retorna true si hay un elemento antes de la posicin actual del
iterador.
Object previous(): Retorna el elemento anterior, si lo hay.
add(Object): Adiciona un objeto en la posicin actual del iterador. Si el iterador se
acab de crear se adicionar el elemento al comienzo de la lista. Despus de insertar
el elemento una llamada a previous retornar una referencia al mismo.
set(Object): Reemplaza el ltimo elemento que retorn el iterador (con next o
previous), con el objeto que llega como parmetro.
Los ltimos dos mtodos, que permiten adicionar o modificar un elemento en la coleccin,
resultan ms eficientes que usar los mtodos de List para los mismos propsitos.
Ejemplo:
Se tiene una lista de camiones que son cargados con mercanca para llevar a diferentes
lugares del pas. Cuando llega un nuevo camin, ste se ubica despus del primer
camin en la lista que ya tenga su carga completa.
Diagrama de clases:
Camin
capacidad
cargado

Camiones

*
ingresarCamin()

Cdigo (apartes):
class Camion {
private int capacidad;
private boolean cargado;

public boolean estCargado() {


return cargado;
}
public Camion(int cap, boolean carg) {
capacidad = cap;
cargado = carg;
}

import java.util.*;
public class Camiones {
private List listaCamiones = new LinkedList();
public void ingresarCamin(Camion caminNuevo) {
ListIterator iterador = listaCamiones.listIterator();

5.5

while (iterador.hasNext()) {
Camion camin = (Camion)iterador.next();
if (camin.estCargado()) {
iterador.add(caminNuevo);
break;
}
}

Jerarqua Map

La interfaz Map define otro estilo de colecciones en Java, donde se tienen parejas
clave/valor, llamadas normalmente entradas (entry). La idea es que las claves sean
nicas, y a travs de una clave se puede obtener el valor asociado a ella. Tanto la clave
como el valor deben ser objetos, no tipos bsicos.
Es comn identificar a las colecciones de esta jerarqua como de tipo diccionario. En un
diccionario se tienen palabras nicas, y a cada palabra est asociado su significado.
Haciendo el smil con el diccionario, en una coleccin tipo map tendramos una clave la
palabra en el diccionario --, con su valor asociado el significado de esa palabra --.
Aunque las colecciones de esta jerarqua tambin son grupos de objetos, la forma de
trabajar con ellos es un poco diferente, y por lo tanto la interfaz Map no hereda de
Collection.

Figura 18 Mtodos definidos en la interfaz Map

Algunos de los mtodos definidos en la interfaz Map son:


Object put(Object, Object): Adiciona una entrada al Map (pareja clave/valor). Si ya
exista en el Map la clave que se est adicionando, entonces simplemente se
reemplaza el valor que tena asociado por el nuevo. Retorna el valor anterior asociado
a la clave, o null si no exista previamente en el Map.
Object remove(Object): Retira del Map la pareja clave/valor que corresponde a la
clave dada. Retorna el valor que tena asociado la clave en el Map.
boolean containsKey(Object): Permite determinar si la clave que se pasa como
parmetro existe en el Map.
boolean containsValue(Object): Retorna true si el valor recibido en el parmetro existe
en el Map al menos una vez (los valores pueden repetirse, a diferencia de las claves).
boolean isEmpty(): Indica si el Map no tiene ninguna entrada.
Object get(Object): Este es uno de los mtodos ms tiles de Map, ya que recibe una
clave y retorna el valor asociado, es decir, Elimina las operaciones de bsqueda que
se requieren para otras colecciones!
int size(): Devuelve el tamao del Map (nmero de entradas).
Set keySet(): Retorna una vista de las claves como un conjunto.
Collection values(): Retorna una vista de los valores del Map, como una coleccin.
Set entrySet(): Retorna una vista de las entradas como una coleccin. Los elementos
de esta coleccin son de tipo Map.Entry.
Al igual que en las colecciones, no todas las implementaciones de Map soportan todas las
operaciones definidas en la interfaz, en cuyo caso se lanzar una
UnsupportedOperationException.
Aunque los Maps no tienen un mecanismo para recorrerlos, como el iterador de las
colecciones, s es posible obtener el conjunto de entradas, el conjunto de claves o la
coleccin de valores, y cada uno de stos se puede recorrer con iteradores.
5.5.1

Interfaz SortedMap

La interfaz SortedMap es similar a la interfaz SortedSet, en el sentido de que permite


ordenar los elementos, pero en este caso se ordenan de acuerdo a las claves de manera
ascendente.
El orden de los elementos en un SortedMap est dado por el orden natural de los objetos
clave, o por el orden que determine un objeto comparador que se pase como parmetro a
una de las clases que implementen SortedMap.

Figura 19 Mtodos definidos en la interfaz SortedMap

Algunos de los mtodos que define esta interfaz son:


Comparator comparator(): Retorna el objeto comparador usado para ordenar, si lo
hay.
Object firstKey(): Retorna la primera clave del Map, es decir, la menor.
Object lastKey(): Devuelve la ltima clave del Map.
5.5.2

Interfaz Map.Entry

Esta interfaz define mtodos que permiten acceder a la informacin de las parejas
clave/valor almacenadas en un Map.

Object getKey(): Retorna el objeto clave.


Object getValue(): Retorna el objeto valor.
Object setValue(Object): Permite modificar el valor actual de la entrada,
reemplazndolo con el que se recibe como parmetro. Retorna el valor anterior.

5.5.3

Clase AbstractMap

Esta clase, de tipo abstracto, implementa a la interfaz Map, y define cierta funcionalidad
bsica para las clases que hereden de ella. Es especialmente til cuando se requiere
elaborar una coleccin propia con el comportamiento de un diccionario, en cuyo el

diccionario hereda de AbstractMap, evitando el tener que implementar directamente a la


interfaz Map.

Figura 20 Mtodos definidos en la clase AbstractMap

Pregunta:
Cules son los mtodos cuyo cdigo ya fue elaborado en la clase AbstracMap?
5.5.4

Clase TreeMap

Esta clase, hija de AbstractMap, y que implementa la interfaz SortedMap, permite tener
parejas clave/valor ordenadas.
Al igual que la clase TreeSet, permite ordenamientos dados por el orden natural de los
objetos, o dados por un objeto comparador. Este ltimo ordenamiento se obtiene cuando
se utiliza el constructor TreeMap(Comparator).
Los constructores de esta clase son:

TreeMap(): Constructor por defecto. Almacenar los elementos de acuerdo al orden


natural definido en los objetos clave.

TreeMap(Comparator): Crea un TreeMap en donde los elementos se ordenarn de


acuerdo al orden parcial de sus claves, definido en el objeto comparador que se pasa
por parmetro
TreeMap(Map): Crea un TreeMap que contiene los elementos del Map que se pasa
por parmetro. Los elementos se almacenarn de acuerdo al orden natural de las
claves, por lo que la clase que define al objet clave debe implementer la interfaz
Comparable.
TreeMap(SortedMap):Crea un TreeMap que contiene los elementos del SortedMap,
siguiendo el mismo criterio de ordenamiento utilizado en el SortedMap.

Ejemplo
En este ejemplo se definen dos clases: Cancin y Compositor. De ambas clases se crean
varios objetos y se adicionan en un TreeMap. La clave para encontrar cada compositor
es la cancin, de manera que se almacenarn por orden alfabtico de acuerdo al ttulo de
la cancin. Se define adicionalmente un mtodo que permite mostrar las canciones
registradas en orden alfabtico.
public class Cancin implements Comparable{
private String ttulo;
private double duracin;

public Cancin(String elTtulo, String laDuracin){


ttulo=elTtulo;
duracin=laDuracin;
}
public Cancin(String elTtulo){
ttulo=elTtulo;
}
public int compareTo(object obj){
if (obj instanceof Cancin){
Cancin cancin=(Cancin) obj;
return ttulo.compareTo(cancin.getTtulo());
}
return 1;
}

public class Compositor{


private String nombre;
private String docIdentidad;
private String direccin;
private String telfono;

contina

continuacin

public Compositor(String elNombre,String elDoc, String laDireccin, String elTel){


nombre=elNombre;
docIdentidad=elDoc;
direccin=laDireccin;
telfono=elTelfono;
}
.

import java.util.*;
public class Disquera{
private TreeMap canciones=new TreeMap();

5.5.5

public agregar(Cancin cancin, Compositor compositor){


canciones.put(cancin,compositor);
}
public void mostrarCanciones(){
Set clavesCancin=canciones.keySet();
Iterator iterador=clavesCancin.iterator();
while (iterador.hasNext()){
Cancin cancin=(Cancin) clavesCancin.next();
System.out.println(Nombre: +cancin.getNombre()+\n);
}
}

Clase HashMap

Esta clase, hija de AbstractMap, permite tener parejas clave/valor organizadas usando el
cdigo hash del objeto clave, por lo que es importante que los objetos que sean claves
redefinan el mtodo hashCode. Cada vez que una pareja se va a adicionar o buscar en el
HashMap, el cdigo hash de la clave es convertido a una posicin dentro de la tabla, lo
cual hace muy eficientes ambas operaciones.
Algunos constructores de esta clase son:

HashMap(): Crea un HashMap con una capacidad inicial por defecto de 16.
HashMap(int): Crea un HashMap con la capacidad inicial especificada en el parmetro
HashMap(Map):Crea un HashMap a partir del Map recibido por parmetro.

El comportamiento de esta clase es similar al que se indic para HashSet. Debe tenerse
en cuenta que las entradas almacenadas en el HashMap no quedan ordenadas.
Ejemplo:
Se han definido las clases Placa y Vehculo para el sistema de trnsito de la ciudad.
Cada placa guarda la informacin de su identificacin, fecha y ciudad de expedicin, y de
cada vehculo se almacena la informacin de su modelo, color, marca y propietario. En el

siguiente cdigo se tienen parejas placa,vehculo en un HashMap, indicando la relacin


de la placa asignada a cada vehculo, se obtiene la informacin de un vehculo a partir de
su placa y se recorren las entradas para mostrar la informacin de la placa y el modelo de
cada vehculo registrado.
import java.util.*;
public class Placa{
private String identificacin;
private String ciudad;
private Date fecha;
public Placa(String id,String laCiudad, Date laFecha){
identificacin=id;
ciudad=laCiudad;
fecha=laFecha;
}
public Placa(String id){
identificacin=id;
}

..
}

public int hashCode(){


return identificacin.hashCode();
}
public boolean equals(Object obj){
if (obj instanceof Placa){
Placa nueva=(Placa) obj;
return identificacin.equals(nueva.getPlaca());
}
return false;
}

public class Vehiculo {


private String modelo;
private String color;
private String marca;
private String propietario;
public Vehiculo(String marca, String color, String modelo, String propietario){
this.marca = marca;
this.color = color;
this.modelo = modelo;
this.propietario=propietario;
}
public String getColor() {
return color;
}
}

import java.util.*;
public class Trnsito {
private HashMap autos = new HashMap();
public Vehiculo buscar(Placa placa){
Vehiculo auto = (Vehiculo)autos.get(placa);
return auto;
}
.

5.6

public void mostrarVehiculos(){


Set conjunto = autos.entrySet();
Iterator iterador = conjunto.iterator();
while (iterador.hasNext()) {
Map.Entry entrada = (Map.Entry)iterador.next();
Placa placa = (Placa)entrada.getKey();
Vehiculo carro = (Vehiculo)entrada.getValue();
System.out.println(placa.getIdentificacin() +"-"+carro.getModelo());
}
}

Otros elementos

En el marco de trabajo de colecciones existe una clase especial llamada Collections. Esta
clase contiene nicamente mtodos estticos, que permiten realizar diversas operaciones
con las colecciones. Algunos de estos mtodos son:

int binarySearch(List, Object): Busca el objeto dado en la lista, la cual debe estar
ordenada de manera ascendente. Retorna la posicin donde se encuentra el objeto o
1 si no se encuentra.
void reverse(List): Invierte el orden de los elementos de la lista.
sort(List): Ordena los elementos de la lista, de acuerdo con su orden natural.
sort(List, Comparator): Ordena los elementos de la lista, de acuerdo con el orden dado
por el comparador.
Object min(Collection): Retorna el menor elemento de la coleccin, segn el orden
natural de los objetos.
Object max(Collection): Retorna el mayor elemento en la coleccin, de acuerdo con su
orden natural.

Ejercicios

Complemente los ejemplos presentados en este captulo, definiendo para cada uno el
tipo de coleccin que se puede utilizar.

En una gran biblioteca de la ciudad han decidido facilitar las bsquedas de los
diferentes recursos con los que cuenta, y le han pedido que modele esta situacin
(utilizando colecciones) y realice el programa en Java, teniendo en cuenta:
- Todos los recursos (libros y revistas) tienen un nombre y un nmero que los
identifica. Los libros tienen, adems, el nombre de su autor o autores (pueden ser
varios) y la editorial. Las revistas tienen la fecha de publicacin y el nombre de
todos los artculos que contienen, indicando para cada uno su autor.
- Todos los recursos estn organizados en estantes, y es importante saber el
nmero del estante y la posicin dentro del mismo que ocupa cada recurso.
- En general la forma de buscar todos los recursos es a travs de su nombre, por lo
que le han pedido que se pueda realizar esta bsqueda rpidamente.
- Cada vez que se consulta una revista deben desplegarse todos los artculos que
tiene.

Para el ejercicio anterior incluya una nueva opcin que permita realizar bsquedas por
autor.

En una empresa con muchos empleados se deben generar reportes peridicos donde
se muestre la informacin de todos ellos. Estos reportes deben estar ordenados
alfabticamente. Determine el tipo de coleccin que se puede utilizar en este caso y
elabore el programa correspondiente.