Eingebautes Java 8-Prädikat, das immer true zurückgibt?

128

Google Guava hat ein Prädikat, das immer zurückgibttrue . Hat Java 8 etwas Ähnliches Predicate? Ich weiß, ich könnte es gebrauchen (foo)->{return true;}, aber ich möchte etwas Vorgefertigtes, analog zu Collections.emptySet().

Garret Wilson
quelle

Antworten:

161

In Java 8 gibt es keine integrierten Prädikate für immer wahr und immer falsch. Die präziseste Art, diese zu schreiben, ist

x -> true

und

x -> false

Vergleichen Sie diese mit

Predicates.alwaysTrue() // Guava

und schließlich zu einer anonymen inneren Klasse:

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

Wahrscheinlich liegt der Grund dafür, dass Guava über diese integrierten Prädikate verfügt, darin, dass ein statischer Methodenaufruf einen großen syntaktischen Vorteil gegenüber einer anonymen inneren Klasse bietet. In Java 8 ist die Lambda-Syntax so präzise, ​​dass das Schreiben eines statischen Methodenaufrufs einen syntaktischen Nachteil hat .

Das ist jedoch nur ein syntaktischer Vergleich. Es gibt wahrscheinlich einen kleinen Platzvorteil, wenn es ein einzelnes globales immer wahres Prädikat gäbe, verglichen mit x -> trueVorkommen, die über mehrere Klassen verteilt sind, von denen jede ihre eigene Prädikatinstanz erstellen würde. Ist es das, worüber Sie sich Sorgen machen? Die Einsparungen schienen nicht zwingend zu sein, weshalb sie wahrscheinlich überhaupt nicht hinzugefügt wurden. Aber es könnte für eine zukünftige Veröffentlichung überdacht werden.

UPDATE 24.04.2015

Wir haben die Hinzufügung einer Vielzahl von statischen, benannten Funktionen in Betracht gezogen, wie z Predicate.alwaysTrue .Runnable.noop usw., und wir haben beschlossen , nicht mehr in zukünftigen Versionen von Java SE hinzuzufügen.

Sicherlich hat etwas, das einen Namen hat, einen Wert gegenüber einem ausgeschriebenen Lambda, aber dieser Wert ist ziemlich klein. Wir gehen davon aus, dass die Menschen lernen , wie man lesen und schreiben x -> trueund () -> { }und dass ihre Nutzung wird sich idiomatisch. Sogar der Wert von Function.identity()überx -> x ist fraglich.

Es ist ein winziger Leistungsvorteil, eine vorhandene Funktion wiederzuverwenden, anstatt ein ausgeschriebenes Lambda auszuwerten. Wir erwarten jedoch, dass die Verwendung dieser Art von Funktionen so gering ist, dass ein solcher Vorteil vernachlässigbar wäre und die API-Aufblähung sicherlich nicht wert wäre.

Holger erwähnte in Kommentaren auch die Möglichkeit, zusammengesetzte Funktionen wie Predicate.orund so zu optimieren . Dies wurde ebenfalls berücksichtigt ( JDK-8067971) ), wurde jedoch als etwas fragil und fehleranfällig eingestuft und trat selten genug auf, dass sich die Implementierung nicht lohnte.

Siehe auch diesen Lambda-FAQ- Eintrag.

Stuart Marks
quelle
14
Zwei Bedenken: Die erste ist die Kürze. Wenn (foo)->{return true;}es das Beste ist, was ich tun kann, möchte ich es besser. Aber Sie haben es angesprochen x->true, was viel besser ist und das erste Problem mildert. Das zweite Problem betrifft die Logik gegenüber der statischen Deklaration. Wenn ich benutze x->true, ist immer noch Logik involviert, die ich versehentlich vermasseln könnte (zB x->!true). Bei Predicate.alwaysTrue()gibt es jedoch keinen Raum für logische Fehler, da es nur eine oder zwei ähnliche Methoden gibt. Außerdem bekomme ich die Vervollständigung des IDE-Codes kostenlos. x->trueist fast in Ordnung, aber ich habe Predicate.alwaysTrue()aus den oben genannten Gründen immer noch eine Methode geschrieben.
Garret Wilson
9
@ GarretWilson Aber mit Predicate.alwaysTrue()dir könnte man es auch vermasseln , indem man versehentlich schreibt Predicate.alwaysFalse().
David Conrad
5
@ DavidConrad natürlich. Es gibt immer Möglichkeiten, wie ich Fehler machen kann, und tatsächlich erfinde ich ständig neue. ;) Ich möchte hier keinen Streit über etwas Triviales beginnen, aber ich möchte nur sagen, dass mein Punkt darin besteht, dass ich mit einer statischen Methodenreferenz ein eingeschränktes Vokabular mit nur zwei Auswahlmöglichkeiten habe: alwaysTrue()und alwaysFalse(). Mit dem tatsächlichen Lambda habe ich viele Variationen; Ich rekonstruiere im Wesentlichen jedes Mal die Formel. Im Wesentlichen alwaysTrue()ist eine semantische Bezeichnung für das, was ich tun möchte; x->truemacht es tatsächlich jedes Mal wieder. Nicht riesig, aber eine Überlegung.
Garret Wilson
25
Ein großer Vorteil der kanonischen Predicate.alwaysTrue()und Predicate.alwaysFalse()Instanzen ist, dass sie durch die Kombination von Methoden , wie erkannt werden können Predicate.or, Predicate.andund Predicate.negate(). Dies würde es ermöglichen, PredicateVariablen vorab zu initialisieren alwaysTrue()und Prädikate hinzuzufügen, indem über andohne Overhead kombiniert wird . Da Lambda-Ausdrücke keine Garantie für die Objektidentität haben, kann dies fehlschlagen x->true. Übrigens, wenn ich eine Klasse Xmit einer staticMethode habe y(){return true;}, ist die Verwendung X::ynoch kürzer als x->trueaber nicht wirklich zu empfehlen ...
Holger
10
Die Redewendung x -> truehat den Nachteil, dass ich eine Variable ohne Verwendung verwenden muss. Dies führt zu unnötiger Gehirnlast und einer Warnung in meiner IDE. Ich habe versucht zu verwenden _ -> true, aber das ist ein Syntaxfehler. In Java fehlt definitiv ein Schlüsselwort (sprich: Keyletter) für "unbenutzte Parameter". Hoffe, dass so etwas in Java 9 kommt (oder zumindest: Java was auch immer, bevor ich sterbe ^^)
kap
4

Ohne Guave

Boolean.TRUE::booleanValue
Boriselec
quelle
3
Das ist interessant. Ich bin mir nicht sicher, ob es den Geist der Anfrage vollständig erfasst, aber es gibt Punkte für Kreativität!
Garret Wilson
21
Aber es ist kein Predicate, da es kein Argument braucht.
Florent Guillaume
1
Es ist kein Prädikat, es ist eine Methodenreferenz, aber es hat den Vorteil, dass es präzise ist und nicht gezwungen wird, einen nicht verwendeten Parameter zu erwähnen. +1 Übrigens, da es die Verwendung von Guave vermeidet, die ein ernstes Problem der Modularität aufweist, verdient es meine Zustimmung;)
gouessej
16
Ihre Methodenreferenz kann dem Lieferanten <Boolean> zugewiesen werden, nicht jedoch dem Prädikat <T>
Daniel K.,