¿Predicado incorporado de Java 8 que siempre devuelve verdadero?

6 minutos de lectura

avatar de usuario
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().

avatar de usuario
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.noopetc., 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 mencionaste x->true, que es mucho mejor y mitiga el primer problema. El segundo problema es de lógica frente a declaración estática. si uso x->truetodavía hay lógica involucrada, que podría arruinar sin darme cuenta (por ejemplo, x->!true). Pero con Predicate.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í un Predicate.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 accidentalmente Predicate.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() 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 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() y Predicate.alwaysFalse() casos es, que podrían ser reconocidos mediante la combinación de métodos como Predicate.or, Predicate.andy Predicate.negate(). Esto permitiría pre-inicializar Predicate variable con alwaysTrue() y agregue predicados combinando a través de and sin sobrecarga. Dado que las expresiones lambda no tienen garantía de identidad de objeto, esto podría fallar con x->true. Por cierto, si tengo una clase X con un static método y(){return true;}usando X::y es incluso más corto que x->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()

avatar de usuario
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 Predicateya 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 porque booleanValue() no acepta ningún argumento. Simplemente podría usarlo como Supplier<Boolean> (como dice Daniel), que no responde la pregunta (y probablemente rara vez sea útil).

    – Didier L.

    7 de febrero a las 19:35


¿Ha sido útil esta solución?