Predicato Java 8 incorporato che restituisce sempre true?


129

Google Guava ha un predicato che ritorna sempretrue . Java 8 ha qualcosa di simile per i suoi Predicate? So che potrei usare (foo)->{return true;}, ma voglio qualcosa di pre-fatto, analogo a Collections.emptySet().

Risposte:


162

Non ci sono predicati sempre veri e sempre falsi in Java 8. Il modo più conciso per scrivere questi è

x -> true

e

x -> false

Confronta questi con

Predicates.alwaysTrue() // Guava

e infine a una classe interna anonima:

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

Probabilmente il motivo per cui Guava ha questi predicati integrati è che esiste un enorme vantaggio sintattico di una chiamata di metodo statico rispetto a una classe interna anonima. In Java 8, la sintassi lambda è così concisa che esiste uno svantaggio sintattico nello scrivere una chiamata di metodo statica.

Questo è solo un confronto sintattico, però. Vi è probabilmente un piccolo vantaggio in termini di spazio se esistesse un unico predicato sempre vero globale, rispetto alle x -> trueoccorrenze distribuite su più classi, ognuna delle quali creerebbe la propria istanza del predicato. È di questo che ti preoccupi? I risparmi non sembravano convincenti, motivo per cui non sono stati aggiunti in primo luogo. Ma potrebbe essere riconsiderato per una versione futura.

AGGIORNAMENTO 2015-04-24

Abbiamo considerato l'aggiunta di una varietà di statica, funzioni con nome, come Predicate.alwaysTrue, Runnable.noope così via, e noi abbiamo deciso di non aggiungere altro nelle future versioni di Java SE.

Certamente c'è un valore in qualcosa che ha un nome rispetto a un lambda scritto, ma questo valore è piuttosto piccolo. Ci aspettiamo che la gente imparare a leggere e scrivere x -> truee () -> { }e che il loro utilizzo diventi idiomatica. Anche il valore di Function.identity()over x -> xè discutibile.

C'è un piccolo vantaggio in termini di prestazioni nel riutilizzare una funzione esistente invece di valutare un lambda scritto, ma ci aspettiamo che l'uso di questo tipo di funzioni sia così piccolo che un tale vantaggio sarebbe trascurabile, certamente non vale la pena dell'API.

Holger ha anche menzionato nei commenti la possibilità di ottimizzare funzioni composte come Predicate.ore tali. Anche questo è stato considerato ( JDK-8067971 ), ma è stato considerato un po 'fragile e soggetto a errori, e si verifica abbastanza raramente da non valere lo sforzo di implementarlo.

Vedi anche questa voce FAQ su Lambda .


14
Due preoccupazioni: la prima è la brevità. Se (foo)->{return true;}è il meglio che posso fare, voglio di meglio. Ma hai sollevato x->true, il che è molto meglio e mitiga il primo problema. Il secondo problema riguarda la logica e la dichiarazione statica. Se uso x->true, c'è ancora la logica in questione, che potrei inavvertitamente rovinare (ad es x->!true.). Ma con Predicate.alwaysTrue(), non c'è spazio per l'errore logico, poiché esistono solo uno o due metodi simili. Inoltre ottengo il completamento del codice IDE gratuitamente. x->trueva quasi bene, ma ho ancora scritto un Predicate.alwaysTrue()metodo per i motivi sopra.
Garret Wilson,

10
@GarretWilson Ma con Predicate.alwaysTrue()te potresti anche rovinare scrivendo accidentalmente Predicate.alwaysFalse().
David Conrad,

5
@DavidConrad, ovviamente. Ci sono sempre modi in cui posso commettere errori, e infatti ne sto inventando costantemente di nuovi. ;) Non voglio iniziare qui una discussione su qualcosa di banale, ma dirò solo che il mio punto è che con un riferimento al metodo statico ho un vocabolario vincolato con solo due scelte: alwaysTrue()e alwaysFalse(). Con l'attuale lambda, ho molte varianti; Sto essenzialmente ricostruendo la formula ogni volta. In sostanza, alwaysTrue()è un'etichetta semantica per ciò che voglio fare; x->truelo sta facendo di nuovo ogni volta. Non enorme, ma una considerazione.
Garret Wilson,

25
Uno dei grandi vantaggi della canonica Predicate.alwaysTrue()e Predicate.alwaysFalse()istanze è, che potevano essere riconosciuti dalla combinazione di metodi come Predicate.or, Predicate.ande Predicate.negate(). Ciò consentirebbe di pre-inizializzare le Predicatevariabili con alwaysTrue()e aggiungere predicati combinando via andsenza sovraccarico. Poiché le espressioni lambda non hanno alcuna garanzia di identità degli oggetti, ciò potrebbe non riuscire x->true. A proposito, se ho una classe Xcon un staticmetodo y(){return true;}, l'utilizzo X::yè ancora più breve di x->truema non è davvero consigliato ...
Holger,

10
Il linguaggio x -> trueha lo svantaggio che devo usare una variabile senza usare. Questo crea inutili carichi cerebrali e anche un avvertimento nel mio IDE. Ho provato a usare _ -> true, ma questo è un errore di sintassi. A Java manca sicuramente una parola chiave (leggi: keyletter) per "parametro inutilizzato". Spero che qualcosa di simile arriverà in Java 9 (o almeno: Java qualunque cosa io muoia prima ^^)
kap

4

Senza guava

Boolean.TRUE::booleanValue

3
Interessante. Non sono sicuro che catturi completamente lo spirito della richiesta, ma ottiene punti per la creatività!
Garret Wilson,

21
Ma non è un Predicate, in quanto non accetta una discussione.
Florent Guillaume,

1
Non è un predicato, è un riferimento al metodo ma ha il merito di essere conciso e di non forzare a menzionare un parametro inutilizzato. +1 A proposito, poiché evita di usare Guava che ha un grave problema di modularità, merita il mio voto;)
gouessej

16
Il riferimento al metodo è assegnabile al fornitore <Boolean> ma non Predicate <T>
Daniel K.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.