Tema 4: Colecciones I

Anuncio
FUNDAMENTOS DE PROGRAMACIÓN
Versión: 0.0.2
Tema 4. Colecciones I
Autor: Miguel Toro Bonilla
Revisión: José C. Riquelme
Adaptación a FP: Carlos A. García Vallejo
Tiempo estimado: 2 horas
1.
Introducción ................................................................................................................................................ 1
2.
La interfaz Collection................................................................................................................................... 1
3.
El tipo List .................................................................................................................................................... 3
4.
El tipo Set .................................................................................................................................................... 6
5.
El tipo SortedSet.......................................................................................................................................... 7
6.
La clase de utilidad Collections ................................................................................................................. 11
7.
Ejercicios.................................................................................................................................................... 14
1. Introducción
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 posición size() – 1 (recordemos que size() es una operación que devuelve el número
de elementos de la lista.
La adecuada utilización 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:




Reduce el esfuerzo de programación puesto que proporciona estructuras de datos y algoritmos
útiles.
Incrementa la velocidad y la calidad de los programas, puesto que Java ofrece implementaciones
optimizadas y libres de errores.
Simplifica la interoperabilidad y la reemplazabilidad entre aplicaciones, puesto que facilita
estructuras que se pueden intercambiar entre distintos componentes.
Reduce esfuerzos de aprendizaje y diseño.
En este capítulo 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 Colección, está definida en el paquete
java.util. Una colección es un tipo muy general, que agrupa objetos (elementos) de un mismo tipo; su
2
Fundamentos de Programación
comportamiento específico viene determinado por sus subinterfaces, que pueden admitir elementos
duplicados o no, y cuyos elementos pueden estar ordenados o no según determinado criterio. No existe una
implementación específica de la interfaz Collection; sí la tienen sus subinterfaces. El tipo Collection se utiliza
para declarar variables o parámetros donde se quiere la máxima generalidad posible, esto es, que puedan
ser utilizados tanto por listas como por conjuntos (Collection tiene otros subtipos que se tratarán más
adelante).
La interfaz Collection es genérica, 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 jerarquía de interfaces se representa en la Figura 1.
<<interfaz>>
Iterable<E>
<<interfaz>>
Collection<E>
<<interfaz>>
List<E>
......
<<interfaz>>
Set<E>
Figura 1. Jerarquía de tipos: Iterable, Collection, List y Set
Las operaciones del tipo Collection se especifican a continuación1. En general, el valor devuelto por los
métodos que devuelven boolean será true si la colección queda modificada por la aplicación del método y
false en caso contrario.
boolean add(E e)
Añade un elemento a la colección, devuelve false si no se añade.
boolean addAll(Collection<? extends E> c)
Añade todos los elementos de c a la colección que invoca. Es el operador unión. Devuelve true si la
colección original se modifica.
void
clear()
Borra todos los elementos de la colección.
boolean contains(Object o)
Devuelve true si o está en la colección invocante.
boolean containsAll(Collection<?> c)
Devuelve true si la colección que invoca contiene todos los elementos de c.
boolean isEmpty()
Devuelve true si la colección no tiene elementos.
1
Puede obtener más información de la interfaz Collection en la documentación de la API de Java:
http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
4. Colecciones
boolean remove(Object o)
Borra el objeto o de la colección que invoca; si no estuviera se devuelve false.
boolean removeAll(Collection<?> c)
Borra todos los objetos de la colección que invoca que estén en c. Devuelve true si la colección original se
modifica.
boolean retainAll(Collection<?> c)
En la colección que invoca sólo se quedarán aquellos objetos que están en c. Por tanto, es la intersección
entre ambas colecciones. Devuelve true si la colección original se modifica.
int
size()
Devuelve el número de elementos.
T[]
toArray(T[] a)
Devuelve un array con la colección.
3. El tipo List
Conceptualmente, las listas representan colecciones de elementos en los que importa cuál 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 atención a la semántica de algunas operaciones: La operación addAll añade 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 operación removeAll elimina de esta todas las instancias de los elementos que aparecen en la
lista que se pasa. De manera análoga 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 número de veces que
aparezca), en la lista resultado permanecerán las n apariciones del elemento. Todo esto se ilustra en el
Ejemplo 1:
Ejemplo 1. Ejemplo de comportamiento de removeAll y retainAll
Si se ejecuta el siguiente código:
List<String> l1 = new LinkedList<String>();
List<String> l2 = new LinkedList<String>();
l1.add("A");
l1.add("B");
l1.add("C");
l2.add("B");
l2.add("B");
l1.removeAll(l2);
mostrar("l1 después de l1.removeAll(l2): ", l1);
l1.add("A");
l1.add("B");
l1.add("C");
l2.add("B");
l2.add("B");
l2.removeAll(l1);
3
4
Fundamentos de Programación
mostrar("l2 después de l2.removeAll(l1): ", l2);
l1.add("A");
l1.add("B");
l1.add("C");
l2.add("B");
l2.add("B");
l2.retainAll(l1);
mostrar("l2 después de l2.retainAll(l1): ", l2);
se obtiene como salida:
l1 después de l1.removeAll(l2): [A, C]
l2 después de l2.removeAll(l1): []
l2 después de l2.retainAll(l1): [B, B]
La interfaz List2 aporta varias operaciones específicas, que no aparecen en Collection; en las operaciones que
tienen índice, si no se cumple la restricción sobre este se eleva la excepción IndexOutOfBoundsException.
void
add(int index, E element)
Inserta el elemento especificado en la posición especificada. El que estaba previamente en la posición
index pasará a la posición index + 1, el que estaba en la posición index + 1 pasará a la
posición index + 2, etc. Los valores lícitos para index son 0 ≤ index ≤ size().
boolean addAll(int index, Collection<? extends E> c)
Inserta todos los elementos de c en la posición especificada, desplazando el que estaba previamente en la
posición index a la posición index + c.size(), etc. Los valores lícitos para index son 0 ≤
index ≤ size().
E
get(int index)
Devuelve el elemento de la lista en la posición especificada. Los valores lícitos para index son 0
index < size().
int
indexOf(Object o)
Devuelve el índice donde ser encuentra por primera vez el elemento o (si no está devuelve
int
-1).
lastIndexOf(Object o)
Devuelve el índice donde ser encuentra por última vez el elemento o (si no estuviera devuelve
E
-1).
remove(int index)
Borra el elemento de la posición especificada. Los valores lícitos para index son 0
size().
E
≤
≤ index <
set(int index, E element)
Remplaza el elemento de la posición indicada por el que se da como argumento. Los valores lícitos para
index son 0 ≤ index < size().
List<E> subList(int fromIndex, int toIndex)
Devuelve una vista de la porción de la lista entre fromIndex, inclusive, and toIndex, sin incluir. Los
valores lícitos de fromIndex y toIndex son 0 ≤ fromIndex ≤ toIndex ≤ size().
2
Puede encontrarse más información en http://docs.oracle.com/javase/7/docs/api/java/util/List.html.
4. Colecciones
La operación subList devuelve una vista de la lista original. Esto quiere decir que las operaciones que se
realicen sobre la sublista se verán reflejadas en la lista original y viceversa. Hay que prestar atención al hecho
de que si se produce un cambio estructural que afecte al tamaño de la lista original, pueden ocurrir
comportamientos extraños, en particular la elevación de una excepción 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 código:
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 después de modificar el elemento 2 de la lista: ", subLs);
subLs.remove(1);
mostrar("Sublista después de eliminar el elemento 1: ", subLs);
mostrar("Lista original después de modificar la sublista: ", ls);
subLs.add("X");
subLs.add("Y"); // añade "X" e "Y" al final de la sublista
mostrar("Sublista después de añadirle X e Y: ", subLs);
mostrar("Lista después de la modificación de la sublista: ", ls);
ls.remove(0);
mostrar("Lista después de eliminar el primer elemento: ", ls);
mostrar("Sublista después de modificar la lista: ", subLs);
Se obtiene como salida:
Sublista: [B, C, D]
Sublista después de modificar el elemento 2 de la lista: [B, F, D]
Sublista después de eliminar el elemento 1: [B, D]
Lista original después de modificar la sublista: [A, B, D, E]
Sublista después de añadirle X e Y: [B, D, X, Y]
Lista después de la modificación de la sublista: [A, B, D, X, Y, E]
Lista después de eliminar el primer elemento: [B, D, X, Y, E]
Ejemplo 3. Ejemplo de uso de subList con modificación de la lista original
Si se ejectuta el código:
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);
mostrar("Sublista después de modificar la lista: ", subLs);
Se obtiene como salida:
Exception in thread "main" java.util.ConcurrentModificationException
5
6
Fundamentos de Programación
Las implementaciones de las listas son ArrayList y LinkedList3. La elección de una u otra implementación
dependerá del tipo de operaciones que realicemos sobre ellas. Si se va a acceder preferentemente a los
elementos mediante índice o a realizar búsquedas, debe usarse ArrayList. Si preferentemente se van a
realizar operaciones de inserción o borrado al principio o al final debe usarse LinkedList. Esto se estudiará
con más detalle en la asignatura ADDA de segundo curso. Las dos clases tienen dos constructores cada una:
uno sin argumentos, que construye una lista vacía y otro que recibe una Collection y construye una lista con
los elementos de la colección, en el orden en el que un for extendido devolvería sus elementos.
4. El tipo Set
El tipo Set se corresponde con el concepto matemático de conjunto: un agregado de elementos en el que no
hay orden (no se puede decir cuál es el 0, el 1, el 2, 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}
1
6
4
3
2
a
5
b
La interfaz Set4 no aporta ningún método extra a los que ya tiene Collection; por tanto, sus métodos son los
de Collection y solo estos. Las operaciones addAll, retainAll y removeAll se pueden identificar con la unión,
intersección y diferencia de conjuntos, respectivamente; la operación contains equivale a la pertenencia en
conjuntos ( ); la operación containsAll se corresponde con la de subconjunto ( ).
La implementación más habitual del tipo Set es la clase HashSet5. Tiene dos constructores: uno vacío, que
construye un conjunto vacío, y otro que recibe una colección y construye un conjunto con los elementos de
la colección (sin duplicados).
El for extendido aplicado a un conjunto devuelve todos sus elementos en un orden que no es predecible. Hay
una implementación, LinkedHashSet, en la que el for extendido devuelve los elementos en el orden en el que
fueron insertados en el conjunto.
3
La información completa se puede encontrar en
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html y
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html).
4
Se puede encontrar más información en http://docs.oracle.com/javase/7/docs/api/java/util/Set.html.
5
Más información en http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html.
4. Colecciones
Ejemplo 4. Orden en el que se itera sobre los elementos de un Set
Si se ejecuta el código
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
[Q, P, A, B]
[A, B, P, Q]
5. El tipo SortedSet
El tipo SortedSet es un subtipo de los conjuntos (por tanto los elementos no están indexados y no puede
haber elementos repetidos), en el que existe una relación de orden entre los elementos que permite decir
cuál va antes y cuál después. Para simplificar hablaremos de menores o mayores, entendiendo que significa
“va antes o después”, según el criterio de ordenación. A las operaciones de Set (a su vez las de Collection)
añade 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 según el criterio de ordenación) que
toElement, excluido.
SortedSet<E>
tailSet(E fromElement)
Devuelve una vista con los elementos que son mayores que
incluido este.
SortedSet<E>
fromElement,
subSet(E fromElement, E toElement)
Devuelve una vista con los elementos mayores que fromElement, incluido, y
menores que toElement, excluido. Si toElement es posterior a
fromElement, se eleva la excepción IllegalArgumentException.
E
first()
Devuelve el primer elemento. Si el SortedSet está vacío eleva la excepción
NoSuchElementException.
E
last()
Devuelve el último elemento. Si el SortedSet está vacío eleva la excepción
NoSuchElementException.
7
8
Fundamentos de Programación
Comparator<? super E> comparator()
Devuelve el orden del conjunto ordenado o
natural de E.
null si está ordenado por el orden
Ejemplo 5. Ejemplo de uso de headSet, tailSet y subSet
Si se ejecuta el código
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 actúa
sobre el original se modifica la vista y viceversa.
Ejemplo 6. Ejemplo que ilustra que los rangos son vistas del conjunto ordenado original
Si se ejecuta el código
mostrar("ss = " + ss);
fin.add('S');
mostrar("tailSet('Q') tras add('S') = " + fin);
mostrar("ss tras add('S') = " + ss);
ss.add('D');
mostrar("ss tras add('D') = " + ss);
mostrar("headSet('G') tras add('D') = " + inicio);
Se obtiene como salida
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.
4. Colecciones
Ejemplo 7. En las vistas de los SortedSet no se puede actuar fuera del rango
Si se ejecuta
inicio.add('G');
Se obtiene
java.lang.IllegalArgumentException: key out of range
La implementación de los conjuntos ordenados es la clase TreeSet6. Esta clase tiene cuatro constructores:
 Un constructor vacío, que crea un conjunto ordenado vacío donde los elementos se ordenaran
