Tema 10: Órdenes, predicados y funciones

Anuncio
FUNDAMENTOS DE PROGRAMACIÓN
Versión: 0.3.0
Tema 10. Órdenes, predicados y funciones
Autores: Juan A. Nepomuceno
Revisiones: Antonia M. Reina
Tiempo estimado: 4 horas
1.
Introducción ................................................................................................................................................ 1
2.
El tipo Ordering ........................................................................................................................................... 2
3.
El tipo Predicate .......................................................................................................................................... 5
4.
La clase de utilidad Predicates ................................................................................................................... 6
5.
El tipo Function ........................................................................................................................................... 8
6.
La clase de utilidad Functions ..................................................................................................................... 9
7.
Acciones .................................................................................................................................................... 10
8.
Ejercicios propuestos ................................................................................................................................ 10
Anexo ................................................................................................................................................................ 13
1. Introducción
Nos marcamos como objetivo resolver cada tratamiento secuencial visto en el primer cuatrimestre mediante
la llamada a un método implementado previamente que lo resuelva. De esta forma, utilizando código ya
verificado, reducimos las posibilidades de cometer errores de programación.
Uno de los mecanismos más importantes de la Programación Orientada a Objetos para la reutilización de
código es el mecanismo de abstracción. Dicho mecanismo consiste en programar teniendo en cuenta “qué
se hace” en lugar del “cómo se hace” y, de esta forma, se puede programar de forma generalizada.
Veámoslo con un ejemplo: un método que calcule, dados dos objetos, el mayor de ellos según un orden
determinado. Nos centramos en “qué significa orden” y no en “cómo se ordena”. De esta forma, el método
public static <T> T mayor(T o1, T o2, Comparator<T> cmp) {
T res;
if (cmp.compare(o1, o2) > 0) {
res = o1;
} else {
res = o2;
}
return res;
}
sirve para cualquier criterio de ordenación y para objetos de cualquier tipo. Cuando se quiera utilizar este
método, bastará pasarle como parámetro de entrada no sólo los dos objetos a ordenar, sino también un
objeto comparador que abstrae la idea del criterio de ordenación que se vaya a utilizar. En el tema 3 vimos
2
Fundamentos de Programación
cómo implementar comparadores, que son clases que implementan la interfaz Comparator<T> presente en
la API de Java en el paquete java.util1. De esta forma, cuando se quiera abstraer la información de un criterio
de ordenación, lo que se hará será implementar un comparador que indique cómo se ordenan los objetos
dos a dos. Así se pueden reutilizar métodos genéricos que calculan, por ejemplo, máximos o mínimos.
De una manera análoga a los comparadores, en este tema nos abstraeremos de expresiones lógicas
concretas usando la interfaz Predicate<T> de la librería Guava y de expresiones sobre un tipo F que
devuelven un resultado de tipo T mediante la interfaz Function<F,T>, también de la librería Guava. El
abstraernos de expresiones concretas nos permitirá implementar métodos genéricos que requieran una
condición de filtrado o expresiones generales que transformen objetos de un tipo en otro.
En este tema veremos, en primer lugar, la clase Ordering, una clase de la librería Guava que, a la vez, hace de
factoría y proporciona métodos para calcular máximos, mínimos y ordenar, entre otras utilidades. En
segundo lugar, introduciremos el tipo Predicate como una forma de abstracción de las expresiones lógicas, y
la clase de utilidad Predicates, que contiene métodos para combinar predicados. En tercer lugar, se verá el
tipo Function, como una forma de abstraerse de una expresión sobre un tipo, y la clase de utilidad Functions,
que contiene métodos para combinar expresiones. Finalmente, se introducirá el tipo Accion, que es propio
de la asignatura y no está soportado por Guava, como una forma de abstraerse de una expresión que
modifica alguna propiedad de un objeto de un tipo concreto.
2. El tipo Ordering
La clase Ordering2 pertenece al paquete com.google.common.collect y en ella se puede encontrar toda la
funcionalidad relacionada con órdenes: máximos, mínimos, ordenaciones, etc. Los métodos que proporciona
se pueden clasificar en tres grandes grupos: (1) métodos para crear objetos de tipo Ordering (o métodos de
factoría); (2) métodos para combinar criterios de ordenación (o métodos de manipulación de objetos de tipo
Ordering); y (3) métodos para aplicar criterios de ordenación.
Veamos algunos de los métodos más importantes de estas tres categorías:
1. Métodos de factoría.
Los métodos de este grupo sirven para crear un objeto de tipo Ordering que será utilizado
posteriormente como objeto base o pivote que invoque otras funcionalidades. Note que todos los
métodos de esta categoría son estáticos. Los principales son:
static <T> Ordering<T>
from(Comparator<T> comparator)
Crea un objeto de tipo Ordering usando el orden inducido
por el comparador que se pasa como parámetro.
static <C extends Comparable>
Ordering<C>
1
2
natural()
Crea un objeto de tipo Ordering usando como criterio de
ordenación el orden natural.
Ver: http://docs.oracle.com/javase/7/docs/api/
http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Ordering.html
10. Órdenes, predicados y funciones
static Ordering<Object>
usingToString()
Crea un objeto de tipo Ordering usando como criterio de
ordenación el orden alfabético de la representación como
cadena de los objetos.
Note que, a diferencia de los métodos natural y from, el método usingToString devuelve un objeto de
tipo Ordering<Object>.
2. Métodos de manipulación de objetos de tipo Ordering.
Los métodos de este grupo se utilizan para obtener nuevos objetos de tipo Ordering derivados de los
objetos de tipo Ordering sobre los que se invocan. Pueden verse como una forma de componer objetos
de tipo Ordering. Note que los métodos de este grupo no son estáticos, por lo que para utilizarlos es
necesario haber creado previamente un objeto de tipo Ordering con los métodos factoría. Algunos de los
métodos de este grupo son:
<S extends T>
Ordering<S>
reverse()
<S extends T>
Ordering<S>
nullsLast()
<S extends T>
Ordering<S>
nullsFirst()
<U extends T>
Ordering<U>
compound(Comparator<? super U> secondaryComparator)
<F> Ordering<F>
onResultOf(Function<F,? extends T> function)
Devuelve un objeto de tipo Ordering que especifica el criterio de
ordenación inverso al del objeto de tipo Ordering con el que se invoca al
método.
Devuelve un objeto de tipo Ordering que trata a los nulos como
elementos mayores que el resto. Los elementos no nulos se ordenan
según el criterio definido por el objeto de tipo Ordering con el que se
invoca al método.
Devuelve un objeto de tipo Ordering que trata a los nulos como
elementos menores que el resto. Los elementos no nulos se ordenan
según el criterio definido por el objeto de tipo Ordering con el que se
invoca al método.
Devuelve un objeto de tipo Ordering que usa el criterio de ordenación
definido por el objeto de tipo Ordering con el que se invoca, pero que en
caso de empate usa el comparador secundario para desempatar.
Devuelve un objeto de tipo Ordering sobre F que ordena los elementos
primero aplicándoles la función3, y luego según el criterio definido por el
objeto de tipo Ordering que lo invoca.
3. Métodos de aplicación de criterios de ordenación.
Los métodos de este grupo se utilizan para aplicar criterios de ordenación a valores o colecciones de
elementos. Los métodos de este grupo tampoco son estáticos, por lo que para utilizarlos es necesario
3
El concepto de función se verá más adelante en el tema.
3
4
Fundamentos de Programación
haber creado previamente un objeto de tipo Ordering. Algunos de los métodos más populares de este
grupo son:
<E extends T> E
max(E a, E b)
Devuelve el mayor de los dos valores según el criterio de ordenación
inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T> E
max(E a, E b, E c, E... rest)
Devuelve el mayor de los valores especificados según el criterio de
ordenación inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T> E
max(Iterable<E> iterable)
Devuelve el mayor de los elementos del iterable según el criterio de
ordenación inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T> E
min(E a, E b)
Devuelve el menor de los dos valores según el criterio de ordenación
inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T> E
min(E a, E b, E c, E... rest)
Devuelve el menor de los valores especificados según el criterio de
ordenación inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T> E
min(Iterable<E> iterable)
Devuelve el mayor de los elementos del iterable según el criterio de
ordenación inducido por el objeto de tipo Ordering con el que se invoca.
<E extends T>
List<E>
sortedCopy(Iterable<E> iterable)
int
binarySearch(List<? extends T> sortedList, T key)
Devuelve una lista que es una copia del objeto iterable que se pasa como
parámetro, ordenada según el criterio inducido por el objeto de tipo
Ordering con el que se invoca.
Busca en la lista sortedList el elemento key utilizando el algoritmo de
búsqueda binaria. La lista debe estar ordenada según el criterio inducido
por el objeto de tipo Ordering con el que se invoca. Devuelve el índice del
elemento buscado en la lista, o un número negativo si el elemento no se
encuentra.
Para utilizar los métodos de Ordering en el cálculo de un máximo o un mínimo procederemos de la siguiente
forma:
1. Se crea un objeto del tipo Ordering utilizando alguno de los métodos de la factoría (natural, si se quiere
ordenar según el criterio de ordenación natural; from, junto con un comparador, si se quiere ordenar
por un criterio de ordenación alternativo; usingToString, si se quiere ordenar según la representación
como cadena).
2. Con el objeto del tipo Ordering creado en el apartado anterior, se invoca a max, si se quiere calcular un
máximo, o a min, si se quiere calcular un mínimo.
10. Órdenes, predicados y funciones
Tenga en cuenta que los dos pasos anteriores se pueden implementar en una sola línea de código.
Algunos ejemplos de uso de Ordering son:
Ejemplo 1
Dada una lista de libros se desea saber cuál es el mayor libro según el orden natural del tipo Libro.
public static Libro libroMayor(List<Libro> lstLibro) {
return Ordering.natural().max(lstLibro);
}
Listado 1. Cálculo del máximo según el criterio de ordenación natural usando Ordering
Ejemplo 2
Dada una lista de libros se desea saber cuál es el más caro.
public static Libro libroMasCaro(List<Libro> lstLibro) {
return Ordering.from(new ComparadorLibroPorPrecio()).max(lstLibro);
}
Listado 2. Cálculo del máximo según el criterio definido por un comparador usando Ordering
Para lo cual es necesario tener previamente implementado el comparador ComparadorLibroPorPrecio.
public class ComparadorLibroPorPrecio implements Comparator<Libro> {
public int compare(Libro l1, Libro l2){
int res = l1.getPrecio().compareTo(l2.getPrecio());
if (res == 0) {
res = l1.compareTo(l2);
}
return res;
}
}
Listado 3. Clase ComparadorLibroPorPrecio
3. El tipo Predicate
La interfaz Predicate<T>4 se encuentra en el paquete com.google.common.base y nos abstrae del concepto
de expresión lógica. Predicate tiene dos métodos: apply y equals. Su descripción es la siguiente:
boolean
apply(T input)
Devuelve un valor de tipo lógico resultado de aplicar una expresión lógica sobre input.
boolean
equals(Object object)
Devuelve true si el objeto object es un predicado igual al predicado con el que se invoca al
método.
4
http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Predicate.html
5
6
Fundamentos de Programación
Es aconsejable que la expresión lógica del método apply no tenga efectos laterales y sea consistente con
equals. El método equals generalmente no lo implementaremos, sino que utilizaremos el que se hereda de
Object. Un ejemplo de uso del tipo Predicate es el siguiente:
Ejemplo 3
Escriba un predicado que determine si un libro es un best seller.
public class PredicadoLibroEsBestSeller implements Predicate<Libro> {
public boolean apply(Libro l) {
return l.getEsBestSeller();
}
}
Listado 4. Clase PredicadoLibroEsBestSeller.
Los objetos de tipo predicado serán pasados como parámetros de entrada a los métodos genéricos que los
requieran. Así se consigue la abstracción de condiciones de filtrado en una búsqueda, la abstracción de
propiedades en tratamientos secuenciales de existencia, etc. En general serán deseables predicados que
abstraigan pequeñas funcionalidades de modo que se puedan combinar entre sí y obtener de esta forma
piezas de código de fácil combinación y reutilización.
4. La clase de utilidad Predicates
La clase de utilidad Predicates5 está en el paquete com.google.common.base, y proporciona dos tipos de
métodos: (1) métodos de factoría; y (2) métodos para componer predicados.
1. Métodos de factoría.
Los métodos de este grupo sirven para crear predicados de uso común. Algunos métodos de este grupo
son:
static <T> Predicate<T>
alwaysFalse()
Crea un predicado que siempre se evalúa a falso.
static <T> Predicate<T>
alwaysTrue()
Crea un predicado que siempre se evalúa a cierto.
static <T> Predicate<T>
equalTo(T target)
Crea un predicado que se evalúa a cierto si el objeto pasado como
parámetro, target, y el objeto referencia son iguales, según el equals,
o bien si los dos son nulos.
static <T> Predicate<T>
isNull()
Crea un predicado que se evalúa a cierto si el objeto referencia que
está siendo comprobado es nulo.
static <T> Predicate<T>
5
notNull()
http://docs.guava-librariees.googlecode.com/git-history/release/javadoc/com/google/common/base/Predicates.html
10. Órdenes, predicados y funciones
Crea un predicado que se evalúa a cierto si el objeto referencia que
está siendo comprobado no es nulo.
static <T> Predicate<T>
in(Collection<? extends T> target)
Crea un predicado que se evalúa a cierto si el objeto referencia es
miembro de la colección target.
2. Métodos de composición de predicados.
Los métodos de este grupo devuelven un predicado basado en otro o en otros básicos. Algunos métodos
de este grupo son:
static <T> Predicate<T>
and(Predicate<? super T> first,
Predicate<? super T> second)
Devuelve un predicado que se evalúa a cierto si ambos componentes
(first y second) se evalúan a cierto.
static <T> Predicate<T>
and(Predicate<? super T>... components)
Devuelve un predicado que se evalúa a cierto si todos los
componentes se evalúan a cierto.
static <T> Predicate<T>
and(Iterable<? extends Predicate<? super T>> components)
Devuelve un predicado que se evalúa a cierto si todos los predicados
del iterable se evalúan a cierto.
static <T> Predicate<T>
or(Predicate<? super T> first,
Predicate<? super T> second)
Devuelve un predicado que se evalúa a cierto si alguno de los dos
componentes (first o second) se evalúa a cierto.
static <T> Predicate<T>
or(Predicate<? super T>... components)
Devuelve un predicado que se evalúa a cierto si alguno de los
componentes se evalúa a cierto.
static <T> Predicate<T>
or(Iterable<? extends Predicate<? super T>> components)
Devuelve un predicado que se evalúa a cierto si alguno de los
predicados del iterable se evalúa a cierto.
static <T> Predicate<T>
not(Predicate<T> predicate)
Devuelve un predicado que se evalúa a cierto si el predicado
predicate se evalúa a falso.
static
<A,B> Predicate<A>
compose(Predicate<B> predicate,
Function<A,? extends B> function)
Devuelve un predicado resultado de la composición de una función6 y
un predicado.
Un ejemplo de uso de los métodos de Predicates es el siguiente:
6
En el siguiente apartado se verá el concepto de función.
7
8
Fundamentos de Programación
Ejemplo 4
Se pretende obtener un predicado que indique si un libro tiene un autor en concreto, un número de páginas
determinado y un precio concreto.
Predicate<Libro>
Predicate<Libro>
Predicate<Libro>
Predicate<Libro>
pr1 = new PredicadoLibroNombreAutorIgualA("Amos");
pr2 = new PredicadoLibroNumPaginasIgualA(100);
pr3 = new PredicadoLibroPrecioIgualA(25.0);
resultado = Predicates.and(pr1,pr2,pr3);
Listado 5. Combinación de predicados mediante Predicates.and
En el Listado 5 se supone que previamente se han implementado las clases PredicadoLibroPrecioIgualA,
PredicadoLIbroNumPaginasIgualA y PredicadoLibroNombreAutorIgualA.
5. El tipo Function
De manera análoga a como trabajamos con Predicate<T>, trabajaremos con la interfaz Function<F,T>7, que
abstrae una función que se aplica a un objeto de tipo F y cuyo resultado es un objeto de tipo T. Las funciones
se pueden ver como una generalización del concepto de predicado, ya que un predicado Predicate<T> puede
considerarse una función de tipo Function<T, Boolean>. Al igual que Predicate, tiene dos métodos: apply y
equals. Su descripción es la siguiente:
T
apply(F input)
Devuelve un objeto de tipo T resultado de aplicar la función al objeto input.
boolean
equals(Object object)
Devuelve true si el objeto object es una función igual a la función con la que se invoca al
método.
Al igual que ocurría con Predicate, es aconsejable que la expresión del método apply no tenga efectos
laterales y sea consistente con equals. El método equals generalmente no lo implementaremos, sino que
utilizaremos el que se hereda de Object.
Un ejemplo de uso del tipo Function es el siguiente:
Ejemplo 5
Escriba una función que dado un libro devuelva su precio.
public class FuncionPrecioLibro implements Function<Libro, Double> {
public Double apply(Libro l) {
return l.getPrecio();
}
}
Listado 6. Clase FuncionPrecioLibro
7
http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Function.html
10. Órdenes, predicados y funciones
6. La clase de utilidad Functions
La clase de utilidad Functions8 está en el paquete com.google.common.base y, de forma similar a la clase
Predicates, proporciona dos tipos de métodos: (1) métodos de factoría; y (2) métodos para componer
funciones.
1. Métodos de factoría.
Los métodos de este grupo sirven para crear funciones de uso común. Algunos métodos de este grupo
son:
static
<E> Function<Object,E>
constant(E value)
static
<E> Function<E,E>
identity()
static
Function<Object,String>
toStringFunction()
static
<T> Function<T,Boolean>
forPredicate(Predicate<T> predicate)
static
<K,V> Function<K,V>
forMap(Map<K,V> map)
Crea una función que devuelve value para cualquier entrada.
Devuelve la función identidad.
Devuelve una función que a cada objeto le hace corresponder su
representación como cadena.
Crea una función que devuelve el mismo resultado booleano que el
predicado predicate.
Devuelve una función que hace una búsqueda en el map. Si el
elemento buscado no está en el map, se lanza la excepción
IllegalArgumentException.
2. Métodos de composición de funciones.
Los métodos de este grupo devuelven una función basada en otra u otras básicas. El único método de
este grupo es:
static
<A,B,C> Function<A,C>
compose(Function<B,C> g, Function<A,? extends B> f)
Devuelve una función resultado de componer las funciones f y g.
Un ejemplo de uso de los métodos de Functions es el siguiente:
Ejemplo 6
Suponga definida la aplicación ap y la clase llamada FuncionContarElementosLista. La aplicación ap relaciona
un autor con el conjunto de libros que ha escrito. La clase FuncionContarElementosLista, cuyo código se
muestra en el Listado 7, define una función que asocia a una lista el número de elementos que tiene. Cree
una función que asocie un autor con el número de libros que ha escrito.
8
http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/base/Functions.html
9
10
Fundamentos de Programación
public class FuncionContarElementosConjunto<T> implements Function<Set<T>, Integer> {
public Integer apply(Set<T> conjunto) {
return conjunto.size();
}
}
Listado 7. Clase FuncionContarElementosLista
Map<Persona, Set<Libro>> ap = ...
Function<Persona, Set<Libro>> f = Functions.forMap (ap);
Function<Set<Libro>,Integer> g = new FuncionContarElementosConjunto<Libro>();
Function<Persona, Integer> resultado = Functions.compose(g,f);
Listado 8. Composición de funciones mediante Functions.compose
7. Acciones
En determinados casos se necesitarán funciones que en lugar de obtener un objeto a partir de otro lo que
hagan es una modificación de dicho objeto. Dichas funciones se llaman acciones9. Una acción no es más que
una función que no devuelve nada y que tiene efectos laterales. Para definir las acciones nos basamos en el
tipo Function y decimos que una acción es de tipo Function<F,Void>. El tipo Void es el tipo envoltura de void.
Cuando trabajamos con tipos genéricos no se pueden usar tipos básicos, por eso es necesario usar Void.
Un ejemplo de acción es el siguiente:
Ejemplo 7
Escriba una acción que ponga el precio de un libro a cero.
public class AccionLibroGratis implements Function<Libro, Void> {
public Void apply(Libro l) {
l.setPrecio(0.0);
return null;
}
}
Listado 9. Clase AccionLibroGratis
Observe que es necesario poner return null porque el compilador obliga a poner un return cuando se trabaja
con objetos y, en este caso, el método apply trabaja con Void.
8. Ejercicios propuestos
Ejercicio 1
Dados los tipos Libro y Persona, vistos en temas anteriores y cuyas interfaces se muestran a continuación, se
pide:
9
El concepto de acción es propio de la asignatura y no está definido en la librería Guava.
10. Órdenes, predicados y funciones
public interface Libro extends Comparable<Libro> {
String getISBN();
String getTitulo();
void setTitulo(String titulo);
Persona getAutor();
void setAutor(Persona p);
Integer getNumPaginas();
void setNumPaginas(Integer n);
Double getPrecio();
void setPrecio(Double precio);
Boolean getEsBestSeller();
void setEsBestSeller(Boolean b);
}
public interface Persona extends
Comparable<Persona> {
String getDNI();
String getNombre();
void setNombre(String nombre);
String getApellidos();
void setApellidos(String apellidos);
}
a) En la clase de utilidad Libros, añada cuatros métodos tales que, dada una lista de libros, respondan a las
siguientes preguntas:
 ¿cuál es el menor según el orden natural?
 ¿cuál es el que tiene más páginas?
 ¿cuál es el más barato?
 Ordene dicha lista según el apellido del autor que ha escrito el libro
