Escolar Documentos
Profissional Documentos
Cultura Documentos
Curso 2015/2016
Colecciones ordenadas
1/8
Mapas con claves ordenadas:
- Declara y construye un mapa ordenado (TreeMap) que asocie cadenas (String) con
objetos usuario.
- Recorre el último conjunto ordenado e inserta en el mapa los objetos del conjunto. Utiliza
el nombre del usuario como clave en el mapa.
- Recorre las claves del mapa ordenado (método keySet) y muestra por la consola las
claves. Observa que el mapa retorna las entradas ordenadas por clave. Por defecto,
utiliza el orden natural de la clase que actúa de clave (String).
- Implementa un comparador de cadenas que implemente el orden alfabético inverso.
Para ello utiliza el orden natural de las cadenas (método compareTo).
- Declara y construye un mapa ordenado que utilice el comparador. Introduce las entradas
del mapa anterior al nuevo mapa.
- Recorre y muestra por la consola las claves del mapa. Observa que las claves están
ordenadas aplicando el orden del comparador.
Ejercicios colecciones:
Crea un paquete colecciones y añade una clase Utilidades que contenga los siguientes
métodos de clase (static).
2. Escribe un método en Java que tenga como parámetro un mapa que asocie cadenas
con enteros y que devuelva un conjunto con las cadenas que tienen asociado un número
par.
3. La moda es el valor (o valores) de una serie de números que más veces se repite. Por
ejemplo, la moda de la serie {2, 3, 3, 3, 4, 5, 4, 6, 4} es {3, 4}. En el caso de que no se
repita ningún valor la serie no tiene moda. Implementa un método que reciba como
parámetro una serie de números de tamaño variable y devuelva una lista que contenga
la moda de dicha serie.
4. Escribe un método genérico que reciba como parámetro una colección de elementos y
retorne una nueva colección formada por los elementos de la original sin repetidos.
5. Programa un método genérico que acepte como parámetro un mapa que asocie
cadenas con cualquier otro tipo de datos y retorne un conjunto con los valores
almacenados en el mapa
2/8
Java 8 – Caso de estudio
El enfoque más simple es implementar en una clase de utilidades (clase Utils) tantos
métodos diferentes como criterios de búsqueda y acciones queramos aplicar sobre los
usuarios registrados. Por ejemplo,
System.out.println(usuario); ACCIÓN
}
}
Una mejora al código anterior consiste en definir cada criterio de búsqueda en una clase
separada. De esta manera, podemos definir un método que imprima los usuarios que
cumplan el criterio que se establece como parámetro:
3/8
El método imprimirUsuarios es un ejemplo de aplicación del patrón estrategia. El criterio
de búsqueda (estrategia) se define en una interfaz que incluye el método test. Este método
recibe como parámetro un objeto de tipo Usuario y devuelve un valor boolean que indica
si el usuario cumple o no el criterio de búsqueda.
De esta forma, tendremos que implementar tantas clases como criterios de búsqueda
necesitemos. Por ejemplo, el criterio que seleccione los usuarios jóvenes, esto es mayores
de edad y menores de 35 años.
@Override
public boolean test(Usuario usuario) {
Para imprimir los usuarios jóvenes, tendremos que pasar como parámetro al método
imprimirUsuarios un objeto de la clase que implementa el criterio de búsqueda (o
selección) de usuarios:
public class Programa {
4/8
Enfoque 4: Utilizar expresiones lambda para especificar el criterio de búsqueda
(Java 8)
Dado que la interfaz Criterio que hemos definido contiene un solo método (método
test), es un ejemplo de interfaz funcional, que se introduce en Java 8. Una característica
útil de este tipo de interfaz es que cuando se implementa se puede omitir el nombre del
método y el tipo de la interfaz. Así, en lugar de utilizar una clase anónima, cuando se llama
al método imprimirUsuarios, se puede pasar como parámetro una expresión lambda
que especifica el comportamiento del método test de la interfaz.
Utils.imprimirUsuarios(usuarios,
usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35);
La definición de esta interfaz coincide con la definición de la interfaz Criterio que hemos
implementado previamente (Enfoque 2), con la diferencia de que el predicado se define de
forma genérica. Puesto que el lenguaje proporciona ya este tipo de datos, no merece la
pena implementar un tipo tan sencillo en nuestra aplicación y podemos reutilizar el que nos
ofrece la librería de Java. Así, la versión del método imprimirUsuario quedaría como
sigue:
Utils.imprimirUsuariosPredicado(usuarios,
usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35);
5/8
usuarios, pero la acción a realizar es fija, imprimir el usuario. Podemos generalizar el
método de manera que la acción que se va a aplicar, sobre los usuarios que cumplen el
criterio de selección, también pueda ser establecida en el método.
Para especificar la acción a realizar sobre los objetos seleccionados se puede utilizar otra de
las interfaces funcionales predefinidas, la interfaz java.util.function.Consumer<T>.
Esta interfaz contiene el método void accept(T t), que acepta un objeto y aplica alguna
acción sobre él, sin retornar nada, por ejemplo, imprimir en la consola. Utilizando esta
interfaz el método imprimirUsuarios se puede generalizar como sigue:
La forma de invocar a este método, utilizando expresiones lambda, para imprimir todos los
usuarios jóvenes registrados sería:
Utils.procesarUsuarios(usuarios,
usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35,
usuario -> System.out.println(usuario));
Utils.procesarUsuarios(usuarios,
usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35,
System.out::println);
6/8
usuarios.stream()
.filter(usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35)
.forEach(usuario -> System.out.println (usuario));
Los streams también proporcionan, entre otras, una operación para obtener un nuevo
stream con el resultado de la correspondencia del objeto original con otro (map). Así, la
funcionalidad para imprimir el email de todos los usuarios jóvenes sería:
usuarios.stream()
.filter(usuario -> usuario.getEdad() >= 18 && usuario.getEdad() < 35)
.map(usuario -> usuario.getEmail())
.forEach(email -> System.out.println (email));
NOTA: En la sección anterior no se utilizan todas las operaciones soportadas por los
streams (filter, sorted, map, forEach, anyMatch, noMatch, allMatch, count). Revisa las
transparencias del Tema 6 de teoría para completar la información que aquí aparece y poder
implementar los ejercicios propuestos.
1) Cuenta los usuarios que tienen cuenta de correo en Gmail. Muestra el resultado en la
consola.
2) Mostrar por la consola los nombres de usuarios que sean propietarios de subastas
ordenados por orden alfabético inverso.
3) Mostrar por la consola los nombres de los productos cuyas subastas hayan recibido
alguna puja ordenados alfabéticamente.
4) Mostrar por la consola el nombre de los productos de aquellas subastas que hayan
recibido pujas superiores a 50 euros.
5) Consultar si hay usuarios que hayan ganado alguna subasta y que sean propietarios de
subastas.
6) Crea un conjunto vacío de pujas, añade a ese conjunto todas las pujas que se hayan
realizado en las subastas.
7/8
Ejercicios de exámenes anteriores relacionados con Java 8
(Junio 2015) Declara un método que pueda aceptar como parámetro un constructor sin
argumentos de cualquier colección de cadenas. El método retornará una colección obtenida
a partir del constructor con un solo elemento, la cadena vacía. Escribe un ejemplo que
muestre el uso de este método.
8/8