Prédicat Java 8 intégré qui renvoie toujours vrai?

129

Google Guava a un prédicat qui revient toujourstrue . Java 8 a-t-il quelque chose de similaire pour son Predicate? Je sais que je pourrais utiliser (foo)->{return true;}, mais je veux quelque chose de préfabriqué, analogue à Collections.emptySet().

Garret Wilson
la source

Réponses:

162

Il n'y a pas de prédicats intégrés toujours vrais et toujours faux dans Java 8. La façon la plus concise de les écrire est

x -> true

et

x -> false

Comparez-les à

Predicates.alwaysTrue() // Guava

et enfin à une classe interne anonyme:

new Predicate<Object>() {
    public boolean test(Object x) {
        return true;
    }
}

La raison pour laquelle Guava a ces prédicats intégrés est probablement qu'il y a un énorme avantage syntaxique à un appel de méthode statique par rapport à une classe interne anonyme. Dans Java 8, la syntaxe lambda est si concise qu'il existe un inconvénient syntaxique à l'écriture d'un appel de méthode statique.

C'est juste une comparaison syntaxique, cependant. Il y a probablement un petit avantage d'espace s'il y avait un seul prédicat global toujours vrai, par rapport aux x -> trueoccurrences réparties sur plusieurs classes, chacune créant sa propre instance de prédicat. Est-ce cela qui vous préoccupe? Les économies ne semblaient pas convaincantes, ce qui explique probablement pourquoi elles n'ont pas été ajoutées en premier lieu. Mais il pourrait être reconsidéré pour une future version.

MISE À JOUR 2015-04-24

Nous avons considéré l'ajout d'une variété de statique, des fonctions telles que nommées Predicate.alwaysTrue, Runnable.noopetc., et nous avons décidé de ne pas ajouter plus dans les futures versions de Java SE.

Il y a certainement une valeur dans quelque chose qui a un nom par rapport à un lambda écrit, mais cette valeur est assez petite. Nous nous attendons à ce que les gens vont apprendre à lire et à écrire x -> trueet () -> { }et que leur utilisation deviendra idiomatiques. Même la valeur de Function.identity()over x -> xest discutable.

Il y a un petit avantage en termes de performances à réutiliser une fonction existante au lieu d'évaluer un lambda écrit, mais nous nous attendons à ce que l'utilisation de ces types de fonctions soit si faible qu'un tel avantage serait négligeable, ne valant certainement pas le gonflement de l'API.

Holger a également mentionné dans les commentaires la possibilité d'optimiser des fonctions composées telles que Predicate.oret telles. Cela a également été pris en compte ( JDK-8067971 ) mais a été jugé quelque peu fragile et sujet aux erreurs, et se produisant assez rarement pour que la mise en œuvre ne valait pas la peine.

Consultez également cette entrée de la FAQ Lambda .

Marques Stuart
la source
14
Deux préoccupations: la première est la brièveté. Si (foo)->{return true;}c'est le mieux que je puisse faire, je veux mieux. Mais vous avez évoqué x->true, ce qui est bien mieux et atténue le premier problème. Le deuxième problème concerne la déclaration logique vs statique. Si j'utilise x->true, il y a toujours une logique impliquée, que je pourrais bousiller par inadvertance (par exemple x->!true). Mais avec Predicate.alwaysTrue(), il n'y a aucune place pour l'erreur logique, car il n'y a qu'une ou deux méthodes similaires. De plus, j'obtiens la complétion du code IDE gratuitement. x->truec'est presque bien, mais j'ai quand même écrit une Predicate.alwaysTrue()méthode pour les raisons ci-dessus.
Garret Wilson
10
@GarretWilson Mais avec Predicate.alwaysTrue()vous, vous pourriez aussi vous tromper en écrivant accidentellement Predicate.alwaysFalse().
David Conrad
5
@DavidConrad, bien sûr. Il y a toujours des façons dont je peux faire des erreurs, et en fait j'en invente constamment de nouvelles. ;) Je ne veux pas commencer un argument ici sur quelque chose de trivial, mais je dirai simplement que mon point est qu'avec une référence de méthode statique j'ai un vocabulaire contraint avec seulement deux choix: alwaysTrue()et alwaysFalse(). Avec le lambda actuel, j'ai de nombreuses variantes; Je reconstruis essentiellement la formule à chaque fois. En substance, alwaysTrue()est une étiquette sémantique pour ce que je veux faire; x->truerecommence en fait à chaque fois. Pas énorme, mais une considération.
Garret Wilson
25
Un grand avantage de Canonical Predicate.alwaysTrue()et les Predicate.alwaysFalse()instances est, qu'ils pourraient être reconnus en combinant des méthodes telles que Predicate.or, Predicate.andet Predicate.negate(). Cela permettrait de pré-initialiser des Predicatevariables avec alwaysTrue()et d'ajouter des prédicats en combinant via andsans surcharge. Étant donné que les expressions lambda n'ont aucune garantie d'identité d'objet, cela peut échouer avec x->true. Au fait, si j'ai une classe Xavec une staticméthode y(){return true;}, l'utilisation X::yest encore plus courte x->truemais pas vraiment recommandée…
Holger
10
L'idiome x -> truea l'inconvénient que je dois utiliser une variable sans utilisation. Cela crée une charge cérébrale inutile et aussi un avertissement dans mon IDE. J'ai essayé d'utiliser _ -> true, mais c'est une erreur de syntaxe. Il manque définitivement à Java un mot-clé (lire: keyletter) pour "paramètre non utilisé". J'espère que quelque chose comme ça viendra dans Java 9 (ou du moins: Java peu importe avant de mourir ^^)
kap
4

Sans goyave

Boolean.TRUE::booleanValue
boriselec
la source
3
C'est intéressant. Je ne sais pas si cela reflète complètement l'esprit de la demande, mais cela rapporte des points pour la créativité!
Garret Wilson
21
Mais ce n'est pas un Predicate, car cela ne prend pas d'argument.
Florent Guillaume
1
Ce n'est pas un prédicat, c'est une référence de méthode mais il a le mérite d'être concis et de ne pas obliger à mentionner un paramètre inutilisé. +1 D'ailleurs, comme cela évite d'utiliser Guava qui a un sérieux problème de modularité, il mérite mon vote positif;)
gouessej
16
La référence de votre méthode est assignable au fournisseur <Booléen> mais pas au prédicat <T>
Daniel K.