b) En la clase de utilidad Personas, cree un método que dado un conjunto de personas y un
Map<Persona,Set<Libro>> que asocia un autor con el conjunto de libros que ha escrito, indique cuál es el
autor que ha escrito más libros.
Ejercicio 2
Escriba los siguientes métodos en una clase de utilidad llamada EjerciciosTema10:
a) Un método que a partir del nombre de un fichero de texto y una cadena linea que representa una línea
del fichero, devuelva el índice que ocuparía esa línea si el fichero estuviera ordenado alfabéticamente
por líneas. Si linea no fuera una línea del fichero, el método devolverá un número negativo. Para
resolverlo: (1) obtenga una lista de las líneas del fichero de texto, (2) ordénela alfabéticamente, y (3)
haga una búsqueda binaria en el fichero.
b) Un método que a partir de una lista de libros devuelva el libro más caro.
c) Repita el ejercicio anterior, pero teniendo en cuenta que puede haber objetos null en la lista de libros.
d) Obtenga el libro menor si la lista se ordena según su representación como cadena.
Ejercicio 3
Construya los siguientes predicados sobre objetos de tipo Libro:
a) Un predicado que indique si un libro tiene un precio inferior a uno dado.
b) Un predicado que indique si un libro tiene un número de páginas superior o igual a uno dado como
parámetro.
c) Un predicado que indique si un libro está escrito por un autor de nombre dado.
d) Suponiendo definido un Map<Persona,Set<Libro>> que asocia un autor con el conjunto de libros que ha
escrito, se pide definir un predicado que indique si un autor ha escrito más de un número de libros dado.
11
12
Fundamentos de Programación
e) Un predicado que indique si un libro pertenece a un conjunto de libros dado.
f) Un predicado que indique si un libro tiene un número de páginas mayor o igual que 100 y menor de 500.
g) Un predicado que indique si un libro tiene menos de 100 páginas o cuesta menos de 9.90 euros.
Ejercicio 4
Construya las siguientes funciones sobre objetos de tipo Libro:
a) Una función que dado un libro devuelva el nombre del autor que lo ha escrito.
b) Una función que dado un libro devuelva el número de páginas que tiene.
c) Suponiendo definido un Map<Persona,Set<Libro>> que asocia un autor con el conjunto de libros que ha
escrito, escriba una función que dado un autor devuelva el conjunto de libros que ha escrito.
d) Escriba una función que dado un conjunto de libros devuelva cuál es el más caro.
e) Suponiendo definido un Map<Persona,Set<Libro>> que asocia un autor con el conjunto de libros que ha
escrito, escriba una función que dado un autor devuelva cuál es el libro más caro de los que ha escrito.
Ejercicio 5
Sin hacer uso de los métodos de las clases Predicates y/o Functions, escriba el código de las siguientes clases:
a) Una clase de tipo Predicate<T> llamada PredicadoY, que dados dos predicados, pred1 y pred2, de tipo
Predicate<T>, realice la conjunción de los mismos.
b) Una clase de tipo Function<A,C> llamada FuncionCompuesta, que dados dos funciones, func1 (de tipo
Function<A,B>) y func2, de tipo Function<B,C>, realice la composición de las dos funciones.
10. Órdenes, predicados y funciones
Anexo
public class Ordering {
// Métodos de creación de objetos Ordering
public static <T> Ordering<T> from(Comparator<T> comparator) {…}
public static <C extends Comparable> Ordering<C> natural (){…}
public static Ordering<Object> usingToString (){…}
//Métodos de manipulación de objetos Ordering
public <S extends T> Ordering<S> reverse(){…}
public <S extends T> Ordering<S> nullsFirst(){…}
public <S extends T> Ordering<S> nullsLast(){…}
public <U extends T> Ordering<U> compound(Comparator<? super U> secondaryComparator) {…}
public <F> Ordering<F> onResultOf(Function<F,? extends T> function) {…}
// Métodos de aplicación de criterios de ordenación mediante Ordering
public int binarySearch(List<? extends T> sortedList, T key) {…}
public <E extends T> List<E> sortedCopy(Iterable<E> iterable) {…}
public <E extends T> E max(Iterable<E> iterable) {…}
public <E extends T> E max(E a, E b, E c, E... rest) {…}
public <E extends T> E max(E a, E b) {…}
public <E extends T> E min(Iterable<E> iterable) {…}
public <E extends T> E min(E a, E b, E c, E... rest) {…}
public <E extends T> E min(E a, E b) {…}
…
}
public interface Predicate<T> {
public interface Function<F, T> {
boolean apply (T o);
T apply (F o);
boolean equals (Object o);
boolean equals (Object o);
}
}
public class Predicates {
public static <T> Predicate<T> alwaysTrue(){…}
public static <T> Predicate<T> alwaysFalse(){…}
public static <T> Predicate<T> equalTo(T target){…}
public static <T> Predicate<T> isNull(){…}
public static <T> Predicate<T> notNull(){…}
public static <T> Predicate<T> in(Collection<? extends T> target) {…}
public static <T> Predicate<T> not(Predicate<T> predicate) {…}
public static <T> Predicate<T> and(Predicate<? super T>... components) {…}
public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {…}
public static <T> Predicate<T> or(Predicate<? super T>... components) {…}
public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {…}
public static <A,B> Predicate<A> compose(Predicate<B> predicate, Function<A,? extends B> function) {…}
…}
public class Functions {
public static <E> Function<Object,E> constant(E value) {…}
public static Function<Object,String> toStringFunction(){…}
public static <E> Function<E,E> identity(){…}
public static <T> Function<T,Boolean> forPredicate(Predicate<T> predicate) {…}
public static <K,V> Function<K,V> forMap(Map<K,V> map) {…}
public static <A,B,C> Function<A,C> compose(Function<B,C> g, Function<A,? extends B> f) {…}
}
13
Descargar