Вбудований предикат Java 8, який завжди повертає істину?


Відповіді:


162

В Java 8. немає вбудованих завжди правдивих і завжди помилкових предикатів. Найбільш стислий спосіб їх написання - це

x -> true

і

x -> false

Порівняйте ці

Predicates.alwaysTrue() // Guava

і нарешті до анонімного внутрішнього класу:

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

Можливо, причиною того, що Guava має ці вбудовані предикати, є те, що існує величезна синтаксична перевага статичного виклику методу над анонімним внутрішнім класом. У Java 8 синтаксис лямбда настільки стислий, що є синтаксичний недолік у написанні виклику статичного методу.

Це просто синтаксичне порівняння. Мабуть, невелика перевага простору, якби існував єдиний глобальний завжди істинний предикат, порівняно з x -> trueподіями, рознесеними по декількох класах, кожен з яких створив би свій власний предикатний екземпляр. Це те, що вас хвилює? Заощадження не здалися переконливими, тому, ймовірно, вони не були додані в першу чергу. Але це може бути переглянути для майбутнього випуску.

ОНОВЛЕННЯ 2015-04-24

Ми розглянули додавання різноманітних статичних, іменованих функцій, таких як Predicate.alwaysTrue, Runnable.noopтощо, і вирішили більше не додавати в майбутні версії Java SE.

Звичайно, є щось значення у чомусь, що має ім’я порівняно з виписаною лямбда, але це значення досить мало. Ми очікуємо, що люди навчаться читати і писати, x -> trueа () -> { }їх використання стане ідіоматичним. Навіть значення Function.identity()над x -> xсумнівом.

Існує невелика перевага в продуктивності використання повторно використання існуючої функції замість того, щоб оцінювати виписану лямбда, але ми очікуємо, що використання таких функцій буде настільки малим, що така перевага була б незначною, звичайно не варто розробити API.

Голгер також згадував у коментарях можливість оптимізації складених функцій, таких як Predicate.orі такі. Це також вважалося ( JDK-8067971 ), але вважалося дещо крихким та схильним до помилок, і траплялося досить рідко, що не варто було докладати зусиль.

Дивіться також цей запис Ламбда-FAQ .


14
Дві проблеми: Перша - стислість. Якщо (foo)->{return true;}це найкраще, що я можу зробити, я хочу кращого. Але ви підняли x->true, що набагато краще і пом'якшує перше питання. Другий випуск - логіка проти статичного оголошення. Якщо я використовую x->true, все ще є логіка, яку я можу ненароком викрутити (наприклад x->!true). Але, маючи Predicate.alwaysTrue()місце, для логічної помилки немає місця, оскільки існує лише один або два подібних методу. Плюс я отримую код IDE безкоштовно. x->trueмайже добре, але я все-таки написав Predicate.alwaysTrue()метод з причин, зазначених вище.
Гаррет Вілсон

10
@GarretWilson Але з Predicate.alwaysTrue()тобою також можна було б заграти , випадково написавши Predicate.alwaysFalse().
Девід Конрад

5
@DavidConrad, звичайно. Завжди є способи помилитися, і насправді я постійно вигадую нові. ;) Я не хочу тут починати аргументи над чимось тривіальним, але я просто скажу, що моя думка полягає в тому, що зі статичним посиланням на метод я маю обмежений словниковий запас із лише двома варіантами: alwaysTrue()і alwaysFalse(). З реальною лямбдаю я маю багато варіацій; Я по суті реконструюю формулу кожен раз. По суті, alwaysTrue()це смислова мітка для того, що я хочу зробити; x->trueнасправді робить це знову і знову кожного разу. Не величезна, але врахування.
Гаррет Вілсон

25
Одна велика перевага канонічної Predicate.alwaysTrue()і Predicate.alwaysFalse()примірників в тому, що вони можуть бути визнані комбінуючи методи , як Predicate.or, Predicate.andі Predicate.negate(). Це дозволить попередньо ініціалізувати Predicateзмінні alwaysTrue()та додати предикати, комбінуючи через andбез накладних витрат. Оскільки лямбда-вирази не мають гарантії ідентичності об'єкта, це може не виконати x->true. До речі, якщо у мене є клас Xіз staticметодом y(){return true;}, використовувати X::yще коротше, x->trueале не дуже рекомендується…
Holger

10
x -> trueНедоліком ідіоми є те, що я повинен використовувати змінну без використання. Це створює непотрібне навантаження на мозок, а також попередження в моєму IDE. Я намагався використовувати _ -> true, але це синтаксична помилка. У Java напевно відсутнє ключове слово (читати: keyletter) для "невикористаного параметра". Сподіваюсь, що щось подібне з’явиться у Java 9 (або принаймні: Java, що завгодно до того, як я помру ^^)
кап

4

Без гуави

Boolean.TRUE::booleanValue

3
Це цікаво. Я не впевнений, чи повністю він захоплює дух прохання, але це отримує бали за творчість!
Гаррет Вілсон

21
Але це не так Predicate, як це не бере аргументу.
Флорент Гійом

1
Це не предикат, це посилання на метод, але він заслуговує на те, що він є стислим і не змушує згадувати невикористаний параметр. +1 До речі, оскільки уникнути використання Guava, яка має серйозну проблему модульності, вона заслуговує на мою нагоду;)
gouessej

16
Ваш посилання на метод призначається постачальнику <Boolean>, але не предикату <T>
Даніель К.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.