Як перевірити, чи існує елемент, використовуючи лямбда-вираз?


118

Зокрема, у мене є TabPane, і я хотів би знати, чи є в ньому елемент із конкретним ідентифікатором.

Отже, я хотів би зробити це з виразом лямбда на Java:

boolean idExists = false;
String idToCheck = "someId";

for (Tab t : tabPane.getTabs()){
    if(t.getId().equals(idToCheck)) {
        idExists = true;
    }
}

Відповіді:


273

Спробуйте використовувати anyMatchLambda Expression. Це набагато кращий підхід.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));

11
Також варто зазначити: якщо ви хочете відмовитись від використання чека, noneMatchа не anyMatch.
Blacklight

Для дзвінка потрібен API рівня 24
FabioLux

50

Хоча прийнята відповідь правильна, я додам більш елегантну версію (на мою думку):

boolean idExists = tabPane.getTabs().stream()
    .map(Tab::getId)
    .anyMatch(idToCheck::equals);

Не нехтуйте використанням Stream # map (), що дозволяє вирівняти структуру даних перед застосуванням Predicate.


3
що тут краще? Я бачу лише ще одну операцію. Вибачте, що я новачок у цій справі з ламбою.
TecHunter

2
@TecHunter це більш явно. Уявіть, що ви читали цей код вперше чи знову через деякий час. Є кілька переваг: По-перше, ми відразу показуємо, що нас насправді не цікавить вкладка, а деяке відображення її. По-друге, використовуючи посилання на метод (який можливий лише тому, що ми розбиваємо початкову лямбда на два етапи), ми показуємо, що в коді немає жодних сюрпризів. По-третє, використовуючи посилання на методи, ми не створюємо новий предикат, а насправді просто повторно використовуємо equals. Хоча, безумовно, приклад тут дуже простий, але я сподіваюся, що ви отримаєте те, що я маю на увазі.
Malte Hartwig

@MalteHartwig дякую! так, я отримую ваші 3 бали, але я питав про вирівнювання map, чи це ще один крок обробки ні? Спробую порівняти 2 методи :)
TecHunter

1
@MalteHartwig перевіряється в 10kk ArrayList простим об'єктом, який намагається знайти останній елемент. дає 2ms різницю 131ms проти 133ms для вашого. у списку масивів 1kk ваш, якщо швидше на 2ms (55ms до 53ms). Тож можна сказати, що ваше краще :)
TecHunter

2
@TecHunter геттери дуже дешеві. Завжди віддайте перевагу ясності коду над економією додаткових 2 мілісекунд (хоча, я сумніваюся, результати є точними, вони можуть коливатися на кожному пробігу). Крім того, пам’ятайте, що проміжні операції на потоках (таких як map) ледачі від природи. Це означає, що getIdметод не застосовується до кожного елемента колекції. Це ліниво оцінюється, поки не anyMatchповернеться істиною .
jFrenetic

3

Наведені вище відповіді вимагають від вас виділити новий об'єкт потоку.

public <T>
boolean containsByLambda(Collection<? extends T> c, Predicate<? super T> p) {

    for (final T z : c) {
        if (p.test(z)) {
            return true;
        }
    }
    return false;
}

public boolean containsTabById(TabPane tabPane, String id) {
    return containsByLambda(tabPane.getTabs(), z -> z.getId().equals(id));
}
...
if (containsTabById(tabPane, idToCheck))) {
   ...
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.