garret wilson
Google Guava tiene un predicado que siempre regresa true
. ¿Java 8 tiene algo similar para su Predicate
? Sé que podría usar (foo)->{return true;}
pero quiero algo prefabricado, análogo a Collections.emptySet()
.
marcas de estuardo
No hay predicados siempre verdaderos y siempre falsos integrados en Java 8. La forma más concisa de escribirlos es
x -> true
y
x -> false
Compara estos con
Predicates.alwaysTrue() // Guava
y finalmente a una clase interna anónima:
new Predicate<Object>() {
public boolean test(Object x) {
return true;
}
}
Probablemente la razón por la que Guava tiene estos predicados incorporados es que existe una gran ventaja sintáctica de una llamada de método estático sobre una clase interna anónima. En Java 8, la sintaxis lambda es tan concisa que hay una sintaxis desventaja para escribir una llamada de método estático.
Sin embargo, eso es solo una comparación sintáctica. Probablemente haya una pequeña ventaja de espacio si hubiera un solo predicado global siempre verdadero, en comparación con x -> true
las ocurrencias se distribuyen en múltiples clases, cada una de las cuales crearía su propia instancia de predicado. ¿Es esto lo que te preocupa? Los ahorros no parecían convincentes, por lo que probablemente no se agregaron en primer lugar. Pero podría reconsiderarse para una versión futura.
ACTUALIZACIÓN 2015-04-24
Hemos considerado la adición de una variedad de funciones estáticas con nombre, como Predicate.alwaysTrue
, Runnable.noop
etc., y hemos decidido no añadir más en futuras versiones de Java SE.
Ciertamente, hay algo de valor en algo que tiene un nombre frente a una lambda escrita, pero este valor es bastante pequeño. Esperamos que la gente aprenda a leer y escribir x -> true
y () -> { }
y que su uso se volverá idiomático. Incluso el valor de Function.identity()
sobre x -> x
es cuestionable.
Hay una pequeña ventaja de rendimiento en reutilizar una función existente en lugar de evaluar una lambda escrita, pero esperamos que el uso de este tipo de funciones sea tan pequeño que tal ventaja sería insignificante, ciertamente no vale la pena el exceso de API.
Holger también mencionó en los comentarios la posibilidad de optimizar funciones compuestas como Predicate.or
y tal. Esto también fue considerado (JDK-8067971) pero se consideró un tanto frágil y propenso a errores, y ocurría con la frecuencia suficiente como para que no valiera la pena el esfuerzo de implementarlo.
Ver también esto Preguntas frecuentes sobre Lambda entrada.
-
Dos preocupaciones: la primera es la brevedad. Si
(foo)->{return true;}
es lo mejor que puedo hacer, quiero algo mejor. pero lo mencionastex->true
, que es mucho mejor y mitiga el primer problema. El segundo problema es de lógica frente a declaración estática. si usox->true
todavía hay lógica involucrada, que podría arruinar sin darme cuenta (por ejemplo,x->!true
). Pero conPredicate.alwaysTrue()
, no hay margen para el error lógico, ya que solo hay uno o dos métodos similares. Además, obtengo la finalización del código IDE de forma gratuita.x->true
está casi bien, pero aún así escribí unPredicate.alwaysTrue()
método por las razones anteriores.– Garret Wilson
24/10/2014 a las 23:54
-
@GarretWilson Pero con
Predicate.alwaysTrue()
también podrías equivocarte al escribir accidentalmentePredicate.alwaysFalse()
.– David Conrado
25 de octubre de 2014 a las 1:26
-
@DavidConrad, por supuesto. Siempre hay formas en las que puedo cometer errores y, de hecho, estoy constantemente inventando otras nuevas. 😉 No quiero comenzar una discusión aquí sobre algo trivial, pero solo diré que mi punto es que con una referencia de método estático tengo un vocabulario restringido con solo dos opciones:
alwaysTrue()
yalwaysFalse()
. Con la lambda real, tengo muchas variaciones; Básicamente estoy reconstruyendo la fórmula cada vez. En esencia,alwaysTrue()
es una etiqueta semántica de lo que quiero hacer;x->true
en realidad lo está haciendo de nuevo cada vez. No enorme, pero una consideración.– Garret Wilson
25 de octubre de 2014 a las 1:33
-
Una gran ventaja de canonical
Predicate.alwaysTrue()
yPredicate.alwaysFalse()
casos es, que podrían ser reconocidos mediante la combinación de métodos comoPredicate.or
,Predicate.and
yPredicate.negate()
. Esto permitiría pre-inicializarPredicate
variable conalwaysTrue()
y agregue predicados combinando a través deand
sin sobrecarga. Dado que las expresiones lambda no tienen garantía de identidad de objeto, esto podría fallar conx->true
. Por cierto, si tengo una claseX
con unstatic
métodoy(){return true;}
usandoX::y
es incluso más corto quex->true
pero no muy recomendable…– Holger
27/10/2014 a las 10:45
-
el idioma
x -> true
tiene el inconveniente de que tengo que usar una variable sin uso. Esto crea una carga cerebral innecesaria y también una advertencia en mi IDE. traté de usar_ -> true
, pero eso es un error de sintaxis. Definitivamente a Java le falta una palabra clave (léase: letra clave) para “parámetro no utilizado”. Espero que algo como esto venga en Java 9 (o al menos: Java lo que sea antes de morir ^^)– cap
10 de noviembre de 2015 a las 21:27
En caso de que esté buscando esto en Spring framework:
org.springframework.data.util.Predicates
apoya esto.
Predicates.isTrue()
, Predicates.isFalse()
borisele
Sin guayaba
Boolean.TRUE::booleanValue
-
Eso es interesante. No estoy seguro de si captura completamente el espíritu de la solicitud, ¡pero obtiene puntos por creatividad!
– Garret Wilson
21 de octubre de 2017 a las 1:16
-
pero no es un
Predicate
ya que no requiere argumento.– Florent Guillaume
31 de octubre de 2017 a las 12:12
-
No es un predicado, es una referencia de método pero tiene el mérito de ser conciso y no obligar a mencionar un parámetro no utilizado. +1 Por cierto, como evita usar Guava que tiene un grave problema de modularidad, merece mi voto a favor 😉
– gouessej
20 de febrero de 2018 a las 16:57
-
La referencia de su método se puede asignar a Proveedor
pero no a Predicado – daniel k.
25 de mayo de 2018 a las 10:13
-
Gente: por favor deja de votar esto! esta respuesta es simplemente incorrecto. Tú no poder escribe
Predicate<Whatever> p = Boolean.TRUE::booleanValue
porquebooleanValue()
no acepta ningún argumento. Simplemente podría usarlo comoSupplier<Boolean>
(como dice Daniel), que no responde la pregunta (y probablemente rara vez sea útil).– Didier L.
7 de febrero a las 19:35