Predicado Java 8 incorporado que siempre devuelve verdadero?

129

Google Guava tiene un predicado que siempre regresatrue . ¿Java 8 tiene algo similar para esto Predicate? Sé que podría usar (foo)->{return true;}, pero quiero algo prefabricado, similar a Collections.emptySet().

Garret Wilson
fuente

Respuestas:

162

No hay predicados integrados siempre verdaderos y siempre falsos en Java 8. La forma más concisa de escribirlos es

x -> true

y

x -> false

Compare 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 hay 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 existe una desventaja sintáctica al escribir una llamada a un 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 las x -> trueocurrencias repartidas en varias 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 un lanzamiento futuro.

ACTUALIZACIÓN 2015-04-24

Hemos considerado la adición de una variedad de estática, funciones con nombre, como Predicate.alwaysTrue, Runnable.noop, etc., y hemos decidido no añadir nada 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 va a aprender a leer y escribir x -> truey () -> { }, y que su uso se convertirá en idiomática. Incluso el valor de Function.identity()over x -> xes cuestionable.

Existe una pequeña ventaja de rendimiento al 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 dicha ventaja sería insignificante, ciertamente no vale la pena el aumento de API.

Holger también mencionó en los comentarios la posibilidad de optimizar funciones compuestas tales como Predicate.ory tales. Esto también se consideró ( JDK-8067971 ), pero se consideró algo frágil y propenso a errores, y ocurría con poca frecuencia como para que no valiera la pena implementarlo.

Consulte también esta entrada de Preguntas frecuentes de Lambda .

Stuart Marks
fuente
14
Dos preocupaciones: la primera es la brevedad. Si (foo)->{return true;}es lo mejor que puedo hacer, quiero algo mejor. Pero lo mencionaste x->true, lo cual es mucho mejor y mitiga el primer problema. El segundo problema es de lógica frente a declaración estática. Si lo uso x->true, todavía hay lógica involucrada, que podría arruinar inadvertidamente (por ejemplo x->!true). Pero con Predicate.alwaysTrue(), hay cero espacio para el error lógico, ya que solo hay uno o dos métodos similares. Además, recibo la finalización del código IDE de forma gratuita. x->trueestá casi bien, pero aún escribí un Predicate.alwaysTrue()método por los motivos anteriores.
Garret Wilson
10
@GarretWilson Pero Predicate.alwaysTrue()contigo también podrías equivocarte escribiendo accidentalmente Predicate.alwaysFalse().
David Conrad
55
@DavidConrad, por supuesto. Siempre hay formas en que puedo cometer errores, y de hecho constantemente invento nuevos. ;) 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()y alwaysFalse(). Con la lambda real, tengo muchas variaciones; Básicamente estoy reconstruyendo la fórmula cada vez. En esencia, alwaysTrue()es una etiqueta semántica para lo que quiero hacer; x->trueen realidad lo está haciendo de nuevo cada vez. No es enorme, pero una consideración.
Garret Wilson
25
Una gran ventaja de canónica Predicate.alwaysTrue()y Predicate.alwaysFalse()casos es, que podrían ser reconocidos por la combinación de métodos como Predicate.or, Predicate.and, y Predicate.negate(). Esto permitiría preinicializar Predicatevariables con alwaysTrue()y agregar predicados combinando vía andsin sobrecarga. Dado que las expresiones lambda no tienen garantía de identidad de objeto, esto podría fallar x->true. Por cierto, si tengo una clase Xcon un staticmétodo y(){return true;}, el uso X::yes aún más corto x->truepero no realmente recomendado ...
Holger
10
El idioma x -> truetiene la desventaja de que tengo que usar una variable sin usar. 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. A Java definitivamente le falta una palabra clave (léase: keyletter) para "parámetro no utilizado". Espero que algo así llegue en Java 9 (o al menos: Java lo que sea antes de morir ^^)
kap
4

Sin guayaba

Boolean.TRUE::booleanValue
boriselec
fuente
3
Eso es interesante. No estoy seguro de si captura completamente el espíritu de la solicitud, ¡pero obtiene puntos por creatividad!
Garret Wilson el
21
Pero no es un Predicate, ya que no requiere una discusión.
Florent Guillaume
1
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, ya que evita usar la guayaba que tiene un grave problema de modularidad, merece mi
voto positivo
16
La referencia de su método se puede asignar al Proveedor <Boolean> pero no al Predicado <T>
Daniel K.