según 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 colección ordenados según su orden natural (los elementos de la colección tienen
que implementar Comparable).
 Un constructor que recibe un Comparator, que crea un conjunto ordenado vacío cuyos elementos se
ordenaran según 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 código
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);
}
Provoca la siguiente salida:
C
F
P
Q
R
X
Hay que hacer una observación 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 comparación con los existentes no es cero para ninguno de ellos. Si se está usando el orden natural, esto
6
La información completa se encuentra en http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html.
9
10
Fundamentos de Programación
equivale a que no hay un elemento igual que el nuevo, lo que coincide con la idea que tenemos de la
inserción en conjuntos no ordenados; sin embargo, si se usa un orden alternativo puede que haya dos
elementos distintos cuya comparación de 0, por lo que el segundo no se insertaría. Si este es el
comportamiento deseado, no habría que hacer nada, pero si no lo es, la solución más sencilla es modificar la
comparación entre elemento introduciendo un “desempate” por el orden natural en caso de que haya
“empate” por el orden alternativo.
Ejemplo 9. Orden natural y alternativos en un SortedSet
Supongamos que tenemos un orden natural en la clase PersonaImpl que es apellidos, nombre, dni (con el
que será compatible equals). Supongamos también 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;
}
}
Si se ejecuta el siguiente código
Persona p1 = new PersonaImpl("31122334-W", "Antonio", "García Maratón", 22);
Persona p2 = new PersonaImpl("34423123-V", "María", "Pérez Piña", 20);
Persona p3 = new PersonaImpl("38962334-W", "Eva", "García Morón", 22);
Persona p4 = new PersonaImpl("34435723-V", "Eugenia", "Gómez 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):
[García Maratón, Antonio (31122334-W), García Morón, Eva (38962334-W), Gómez
Titos, Eugenia (34435723-V), Pérez Piña, María (34423123-V)]
Si a continuación 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 desemapate:\n", ss);
Se obtiene la salida
ss con el orden por edad sin desemapate:
[Pérez Piña, María (34423123-V), García Maratón, Antonio (31122334-W)]
Vemos que se han “perdido” dos personas, que tenían 20 y 22 años, 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 sin desempate:\n", ss);
4. Colecciones
Se obtiene la salida
ss con el orden por edad sin desempate:
[Gómez Titos, Eugenia (34435723-V), Pérez Piña, María (34423123-V), García
Maratón, Antonio (31122334-W), García Morón, Eva (38962334-W)]
donde están todas las personas, están en orden de edad y dentro de los de la misma edad, en orden
alfabético de apellidos, nombre.
6. La clase de utilidad Collections
El paquete java.util contiene la clase de utilidad Collections7. Esta clase está formada por métodos estáticos
que permiten realizar operaciones sofisticadas sobre las colecciones, como invertir una lista, barajarla,
ordenarla, buscar una sublista dentro de una lista, encontrar el máximo o el mínimo de los elementos de una
colección, contar las veces en las que aparece un elemento, etc.
Algunos de sus métodos (los más usados) son:
static <T> boolean
addAll(Collection<? super T> c,
T... elements)
Añade a la colección los elementos indicados en elements.
static <T> int
binarySearch(List<?
extends
super T>> list, T key)
Devuelve la posición del objeto
Comparable<?
key en la lista ordenada según su orden
natural, o -1 si no lo encuentra.
static <T> int
binarySearch(List<? extends
Comparator<? super T> c)
Devuelve la posición del objeto
T> list,T key,
key en la lista ordenada según el orden
c, o -1 si no lo encuentra.
public static <T> void
copy(List<? super T> dest, List<? extends
T> src)
Copia los elementos de la lista src en la lista dest, en el mismo orden
en el que se encuentran. La lista de dest debe tener al menos tantos
elementos como la lista src; en caso contrario eleva la excepción
IndexOutOfBoundsException. Si la lista dest tiene más
elementos que src, los elementos restantes de dest permanecen
inalterados.
static boolean
disjoint(Collection<?> c1, Collection<?> c2)
Devuelve verdadero si no hay elementos comunes a las dos colecciones.
static void
fill(List<? super T> l, T o)
Reemplaza todos los elementos de la lista l por o.
7
Se puede encontrar una descripción exhaustiva en
http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html.
11
12
Fundamentos de Programación
static int
frequency(Collection<?> coll, Object o)
Devuelve el número de elementos iguales a
static int
o en la colección coll.
indexOfSubList(List<?> source,
List<?> target)
Devuelve la primera posición de la primera ocurrencia de target dentro de
source, o -1 si no encuentra ninguna.
static int
lastIndexOfSubList(List<?> source,
List<?> target)
Devuelve la primera posición de la última ocurrencia de target dentro de
source o -1 si no encuentra ninguna.
static
<T max(Collection<? extends T> coll)
extends Object & Comparable Devuelve el elemento máximo de la colección coll según el orden natural
de sus elementos.
<? super T>> T
static <T> T
max(Collection<? extends T> coll,
Comparator<? super T> c)
Devuelve el element máximo de la colección
coll según el orden dado
por el Comparator c.
static <T extends Object
min(Collection<? extends T> coll)
& Comparable<? super T>> T
Devuelve el elemento mínimo de la colección
natural de sus elementos.
static <T> T
min(Collection<? extends T> coll,
coll según el orden
Comparator<? super T> c)
Devuelve el element mínimo de la colección
coll según el orden dado
por el Comparator c.
static <T> boolean
replaceAll(List<T> list, T oldVal, T newVal)
Reemplaza en list el objeto oldVal por newVal.
static void
reverse(List<?> list)
Invierte los elementos de la lista
static void
list.
rotate(List<?> list, int distance)
Rota la lista en un número distance de casillas hacia la derecha si
es positivo o hacia la izquierda si es negativo.
static
<T
extends sort(List<T> list)
Comparable<?
super
T>>
Ordena la lista según el orden natural del tipo.
void
static <T> void
sort(List<T> list, Comparator<? super T> c)
Ordena la lista según el orden dado por c.
4. Colecciones
Ejemplo 10. Utilización de la clase Collections
Si se ejecuta el código
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
Fundamentos de Programación
7. Ejercicios
Ejercicio 1
Escriba la clase TestEjercicio1 con un método main que
a) Cree dos conjuntos vacíos de Integer, añada 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) Añada un entero al primer conjunto, compruebe el valor devuelto por la operación 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 unión, la intersección y la diferencia de los conjuntos y muestre los resultados.
Ejercicio 2
Escriba la clase TestEjercicio2 con un método main que
a) Cree dos listas vacías de Character, añada 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é posición está una letra que sí está en una lista y otra que no está.
e) Añada al final de la primera lista ‘S’, compruebe el valor devuelto por la operación 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 según el orden natural y muéstrela
i) Calcule la unión, la intersección 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 muéstrela.
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
Anexo: Métodos 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
Descargar