PR14 - Criterios de Comparación y Ordering

Anuncio
FUNDAMENTOS DE PROGRAMACIÓN
Curso: 2010/11
PRÁCTICA 14: CRITERIOS DE COMPARACIÓN Y ORDERING
Versión: 1.0.3
OBJETIVOS
Criterios de comparación auxiliar: Comparator/compare.
Utilización de la clase Ordering de la librería Guava.
INTERFAZ COMPARATOR VS COMPARABLE
Interfaz Comparable
En el cuatrimestre anterior hemos diseñado tipos en los que se especificaba un criterio
de orden natural, es decir, es el criterio por el que normalmente se comparan los objetos
instanciados del tipo en el mundo real.
Recordemos que para implementar el criterio de orden natural es necesario:
1. Indicar que la
Comparable<T>:
interfaz
del
tipo
a
implementar
extiende
la
interfaz
public interface Nombre_Interfaz extends Comparable<Nombre_Interfaz> {
...
}
2. Como consecuencia, en la clase que implemente la interfaz será necesario
construir el método int compareTo (T o):
public class Nombre_Clase implements Nombre_Interfaz {
...
public int compareTo (Nombre_Interfaz o){..}
}
Además, tenga en cuenta que:
El método compareTo devolverá un entero negativo, cero o positivo dependiendo
de si el objeto “this” con el que se invoca al método, es menor, igual o mayor al
objeto “o” pasado por parámetro.
La implementación del método compareTo debe ser coherente con la
implementación del método equals, de tal forma que si “o1” y “o2” son dos
objetos, entonces se debe de cumplir que si o1.equals(o2) devuelve true entonces
o1.compareTo(o2) debe devolver cero.
Interfaz Comparator
Además de ordenación natural, nos podría interesar ordenar los objetos de un tipo por
otros criterios, por ejemplo, el tipo Persona por DNI o también por edad. Para definir
estos nuevos criterios de ordenación que son auxiliares y distintos al orden natural se
utiliza la interfaz Comparator, que se encuentra definida en el paquete java.util. En este
caso, para implementar el criterio de orden natural es necesario:
1. Construir tantas clases nuevas que implementen la interfaz Comparator como
criterios de ordenación se deseen
public interface Comparator<T> {
int compare (T o1, T o2);
}
Práctica 14: Criterios de Comparación y Ordering
2
El método compare, se comporta de manera similar al método compareTo en cuanto a lo
que devuelve, que será un entero negativo, cero o positivo según sea su primer
argumento “o1”, menor, igual o mayor al segundo argumento “o2”.
Note la diferencia de sintaxis entre los dos métodos: mientras compareTo se invoca por
un objeto y se le pasa el otro como parámetro, compare recibe los dos objetos a
comparar como argumentos y se invoca con un objeto, creado por defecto, de la clase
comparadora.
LIBRERÍA GUAVA
La librería Guava proporciona un conjunto de utilidades de Google. Esta librería ha sido
utilizada en los proyectos internos de Google y la idea que subyace, al hacer pública
dicha librería, es la de proveer código basado en buenas prácticas que aumenten la
productividad de los desarrolladores. Guava integra también lo que anteriormente era
Google Collections, unificando las utilidades de entrada/salida, primitivas, concurrencia
y colecciones en una única librería.
De todas las utilidades proporcionadas en Guava, nos centramos en la utilización de la
clase Ordering. Esta clase combina Comparators con la funcionalidad de Collections. La
clase Ordering se utilizará si se necesita ordenar iterables, encontrar el máximo o
mínimo en un iterable, encontrar el índice de un elemento del iterable, etc.
La documentación de esta clase (API) se encuentra en el enlace:
http://guava-libraries.googlecode.com/svn/tags/release08/javadoc/index.html
En el siguiente cuadro se observa un resumen de la funcionalidad de la clase Ordering,
en el paquete com.google.common.collect.Ordering;
static <T> Ordering<T>
static Ordering<Object>
static
<C extends Comparable>
Ordering<C>
<E extends T> List<E>
int
<S extends T>
Ordering<S>
<S extends T>
Ordering<S>
from(Comparator<T> comparator)
Devuelve un ordering para un comparator existente.
usingToString()
Devuelve un ordering que compara objetos según el
orden alfabético de la representación en cadena (toString)
de los objetos del iterable que se utilice posteriormente.
natural()
Devuelve un ordering en función del orden natural,
es decir, del método compareTo.
sortedCopy(Iterable<E> iterable)
Devuelve una copia ordenada de un iterable dado. El
orden del iterable depende del criterio de comparación
asociado al objeto ordering que invoque este método.
binarySearch(List<?
extends
T> sortedList,
T key)
Devuelve la posición del element key en el iterable
ordenado sortedList utilizando el algoritmo de búsqueda
binaria.
nullsFirst()
Devuelve un ordering que trata iterables con
elementos null, de manera que éstos se consideran
menores al resto de objetos, si se ordena los elementos
null quedarán al principio.
nullsLast()
Similar al anterior, pero los elementos null
quedarán al final del iterable si este es ordenado.
Práctica 14: Criterios de Comparación y Ordering
<E extends T> E
<E extends T> E
3
max(Iterable<E> iterable)
Devuelve el máximo del iterable de acuerdo con el
criterio de ordenación asociado al objeto ordering que
invoca este método.
min(Iterable<E> iterable)
Devuelve el mínimo del iterable de acuerdo con el
criterio de ordenación asociado al objeto ordering que
invoca este método.
Tenga en cuenta que la clase Ordering tiene un único constructor protegido, es decir, su
nivel de visibilidad no es público. Por ello, para crear objetos de tipo Ordering se ha de
utilizar uno de los tres métodos estáticos siguientes:
El método from, que construye un objeto Ordering en función de un criterio de
comparación auxiliar, es decir, un objeto Comparator.
Comparator<Persona> c = new ComparadorPorEdad();
Ordering<Persona> ord1 = Ordering.from(c);
El método usingToString, que construye un objeto Ordering cuyo criterio de
comparación asociado es el alfabético de la representación en cadena de los
objetos a ordenar.
Ordering<Object> ord2 = Ordering.usingToString();
El método natural, que construye un objeto Ordering cuyo criterio de
comparación es el criterio natural.
Ordering<Persona> ord3 = Ordering.natural();
EJERCICIOS PROPUESTOS
Importe el proyecto Practica14Alumno que se proporciona con la práctica. Dicho
proyecto tiene implementado entre otros los tipos Vuelo y Cancion.
Tipo Vuelo
Codigo, Integer mayor que cero, sólo consultable
Destino, String, sólo consultable
Precio, Double, consultable y modificable
NumeroDePlazas, Integer mayor que cero, sólo consultable
NumeroDePasajeros, Integer mayor o igual que cero y menor o igual que
NumeroDePlazas, sólo consultable
Pasajeros, Vector<Persona>, sólo consultable
Fecha, Fecha, posterior a 1/1/2000, sólo consultable
Orden natural: por Destino y Codigo
Criterio de Igualdad: si tienen el mismo Destino y Codigo
Tipo Canción:
Nombre, de tipo String, consultable
Intérprete, de tipo String, consultable
Duración, de tipo Hora, consultable
Año, de tipo Integer, consultable
Género, de tipo String, consultable
Práctica 14: Criterios de Comparación y Ordering
4
NúmeroDeReproducciones, de tipo Integer, consultable y modificable
Calificación, de tipo Integer, consultable y modificable (la calificación es un
valor que indica cuánto nos gusta una canción y está comprendido entre 0,
muy poco, y 5, mucho)
Reproducir, de tipo Boolean, consultable y modificable
Orden natural: por nombre, y a igualdad de nombre por intérprete
Criterio de igualdad: dos canciones son iguales si tienen el mismo nombre y el
mismo intérprete
Representación como cadena: [Nombre, intérprete]
Abra la vista de tareas, en el menú Window->Show View->Tasks, y realice las tareas
indicadas con la etiqueta TODO ejercicio X. Descomente estas líneas una vez realizada
la tarea que corresponde con los siguientes ejercicios:
1. En el paquete de nombre comparadores implemente para el tipo Vuelo los
siguientes criterios de orden auxiliares:
a. Criterio de comparación basado en la fecha de Vuelo.
b. Según precio de los objetos de Vuelo.
2. En la clase TestVuelos, a partir de la lista proporcionado de nombre vuelos:
a. Ordene dicho iterable según su criterio de orden natural y muéstrelo por
pantalla.
b. Ordene el iterable según el criterio de orden auxiliar basado en la fecha
del vuelo y muéstrelo por pantalla.
c. Finalmente, ordene el iterable de vuelos según el criterio de orden auxiliar
basado en el precio.
3. Añada los siguientes criterios de orden auxiliar al tipo Cancion:
a. Criterio auxiliar basado en el año de la canción.
b. Criterio auxiliar basado en el género.
c. Criterio auxiliar basado en la duración.
4. En la clase TestMusica:
a. Ordene la lista proporcionado según el criterio de orden natural del tipo
Cancion y muéstrelo por pantalla.
b. Ordene la lista de canciones según los criterios del ejercicio anterior.
5. Téngase en cuenta que en Java los criterios de comparación natural son
coherentes con el criterio de igualdad, sin embargo los comparadores auxiliares o
adicionales que hemos realizado no son coherentes con la igualdad. En
ocasiones, puede que el criterio de comparación de un Comparator tenga que ser
coherente con el criterio de igualdad. Por ejemplo, piense en un conjunto
ordenado al que añadimos objetos de tipo Persona teniendo en cuenta un
comparador basado en el año de nacimiento. Al añadir los objetos de manera
ordenada el conjunto se basa en el método compare de la clase Comparador y no
en el equals. ¿Qué pasaría? Tan solo se añade un objeto de todos los que haya
con el mismo año de nacimiento. Haga coherente el criterio criterio de
comparación de Vuelo por fecha con el criterio de orden natural que es coherente
al equals por definición.
Para continuar los ejercicios de la práctica debe importar la librería Guava de Google.
Con este objetivo entre en la siguiente dirección donde se encuentra la librería:
http://code.google.com/p/guava-libraries/
Haga clic a la derecha del navegador en “Downloads guava-r08.zip” y así podrá descargar
el fichero guava-r08.zip. En el espacio de trabajo de su proyecto almacene dicho fichero
Práctica 14: Criterios de Comparación y Ordering
5
descomprimido. Al descomprimir aparecerá la carpeta guava-r08 y dentro de ella la
librería con el nombre guava-r08.jar Este fichero es la librería que se ha de importar en el
proyecto de la práctica, para ello:
Seleccionando el proyecto (en el explorador de paquetes”) y con el botón
derecho, seleccione “Properties” “Java Build Path”.
Seleccione “add External Jar” y seleccione en la ventana de explorador de
ficheros el fichero guava-r08.jar.
Finalmente, pinche el botón “OK” y en el explorador de paquetes debe
aparecer la librería en el proyecto sobre el que estamos trabajando.
6. En la clase utilidad Canciones escriba cada uno de los siguientes métodos
estáticos y pruebe su correcto funcionamiento en la clase TestOrdering:
a. Dada una lista de canciones y un comparador de Cancion basado en el
año de publicación de la canción, devuelva una lista ordenada de la lista.
Para ello cree un objeto de tipo Ordering a partir del comparador y el
método sortedCopy.
public static List<Cancion> creaCopiaIterableOrdenadaAux
(List<Cancion> listaCanciones, Comparator<Cancion> c)
b. Dada una lista de canciones, cree un objeto de tipo Ordering cuyo criterio
de orden será la representación en cadena de los objetos del iterable. Cree
una copia ordenada de la lista y devuelva dicha copia como resultado.
public
static
List<Cancion>
(List<Cancion> listaCanciones)
creaCopiaIterableOrdString
c. Dada una lista de canciones, devuelva una copia de la lista ordenada
según el criterio de orden natural y utilizando la clase Ordering.
public
static
List<Cancion>
(List<Cancion> listaCanciones)
creaCopiaIterOrdenadaNat
d. Dada una lista de canciones y un objeto de tipo Cancion, devuelva la
posición de dicha canción según el orden obtenido a partir del criterio de
orden natural.
public
static
int
listaCanciones, Cancion c)
busquedaDeCancion(List<Cancion>
e. Dada una lista que contiene elementos nulos, cree una copia de la lista
ordenado según su criterio de orden natural y con los elementos nulos al
principio del iterable.
public
static
List
<Cancion>
(List<Cancion> listaCanciones)
f.
ordenaNulosPrimeros
Dada una lista que contiene elementos nulos, cree una copia de la lista
iterable ordenada según su criterio de orden natural y con los elementos
nulos al final del iterable.
public
static
List
<Cancion>
(List<Cancion> listaCanciones)
ordenaNulosUltimos
g. Dada una lista de canciones devuelva la canción más antigua.
public
static
listaCanciones)
Cancion
cancionMasAntigua(List<Cancion>
h. Realice el ejercicio 6.a pero para una lista genérica.
public static <T> List<T> creaCopiaIterableOrdenadaAux2
(List<T> listaT, Comparator<T> c)
Descargar