java - tipos - sujeto y predicado
¿Cuál es la diferencia entre un Predicado y una Interfaz de función en Java8? (6)
Diferencia entre Predicate<T>
y Function<T, R>
En primer lugar, un Predicate<T>
es estrictamente una función de valor booleano:
_ _ _ _ _ _ _
| |
T --> | predicate | --> boolean
|_ _ _ _ _ _ _|
Considerando que esto no es necesariamente cierto para una Function<T, R>
:
_ _ _ _ _ _ _
| |
T --> | function | --> R
|_ _ _ _ _ _ _|
Este último consume cualquier tipo de objeto al igual que Predicate<T>
habilita, pero puede variar en el tipo de retorno.
Caso de uso de Predicate<T>
y Function<T, R>
El caso de uso de Predicate<T>
es cuando se requiere una función que consume un argumento de tipo T
y devuelve un valor booleano. por ejemplo, puede estar en una situación en la que desee filtrar un flujo de elementos, busque el primer elemento de un flujo que satisfaga una condición como tal de .filter(predicate).findFirst()
, o .filter(predicate).findFirst()
la presencia de un elemento en un transmisión que satisface una determinada condición como la de anyMatch
, noneMatch
, allMatch
etc.
El caso de uso para la Function<T, R>
es cuando necesita una función que consume un argumento de tipo T
y la transforma en un tipo R
por ejemplo, que puede ser cuando se llama a stream.map(func)
.
Explicación de su fragmento de código:
En lo que respecta al fragmento de ejemplo en tu publicación, Predicate<String>
y Function<String, Boolean>
son lo mismo en términos de lo que representan, es decir, ambos representan una función que toma una String
y devuelve un boolean
. Sin embargo, el primero evita encasillar el valor devuelto de boolean
a Boolean
mientras que el segundo no lo hace.
Dicho esto, esto no significa necesariamente que siempre que pueda usar un Predicate<String>
también puede usar una Function<String, Boolean>
o viceversa.
Ejemplo:
Mientras esto compila:
Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);
Esto no lo hace:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);
y viceversa:
Mientras esto funciona:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);
Esto no lo hace:
Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);
Sé que puede ser una pregunta muy básica sobre SO, pero quiero saber cuál es la diferencia entre un Predicate
y una Function
Interface en Java8.
Predicate<String> predicateTest = (s)-> s.length() > 5;
System.out.println(predicateTest.test("Predicate"));
Function<String, Boolean> functionTest = str -> str.length()> 5;
System.out.println(functionTest.apply("Function"));
Aquí en mi Ejemplo, ambos están volviendo true
. ¿La única forma de llamar es diferente?
Realmente no hay diferencia.
En teoría, no debería haber ninguna diferencia funcional entre Predicate<T>
y Function<T, Boolean>
. Un Predicate
es solo una función que toma un objeto de algún tipo y devuelve un booleano. Una Function
es una generalización que puede devolver cualquier tipo, no solo Boolean
.
Puede haber detalles de implementación dentro de Java que los distingan, pero en teoría deberían ser los mismos.
Un ejemplo sería si una interfaz solo pudiera aceptar un Predicate<String>
, no una Function<String, Boolean
.
Desde un punto de vista técnico, un Predicate<T>
es solo una función que toma una T
y devuelve un resultado booleano primitivo. Sin embargo, desde un punto de vista de uso, un Predicate<T>
es un concepto totalmente diferente al de una Function<T, Boolean>
.
Usamos un Predicate<T>
para realizar una operación de filtro, por ejemplo, en un canal de flujo, tomamos un Stream<T>
de tamaño n
, lo filtramos usando un Predicate<T>
para obtener un flujo de tamaño menor o igual que n
. Mientras tanto, se utiliza una Function<T, Boolean>
en una tubería de flujo para realizar una operación de mapeo para transformar un Stream<T>
en un Stream<Boolean>
.
Como puede ver, el Predicate<T>
y una Function<T, Boolean>
son técnicamente iguales (ignorando el envoltorio Boolean
por simplicidad), pero cuando se ponen en un contexto específico (por ejemplo, canales de flujo), es una historia totalmente diferente. Como cada uno de ellos juega un papel distinto.
En este caso, no hay diferencia, solo es importante para las cosas a las que puede aplicar. Entonces, por ejemplo, allMatch
espera un Predicate
, no puede pasar una Function
, incluso si lógicamente hacen lo mismo.
La respuesta de Aominè cubre las diferencias básicas. Me gustaría agregar que las dos interfaces también tienen diferentes métodos predeterminados especializados, es decir, métodos que puede llamar en cualquier clase de implementación:
-
Predicate<T>
-
Predicate<T> and(Predicate<? super T> other)
- Devuelve un predicado compuesto que representa un AND lógico de cortocircuito de este predicado y otro. -
Predicate<T> or(Predicate<? super T> other)
- Devuelve un predicado compuesto que representa un OR lógico de cortocircuito de este predicado y otro. -
negate()
: devuelve un predicado que representa la negación lógica de este predicado.
-
-
Function<T,R>
-
<V> Function<T,V> andThen(Function<? super R,? extends V> after)
: devuelve una función compuesta que primero aplica esta función a su entrada y luego aplica la funciónafter
al resultado. -
<V> Function<V,R> compose(Function<? super V,? extends T> before)
: devuelve una función compuesta que primero aplica la funciónbefore
a su entrada, y luego aplica esta función al resultado.
-
Como puede ver, Predicate
tiene métodos útiles para crear condiciones complejas, como los operadores que usaría en una declaración if
regular, mientras que Function
tiene métodos que admiten el encadenamiento simple.
Un Predicate
solo puede devolver un valor boolean
(resultado de la test()
) mientras que la Function
realiza una transformación y puede devolver cualquier cosa (resultado de apply()
).
Se utiliza un Predicate
para probar una condición.
Una Function
se utiliza para hacer una transformación.