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


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 .


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

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.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.