Académique Documents
Professionnel Documents
Culture Documents
Versin: 0.0.3
Tema 4. Colecciones I
Autor: Miguel Toro Bonilla
Revisin: Jos C. Riquelme
Adaptacin a FP: Carlos A. Garca Vallejo
Tiempo estimado: 2 horas
1.
Introduccin ................................................................................................................................................ 1
2.
La interfaz Collection................................................................................................................................... 1
3.
4.
5.
El tipo SortedSet.......................................................................................................................................... 7
6.
7.
Ejercicios.................................................................................................................................................... 14
1. Introduccin
En el tema 2 se han visto las listas (interfaz List). Como se ha explicado, son secuencias de elementos que se
pueden indexar, de modo que el primer elemento es el 0, el siguiente el 1, etc. hasta llegar al ltimo
elemento, que ocupa la posicin size() 1 (recordemos que size() es una operacin que devuelve el nmero
de elementos de la lista.
La adecuada utilizacin de tipos de datos agregados predefinidos en la API de Java, como el tipo List,
simplifica mucho el desarrollo de programas correctos en Java y tiene muchas otras ventajas:
En este captulo vamos a ver las colecciones, modeladas mediante la interfaz Collection y dos de las
interfaces que heredan de ella: List, que modela las listas, y Set, que modela los conjuntos. Finalizaremos
viendo la clase de utilidad Collections, que permite realizar operaciones sobre las colecciones.
2. La interfaz Collection
La interfaz Collection, que define un tipo que podemos denominar Coleccin, est definida en el paquete
java.util. Una coleccin es un tipo muy general, que agrupa objetos (elementos) de un mismo tipo; su
Introduccin a la Programacin
comportamiento especfico viene determinado por sus subinterfaces, que pueden admitir elementos
duplicados o no, y cuyos elementos pueden estar ordenados o no segn determinado criterio. No existe una
implementacin especfica de la interfaz Collection; s la tienen sus subinterfaces. El tipo Collection se utiliza
para declarar variables o parmetros donde se quiere la mxima generalidad posible, esto es, que puedan
ser utilizados tanto por listas como por conjuntos (Collection tiene otros subtipos que se tratarn ms
adelante).
La interfaz Collection es genrica, por lo que hablaremos de Collection<E> (como se vio en el tema 2). Hereda
de Iterable<E>, lo que implica que las colecciones, as como las listas y los conjuntos, subtipos suyos, son
iterables y se puede utilizar con ellas el for extendido.
La jerarqua de interfaces se representa en la Figura 1.
Las operaciones del tipo Collection se especifican a continuacin1. En general, el valor devuelto por los
mtodos add, addAll, remove, removeAll y retainAll ser true si la coleccin queda modificada por la
aplicacin del mtodo y false en caso contrario.
boolean add(E e)
Aade un elemento a la coleccin, devuelve false si no se aade.
void
clear()
Borra todos los elementos de la coleccin.
boolean contains(Object o)
Devuelve true si o est en la coleccin invocante.
boolean containsAll(Collection<?> c)
Devuelve true si la coleccin que invoca contiene todos los elementos de c.
boolean isEmpty()
1
4. Colecciones I
boolean remove(Object o)
Borra el objeto o de la coleccin que invoca; si no estuviera se devuelve false.
boolean removeAll(Collection<?> c)
Borra todos los objetos de la coleccin que invoca que estn en c. Devuelve true si la coleccin original se
modifica.
boolean retainAll(Collection<?> c)
En la coleccin que invoca slo se quedarn aquellos objetos que estn en c. Por tanto, es la interseccin
entre ambas colecciones. Devuelve true si la coleccin original se modifica.
int
size()
Devuelve el nmero de elementos.
T[]
toArray(T[] a)
Devuelve un array con la coleccin.
3. El tipo List
Conceptualmente, las listas representan colecciones de elementos en los que importa cul es el primero, el
segundo, etc. Cada elemento est referenciado mediante un ndice; el ndice del primer elemento es el 0. Las
listas pueden contener elementos duplicados.
Desde el punto de vista de la API de Java, las listas son un subtipo de Collection: la interfaz List hereda de la
interfaz Collection. Por tanto, tienen todas las operaciones vistas en el apartado anterior, aunque debemos
prestar atencin a la semntica de algunas operaciones: La operacin addAll aade los elementos de la lista
que se pasa al final de la lista sobre la que se invoca. Si en la lista sobre la que se invoca hay elementos
duplicados, la operacin removeAll elimina de esta todas las instancias de los elementos que aparecen en la
lista que se pasa. De manera anloga se comporta retainAll: si en la lista sobre la que se invoca un elemento
aparece n veces, y este aparece en la lista que se pasa (independientemente del nmero de veces que
aparezca), en la lista resultado permanecern las n apariciones del elemento. Todo esto se ilustra en el
Ejemplo 1:
Ejemplo 1. Ejemplo de comportamiento de removeAll y retainAll
Introduccin a la Programacin
l1.add("C");
l2.add("B");
l2.add("B");
l2.removeAll(l1);
mostrar("l2 despus de l2.removeAll(l1): ", l2);
l1.clear();
l2.clear();
l1.add("A");
l1.add("B");
l1.add("C");
l2.add("B");
l2.add("B");
l2.retainAll(l1);
mostrar("l2 despus de l2.retainAll(l1): ", l2);
La interfaz List2 aporta varias operaciones especficas, que no aparecen en Collection; en las operaciones que
tienen ndice, si no se cumple la restriccin sobre este se eleva la excepcin IndexOutOfBoundsException.
void
get(int index)
Devuelve el elemento de la lista en la posicin especificada. Los valores lcitos para index son 0
index < size().
int
indexOf(Object o)
Devuelve el ndice donde se encuentra por primera vez el elemento o (si no est devuelve
int
-1).
lastIndexOf(Object o)
Devuelve el ndice donde se encuentra por ltima vez el elemento o (si no estuviera devuelve
-1).
remove(int index)
Borra el elemento de la posicin especificada. Los valores lcitos para index son 0
size().
index <
4. Colecciones I
La operacin subList devuelve una vista de la lista original. Esto quiere decir que las operaciones que se
realicen sobre la sublista se vern reflejadas en la lista original y viceversa. Hay que prestar atencin al hecho
de que si se produce un cambio estructural que afecte al tamao de la lista original, pueden ocurrir
comportamientos extraos, en particular la elevacin de una excepcin cuando se utiliza la sublista. El
comportamiento de subList se puede ver en los Ejemplos 2 y 3.
Ejemplo 2. Ejemplo de uso de subList
Si se ejecuta el cdigo:
List<String> ls = new LinkedList<String>();
ls.add("A");
ls.add("B");
ls.add("C");
ls.add("D");
ls.add("E");
List<String> subLs = ls.subList(1, 4);
mostrar("Sublista: ", subLs);
ls.set(2, "F");
mostrar("Sublista despus de modificar el elemento 2 de la lista: ", subLs);
subLs.remove(1);
mostrar("Sublista despus de eliminar el elemento 1: ", subLs);
mostrar("Lista original despus de modificar la sublista: ", ls);
subLs.add("X");
subLs.add("Y"); // aade "X" e "Y" al final de la sublista
mostrar("Sublista despus de aadirle X e Y: ", subLs);
mostrar("Lista despus de la modificacin de la sublista: ", ls);
ls.remove(0);
mostrar("Lista despus de eliminar el primer elemento: ", ls);
Si se ejectuta el cdigo:
List<String> ls = new LinkedList<String>();
ls.add("A");
ls.add("B");
ls.add("C");
ls.add("D");
ls.add("E");
List<String> subLs = ls.subList(1, 4);
mostrar("Sublista: ", subLs);
ls.remove(2);
Introduccin a la Programacin
Las implementaciones de las listas son ArrayList y LinkedList3. La eleccin de una u otra implementacin
depender del tipo de operaciones que realicemos sobre ellas. Si se va a acceder preferentemente a los
elementos mediante ndice o a realizar bsquedas, debe usarse ArrayList. Si preferentemente se van a
realizar operaciones de insercin o borrado al principio o al final debe usarse LinkedList. Esto se estudiar
con ms detalle en la asignatura ADDA de segundo curso. Las dos clases tienen dos constructores cada una:
uno sin argumentos, que construye una lista vaca y otro que recibe una Collection y construye una lista con
los elementos de la coleccin, en el orden en el que un for extendido devolvera sus elementos.
4. El tipo Set
El tipo Set se corresponde con el concepto matemtico de conjunto: un agregado de elementos en el que no
hay orden (no se puede decir cul es el primero, el segundo, el tercero, etc.) y donde no puede haber
elementos repetidos.
Dados dos conjuntos (de Integer) a y b:
a = {1, 2, 3, 4} b = {4, 5, 6}
recordemos que:
a b = {1,2,3,4,5,6}
a b = {1,2,3}
a b = {4}
3
2
a
5
b
La interfaz Set4 no aporta ningn mtodo extra a los que ya tiene Collection; por tanto, sus mtodos son los
de Collection y solo estos. Las operaciones addAll, retainAll y removeAll se pueden identificar con la unin,
interseccin y diferencia de conjuntos, respectivamente; la operacin contains equivale a la pertenencia en
conjuntos (); la operacin containsAll se corresponde con la de subconjunto ().
4. Colecciones I
La implementacin ms habitual del tipo Set es la clase HashSet5. Tiene dos constructores: uno vaco, que
construye un conjunto vaco, y otro que recibe una coleccin y construye un conjunto con los elementos de
la coleccin (sin duplicados).
El for extendido aplicado a un conjunto devuelve todos sus elementos en un orden que no es predecible. Hay
una implementacin, LinkedHashSet, en la que el for extendido devuelve los elementos en el orden en el que
fueron insertados en el conjunto.
Ejemplo 4. Orden en el que se itera sobre los elementos de un Set
Si se ejecuta el cdigo
Set<Character> s = new HashSet<Character>();
s.add('A');
s.add('B');
s.add('P');
s.add('Q');
mostrar(s);
s = new LinkedHashSet<Character>();
s.add('A');
s.add('B');
s.add('P');
s.add('Q');
mostrar(s);
Se obtiene la salida
[P, A, Q, B]
[A, B, P, Q]
5. El tipo SortedSet
El tipo SortedSet es un subtipo de los conjuntos (por tanto los elementos no estn indexados y no puede
haber elementos repetidos), en el que existe una relacin de orden entre los elementos que permite decir
cul va antes y cul despus. Para simplificar hablaremos de menores o mayores, entendiendo que significa
va antes o despus, segn el criterio de ordenacin. A las operaciones de Set (a su vez las de Collection)
aade estas otras:
SortedSet<E>
headSet(E toElement)
Devuelve una vista de los elementos del SortedSet sobre el que se invoca con
los elementos que son menores (van antes segn el criterio de ordenacin) que
toElement, excluido.
SortedSet<E>
tailSet(E fromElement)
Devuelve una vista con los elementos que son mayores que
incluido este.
Ms informacin en http://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html.
fromElement,
Introduccin a la Programacin
SortedSet<E>
first()
Devuelve el primer elemento. Si el SortedSet est vaco eleva la excepcin
NoSuchElementException.
last()
Devuelve el ltimo elemento. Si el SortedSet est vaco eleva la excepcin
NoSuchElementException.
Si se ejecuta el cdigo
SortedSet<Character> ss = new TreeSet<Character>();
ss.add('X'); ss.add('C'); ss.add('F');
ss.add('P'); ss.add('R'); ss.add('Q');
mostrar("ss = " + ss);
SortedSet<Character> inicio = ss.headSet('G');
SortedSet<Character> medio = ss.subSet('G', 'R');
SortedSet<Character> fin = ss.tailSet('Q');
mostrar("headSet('G') = " + inicio);
mostrar("subSet('G', 'R') = " + medio);
mostrar("tailSet('Q') = " + fin);
Se obtiene la salida
ss = [C, F, P, Q, R, X]
headSet('G') = [C, F]
subSet('G', 'R') = [P, Q]
tailSet('Q') = [Q, R, X]
Las operaciones sobre rangos devuelven vistas del conjunto ordenado original, de modo que si se acta
sobre el original se modifica la vista y viceversa.
Ejemplo 6. Ejemplo que ilustra que los rangos son vistas del conjunto ordenado original
4. Colecciones I
ss = [C, F, P, Q, R, X]
tailSet('Q') tras add('S') =
ss tras add('S') = [C, F, P,
ss tras add('D') = [C, D, F,
headSet('G') tras add('D') =
[Q, R, S, X]
Q, R, S, X]
P, Q, R, S, X]
[C, D, F]
En las vistas devueltas por las operaciones con rangos solo se puede actuar sobre el rango delimitado por
fromElement y toElement.
Ejemplo 7. En las vistas de los SortedSet no se puede actuar fuera del rango
Se obtiene
java.lang.IllegalArgumentException: key out of range
La implementacin de los conjuntos ordenados es la clase TreeSet6. Esta clase tiene cuatro constructores:
Un constructor vaco, que crea un conjunto ordenado vaco donde los elementos se ordenaran
segn su orden natural (los elementos tienen que implementar Comparable).
Un constructor con un argumento de tipo Collection, que crea un conjunto ordenado con los
elementos de la coleccin ordenados segn su orden natural (los elementos de la coleccin tienen
que implementar Comparable).
Un constructor que recibe un Comparator, que crea un conjunto ordenado vaco cuyos elementos se
ordenaran segn el orden inducido por el Comparator.
Un constructor que recibe un SortedSet, que crea un conjunto ordenado con los mismos elementos
que el que recibe como argumento y usando su mismo orden.
El for extendido sobre los elementos de un SortedSet los devuelve en el orden que tienen inducido.
Ejemplo 8. Orden en el que itera el for extendido sobre los elementos de un SortedSet
El cdigo
SortedSet<Character> ss = new TreeSet<Character>();
ss.add('X');
ss.add('C');
ss.add('F');
ss.add('P');
ss.add('R');
ss.add('Q');
for (Character ch : ss) {
mostrar(ch);
}
10
Introduccin a la Programacin
C
F
P
Q
R
X
Hay que hacer una observacin sobre el uso de los conjuntos ordenados el que caso en el que tenga el orden
inducido por un Comparator. El orden natural de los elementos tiene que ser compatible con la igualdad,
esto es, para dos elementos a y b a.equals(b) == true, si y solo si a.compareTo(b) == 0. Sin embargo con un
orden alternativo creado con un Comparator, compare(a, b) == 0 no implica necesariamente que a.equals(b)
== true. Sin embargo, las implementaciones de los conjuntos ordenados insertan un elemento nuevo solo si
su comparacin con los existentes no es cero para ninguno de ellos. Si se est usando el orden natural, esto
equivale a que no hay un elemento igual que el nuevo, lo que coincide con la idea que tenemos de la
insercin en conjuntos no ordenados; sin embargo, si se usa un orden alternativo puede que haya dos
elementos distintos cuya comparacin de 0, por lo que el segundo no se insertara. Si este es el
comportamiento deseado, no habra que hacer nada, pero si no lo es, la solucin ms sencilla es modificar la
comparacin entre elemento introduciendo un desempate por el orden natural en caso de que haya
empate por el orden alternativo.
Supongamos que tenemos un orden natural en la clase PersonaImpl que es apellidos, nombre, dni (con el
que ser compatible equals). Supongamos tambin que tenemos los comparadores:
public class ComparadorPersonaEdad1 implements Comparator<Persona> {
public int compare(Persona p1, Persona p2) {
int cmp = p1.getEdad().compareTo(p2.getEdad());
return cmp;
}
}
y
public class ComparadorPersonaEdad2 implements Comparator<Persona> {
public int compare(Persona p1, Persona p2) {
int cmp = p1.getEdad().compareTo(p2.getEdad());
if (cmp == 0) {
cmp = p1.compareTo(p2);
}
return cmp;
}
}
Supongamos tambin, para simplificar el ejemplo, que tenemos en PersonaImpl un constructor que
recibe el DNI, el nombre, los apellidos y la edad. Si se ejecuta el siguiente cdigo:
Persona p1 = new PersonaImpl("31122334-W", "Antonio", "Garca Maratn", 22);
Persona p2 = new PersonaImpl("34423123-V", "Mara", "Prez Pia", 20);
Persona p3 = new PersonaImpl("38962334-W", "Eva", "Garca Morn", 22);
Persona p4 = new PersonaImpl("34435723-V", "Eugenia", "Gmez Titos", 20);
SortedSet<Persona> ss = new TreeSet<Persona>();
ss.add(p1); ss.add(p2); ss.add(p3); ss.add(p4);
mostrar("ss con el orden natural (apellidos, nombre, dni):\n", ss);
Se obtiene la salida
ss con el orden natural (apellidos, nombre, dni):
4. Colecciones I
Si a continuacin se ejecuta
ss = new TreeSet<Persona>(new ComparadorPersonaEdad1());
ss.add(p1); ss.add(p2); ss.add(p3); ss.add(p4);
mostrar("ss con el orden por edad sin desempate:\n", ss);
Se obtiene la salida
ss con el orden por edad sin desemapate:
[Prez Pia, Mara (34423123-V), Garca Maratn, Antonio (31122334-W)]
Vemos que se han perdido dos personas, que tenan 20 y 22 aos, como las dos que aparecen.
Finalmente, si se ejecuta
ss = new TreeSet<Persona>(new ComparadorPersonaEdad2());
ss.add(p1); ss.add(p2); ss.add(p3); ss.add(p4);
mostrar("ss con el orden por edad con desempate:\n", ss);
Se obtiene la salida
ss con el orden por edad con desempate:
[Gmez Titos, Eugenia (34435723-V), Prez Pia, Mara (34423123-V), Garca
Maratn, Antonio (31122334-W), Garca Morn, Eva (38962334-W)]
donde estn todas las personas, estn en orden de edad y dentro de los de la misma edad, en orden
alfabtico de apellidos, nombre.
binarySearch(List<?
extends
super T>> list, T key)
Devuelve la posicin del objeto
Comparable<?
natural, o -1 si no lo encuentra.
binarySearch(List<? extends
Comparator<? super T> c)
Devuelve la posicin del objeto
11
12
Introduccin a la Programacin
c, o -1 si no lo encuentra.
static <T> void
static boolean
static void
static int
l por o.
static int
o en la coleccin coll.
indexOfSubList(List<?> source,
List<?> target)
Devuelve la primera posicin de la primera ocurrencia de
target
static int
lastIndexOfSubList(List<?> source,
List<?> target)
Devuelve la primera posicin de la ltima ocurrencia de
target dentro
static
<T max(Collection<? extends T> coll)
extends Object & Comparable Devuelve el elemento mximo de la coleccin coll segn el orden
<? super T>> T
natural de sus elementos.
static <T> T
por el Comparator c.
static <T> T
por el Comparator c.
static void
reverse(List<?> list)
Invierte los elementos de la lista
list.
4. Colecciones I
static void
static
<T
extends sort(List<T> list)
Comparable<?
super
T>>
Ordena la lista segn el orden natural del tipo.
void
static <T> void
Si se ejecuta el cdigo
List<String> l = new LinkedList<String>();
l.add("R");
l.add("T");
l.add("B");
l.add("A");
l.add("M");
mostrar(l);
Collections.reverse(l);
mostrar(l);
Collections.sort(l);
mostrar(l);
mostrar(Collections.frequency(l, "B"));
Collections.fill(l, "X");
mostrar(l);
La salida ser:
[R,
[M,
[A,
1
[X,
T, B, A, M]
A, B, T, R]
B, M, R, T]
X, X, X, X]
13
14
Introduccin a la Programacin
7. Ejercicios
Ejercicio 1
Escriba la clase TestEjercicio1 con un mtodo main que
a) Cree dos conjuntos vacos de Integer, aada al primero 7, 3, 9, 1, 5, 3 y al segundo 1, 2, 3, 4 y los
muestre por pantalla.
b) Muestre el cardinal de cada uno de los conjuntos.
c) Pregunte si uno de los conjuntos contiene un entero dado que est y uno que no est.
d) Aada un entero al primer conjunto, compruebe el valor devuelto por la operacin dependiendo de
si el entero estaba ya en el conjunto o no y muestre el conjunto resultante.
e) Elimine un entero de uno de los conjuntos. Muestre el resultado.
f) Calcule la unin, la interseccin y la diferencia de los conjuntos y muestre los resultados.
Ejercicio 2
Escriba la clase TestEjercicio2 con un mtodo main que
a) Cree dos listas vacas de Character, aada a la primera S, E, M, A, N, A y a la segunda R, A,
M, O y las muestre por pantalla.
b) Muestre el cardinal de cada una de las listas.
c) Pregunte si una de las listas contiene una letra dada.
d) Pregunte en qu posicin est una letra que s est en una lista y otra que no est.
e) Aada al final de la primera lista S, compruebe el valor devuelto por la operacin y muestre la lista
resultante.
f) Obtenga la sublista definida por dos posiciones, que incluya el ltimo elemento.
g) Elimine todos los elementos de una lista entre dos posiciones dadas y muestre el resultado.
h) Ordene la lista segn el orden natural y mustrela
i) Calcule la unin, la interseccin y la diferencia de las listas dadas y muestre los resultados. Observe
qu diferencia hay con estas operaciones para conjuntos.
j) Invierta la lista y mustrela.
Nota: Siempre debemos actuar sobre las listas o los conjuntos originales. Para ello creamos dos estructuras
originales y, en aquellos apartados en los que se modifica la estructura, creamos copias. Para copiar el
contenido de una lista o un conjunto se usa el constructor copia. Es un constructor que tiene como
argumento la lista o conjunto que se desea copiar. Por ejemplo: List<Integer> copia = new
ArrayList<Integer>(original) copia los elementos de la lista original en una nueva lista copia.
4. Colecciones I
Anexo: Mtodos de las interfaces Collection, List, Set, SortedSet y clase de utilidad Collections.
public
interface
Collection<T>
extends public interface SortedSet<T> extends Set<T> {
Iterable<T> {
T first();
int size();
T last();
boolean isEmpty();
SortedSet<T> headSet(T toElement);
boolean contains(Object element);
SortedSet<T> tailSet(T fromElement);
boolean add(T element);
SortedSet<T> subSet(T fromElement ,
boolean remove(Object element);
T toElement);
boolean containsAll(Collection<?> c);
Compartor<? Super T> compartor();
boolean addAll(Collection<? extends T> c); }
boolean removeAll(Collection<?> c);
public interface List<T> extends Collection<T> {
boolean retainAll(Collection<?> c);
T get(int index);
void clear();
T set(int index, T element);
<T> T[] toArray(T[] a);
void add(int index, T element);
}
boolean remove(int index);
public interface Set<T> extends Collection<T>
boolean addAll(int index,
{
Collection<? extends T> c);
}
int indexOf(Object o);
int lastIndexOf(Object o);
List<T> subList(int fromIndex, int toIndex);
}
public class Collections {
public static <T> boolean addAll(Collection<? super T> c, T... elements);
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key);
public static <T> int binarySearch(List<? extends T> list,T key, Comparator<? super T> c);
public static void copy (List<? super T> dest, List<? extends T> src);
public static boolean disjoint(Collection<?> c1, Collection<?> c2);
public static void fill (List<? super T> l, T o);
public static int frequency (Collection<?> c, Object o);
public static int indexOfSubList(List<?> source, List<?> target);
public static int lastIndexOfSubList(List<?> source, List<?> target);
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> c);
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll);
public static <T> T min(Collection<? extends T> coll, Comparator<? super T> c);
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal);
public static void reverse (List<T> list);
public static void rotate(List<?> list, int distance);
public static void <T extends Comparable<? super T>> sort ( List<T> l);
public static void sort ( List<T> l, Comparator<? super T> c);
}
15