Wbudowany predykat Java 8, który zawsze zwraca prawdę?

129

Google Guava ma predykat, który zawsze zwracatrue . Czy Java 8 ma coś podobnego Predicate? Wiem, że mógłbym użyć (foo)->{return true;}, ale chcę coś gotowego, analogicznego do Collections.emptySet().

Garret Wilson
źródło

Odpowiedzi:

162

W Javie 8 nie ma wbudowanych predykatów zawsze prawdziwych i zawsze fałszywych. Najbardziej zwięzłym sposobem ich zapisania jest

x -> true

i

x -> false

Porównaj je z

Predicates.alwaysTrue() // Guava

i wreszcie do anonimowej klasy wewnętrznej:

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

Prawdopodobnie powodem, dla którego Guava ma te wbudowane predykaty, jest ogromna przewaga składniowa wywołania metody statycznej nad anonimową klasą wewnętrzną. W Javie 8 składnia lambda jest tak zwięzła, że zapisywanie wywołania metody statycznej ma wadę składniową .

To tylko porównanie składniowe. Prawdopodobnie istnieje niewielka przewaga miejsca, gdyby istniał jeden globalny predykat zawsze prawdziwy, w porównaniu z x -> truewystąpieniami rozproszonymi w wielu klasach, z których każda utworzyłaby własną instancję predykatu. Czy o to się martwisz? Oszczędności nie wydawały się przekonujące i prawdopodobnie dlatego nie zostały dodane w pierwszej kolejności. Ale można by to ponownie rozważyć pod kątem przyszłej wersji.

UPDATE 2015-04-24

Musimy rozważyć dodanie różnych statycznych, nazwanych funkcji, takich jak Predicate.alwaysTrue, Runnable.noopitp, a my nie zdecydowała się dodać więcej w przyszłości wersji Java SE.

Z pewnością jest jakaś wartość w czymś, co ma nazwę, w porównaniu z wypisaną lambdą, ale ta wartość jest dość mała. Oczekujemy, że ludzie nauczą się czytać i pisać, x -> truea () -> { }ich używanie stanie się idiomatyczne. Nawet wartość Function.identity()over x -> xjest wątpliwa.

Ponowne wykorzystanie istniejącej funkcji zamiast szacowania wypisanej lambdy ma niewielką zaletę w zakresie wydajności, ale spodziewamy się, że użycie tego rodzaju funkcji będzie tak małe, że taka przewaga byłaby znikoma, a na pewno nie warta rozbudowy interfejsu API.

Holger wspomniał także w komentarzach o możliwości optymalizacji złożonych funkcji, takich jak Predicate.ori takie. Zostało to również wzięte pod uwagę ( JDK-8067971 ), ale zostało uznane za nieco delikatne i podatne na błędy oraz występowało na tyle rzadko, że nie było warte wysiłku, aby go wdrożyć.

Zobacz także ten wpis Lambda FAQ .

Stuart Marks
źródło
14
Dwie kwestie: pierwsza to zwięzłość. Jeśli (foo)->{return true;}to najlepsze, co mogę zrobić, chcę lepiej. Ale poruszyłeś x->true, co jest znacznie lepsze i łagodzi pierwszą kwestię. Druga kwestia to logika kontra deklaracja statyczna. Jeśli używam x->true, nadal jest zaangażowana logika, którą mógłbym niechcący zepsuć (np x->!true.). Ale w przypadku Predicate.alwaysTrue()nie ma miejsca na błędy logiczne, ponieważ istnieje tylko jedna lub dwie podobne metody. Dodatkowo otrzymuję bezpłatne uzupełnianie kodu IDE. x->truejest prawie w porządku, ale nadal napisałem Predicate.alwaysTrue()metodę z powyższych powodów.
Garret Wilson
10
@GarretWilson Ale z Predicate.alwaysTrue()tobą możesz też schrzanić, przypadkowo pisząc Predicate.alwaysFalse().
David Conrad,
5
@DavidConrad, oczywiście. Zawsze są sposoby na popełnienie błędów i tak naprawdę ciągle wymyślam nowe. ;) Nie chcę zaczynać tutaj sporu o coś trywialnego, ale powiem tylko, że chodzi mi o to, że przy statycznym odwołaniu do metody mam ograniczone słownictwo z tylko dwoma opcjami: alwaysTrue()i alwaysFalse(). Przy rzeczywistej lambdzie mam wiele odmian; Zasadniczo rekonstruuję formułę za każdym razem. W istocie alwaysTrue()jest semantyczną etykietą tego, co chcę zrobić; x->trueza każdym razem robi to od nowa. Niezbyt duże, ale warto się zastanowić.
Garret Wilson,
25
Jedna duża zaleta kanonicznych Predicate.alwaysTrue()iPredicate.alwaysFalse() wypadkach jest to, że mogą one być uznane przez łączenie metod jak Predicate.or, Predicate.andi Predicate.negate(). Pozwoliłoby to na wstępne zainicjowanie Predicatezmiennych z alwaysTrue()i dodanie predykatów poprzez połączenie przelotek andbez narzutu. Ponieważ wyrażenia lambda nie mają gwarancji tożsamości obiektu, może to się nie powieść w przypadku x->true. Nawiasem mówiąc, jeśli mam klasę Xz staticmetodą y(){return true;}, użycie X::yjest nawet krótsze niż, x->trueale niezbyt zalecane…
Holger
10
Idiom x -> truema tę wadę, że muszę używać zmiennej bez użycia. Stwarza to niepotrzebne obciążenie mózgu, a także ostrzeżenie w moim IDE. Próbowałem użyć _ -> true, ale jest to błąd składniowy. W Javie zdecydowanie brakuje słowa kluczowego (czytaj: literka klucza) dla „nieużywanego parametru”. Mam nadzieję, że coś takiego pojawi się w Javie 9 (lub przynajmniej: Java, cokolwiek zanim umrę ^^)
kap
4

Bez guawy

Boolean.TRUE::booleanValue
boriselec
źródło
3
To interesujące. Nie jestem pewien, czy całkowicie oddaje ducha prośby, ale dostaje punkty za kreatywność!
Garret Wilson
21
Ale to nie jest Predicate, ponieważ nie wymaga kłótni.
Florent Guillaume
1
To nie jest predykat, to odwołanie do metody, ale ma tę zaletę, że jest zwięzły i nie wymusza wspominania o nieużywanym parametrze. +1 Swoją drogą, ponieważ unika używania guawy, która ma poważny problem z modułowością, zasługuje na moje uznanie;)
gouessej
16
Odwołanie do metody można przypisać do dostawcy <Boolean>, ale nie do Predicate <T>
Daniel K.