Especificación y Desarrollo de Sistemas de Software. Curso 2018/2019. Práctica 2.
COLECCIONES EN JAVA
El marco de colecciones (Collection Framework) de Java contiene una serie de
interfaces y clases que permiten almacenar y organizar objetos de una forma cómoda y
sencilla y con un acceso eficiente. La mayor parte de estas clases las encontramos en el
paquete [Link], y entre otras cosas nos van a permitir trabajar con conjuntos, listas
y aplicaciones.
El marco de colecciones de Java está formado por:
interfaces que nos dan los métodos para todas las operaciones comunes;
implementaciones de los interfaces (clases);
algoritmos para realizar determinadas operaciones habituales sobre colecciones,
como ordenaciones o búsquedas;
iteradores que nos permiten recorrer las colecciones.
Todos los interfaces y clases del marco de colecciones son genéricas, aunque
con objeto de mantener la compatibilidad con versiones anteriores de Java estos
interfaces y clases genéricos conviven con versiones no genéricas de los mismos. Si no
indicamos el parámetro de tipo, se supondrá que estamos trabajando con
colecciones/aplicaciones sobre la clase Object, con lo que tendremos que hacer las
coerciones necesarias. Más información:
[Link]
LOS INTERFACES BÁSICOS
A continuación, mostramos un diagrama UML con los interfaces básicos del
marco de colecciones y las relaciones entre ellos. Se distinguen dos jerarquías
diferentes, los interfaces que heredan de Collection<T> y los que lo hacen de
Map<K,V> (que llamaremos tablas o aplicaciones).
1
Especificación y Desarrollo de Sistemas de Software. Curso 2018/2019. Práctica 2.
Veamos las características y métodos principales de algunos de ellos:
Collection<T>
Es el interfaz más general; define las operaciones que implementan todas las
clases que representan colecciones de objetos. Podemos encontrarnos una gran variedad
de colecciones de objetos, con características distintas: unas colecciones serán
ordenadas y otras no, unas permitirán elementos repetidos y otras no, etc; pero todas
ellas van a disponer de una serie de operaciones comunes, que son las que quedan
recogidas en el interfaz genérico Collection<T>.
Sus métodos más importantes son (mirar JavaDoc):
int size(): devuelve el número de objetos almacenados en la colección
boolean isEmpty(): dice si la colección está vacía
boolean add(T elem): añade un elemento a la colección
boolean addAll(Collection<? extends T> c): añade un grupo de
objetos (otra colección)
void clear(): vacía la colección
boolean contains(Object elem): chequea si un elemento se encuentra
dentro de la colección
boolean remove(Object elem): quita un elemento de la colección
Iterator<T> iterator(): devuelve un [Link] que permite
recorrer todos los elementos de la colección
T[] toArray(T[]a): devuelve un array con los elementos de la colección
List<T>
Sirve como interfaz para clases que representen listas de datos o vectores cuya
longitud es variable. Sus elementos son accesibles por medio de un índice, y tiene los
métodos de colección y algunos más, entre ellos:
void add(int i, T elem): añade un elemento en una posición determinada
T get(int i): devuelve el elemento que ocupa una posición determinada
T remove(int i): elimina un elemento que ocupa una posición determinada
int indexOf(Object elem): devuelve el índice de la primera aparición del
elemento en la lista (o –1 si no está)
T set(int i, T elem): cambia el elemento que ocupa una posición
determinada por otro elemento
Al añadir un objeto con el método add(T elem) de Collection<T>, el
elemento se añade al final. Al eliminar un objeto con remove(Object elem), todos los
demás se desplazan para no dejar huecos.
Los objetos List<T> más habituales son LinkedList<T> y ArrayList<T>.
Sus métodos y características principales se pueden encontrar en la documentación de
Java.
2
Especificación y Desarrollo de Sistemas de Software. Curso 2018/2019. Práctica 2.
Set<T>
Sirve como interfaz para clases que representen conjuntos de datos donde no
puede haber elementos repetidos, y cuyos elementos no se almacenan necesariamente
siguiendo un orden particular. Por lo tanto sus elementos no son accesibles por un
índice.
Tiene los mismos métodos que Collection<T> (no añade ningún método
nuevo). Las clases Set<T> más habituales son HashSet<T> y TreeSet<T> (ver
JavaDoc).
Map<K,V>
Define las operaciones que implementarán las clases que representan
aplicaciones de claves a valores, es decir, representa lo que se denomina tablas de datos.
Un mapa se compone de un conjunto de “entradas”, compuestas a su vez de:
una clave, que sirve para recuperar el elemento;
y un valor.
Una aplicación no puede contener claves duplicadas, y cada clave se puede emparejar
con, a lo sumo, un valor.
Los métodos más importantes de este interfaz son (mirar JavaDoc):
int size(): devuelve el número de objetos almacenados
boolean isEmpty(): dice si el Map está vacío
void clear(): vacía la estructura
V put(K clave, V valor): almacena un objeto en el mapa con una clave
determinada. Si la clave ya está almacenada se sustituye el objeto asociado por el
nuevo
V get(K clave): permite recuperar un elemento a partir de su clave
V remove(Object clave): elimina un objeto de clave determinada
boolean containsKey(Object clave): devuelve true si hay algún objeto
almacenado con esa clave
boolean containsValue(Object valor): devuelve true si el Map contiene
ese objeto
Set<K> keySet(): devuelve un conjunto con el conjunto de claves del Map
Collection<V> values(): devuelve el conjunto de valores almacenados en
el Map
Una aplicación no es una colección; por eso Map<K,V> no hereda de
Collection<T>. Sin embargo, a partir de un Map podremos obtener colecciones
correspondientes al conjunto de claves, al conjunto de valores y al conjunto de pares
<clave, valor>. Los Maps se implementan como tablas Hash; las clases Map<K,V> más
habituales son HashMap<K,V> y Hashtable<K,V>.
Ejemplo:
Map<String,Persona> agenda=new Hashtable<String,Persona>();
Persona p=new Persona(“Pepe”),
[Link](“16444444E”,p);
[Link](“55555555L”, new Persona(“Luis”);
3
Especificación y Desarrollo de Sistemas de Software. Curso 2018/2019. Práctica 2.
[Link](“Hay alguien con DNI 55555555L?”
+ [Link](“55555555L”)); //true
Persona pr=[Link](“16444444E”); //Debe ser Pepe
[Link](“¿Es Pepe?” + [Link](p)); // true
[Link](“El tamaño de la agenda es ”+[Link]());
IMPLEMENTACIONES DE LOS INTERFACES BÁSICOS
El paquete [Link] proporciona implementaciones de los interfaces genéricos
Collection, List, Set, Deque y Map (entre otros). En la siguiente figura se muestran
algunas de estas clases y las relaciones entre ellas. Recordar que no hay relación entre
Collection<T> y Map<K,V>. Además, podemos observar que no hay una
implementación directa de la interfaz Collection<T>.
En nuestro caso será especialmente conveniente conocer el funcionamiento de
las clases HashMap<K,V> o Hashtable<K,V> (ver JavaDoc).
ESTRUCTURA FOR PARA RECORRER COLECCIONES DIRECTAMENTE
(for each)
A partir de Java 1.5 hay una manera simplificada de recorrer una Collection
mediante un nuevo uso del keyword for (siempre que no se quiera modificar la propia
colección):
Collection<String> col= ....;
for (String s: col)
[Link](s);
Internamente este código lo que hace es obtener un iterador pero queda mucho
más elegante y legible de esta manera.