Когда реализовать предикат вместо логического - PullRequest
0 голосов
/ 22 октября 2018

Я читал не связанный поток , когда я читал комментарий: Каждый раз, когда мне нужно многострочное лямбда, я перемещаю строки в закрытый метод и передаю методссылка вместо лямбды.

Я спрашивал: как правильно реализовать это поведение?С булевым методом, как указано в комментарии, или с предикатом?


Пример: скажем, я хочу проверить, можно ли использовать Table, где использование означает isClean, isEmpty, hasChair.

class Table{
    public boolean hasChair(){...}
    public boolean isClean(){...}
    public boolean isEmpty(){...}
}

Я могу реализовать свой тест фильтрации для своего списка List<Table> tablesList = Arrays.asList(table1,table2,table3,table4); двумя способами: первый с логическим значением:

public boolean isUsable(){
    return hasChair() && isClean() && isEmpty();
}

И использовать его с tablesList.stream().filter(Table::isUsable)

Второй способ - с предикатом:

public Predicate<Table> isUsable(){
    return table -> table.isEmpty() && table.isClean() && table.hasChair();
}

Используется с tablesList.stream().filter(isUsable())


Какая правильная реализация?Почему выбирают одно вместо другого?Есть ли большая разница?

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

Наличие Predicate<Table> isUsable() предполагает, что вы всегда будете требовать, чтобы эта логика использовалась в местах, где требуется экземпляр Predicate<Table>, что является ограничением.

С другой стороны, наличие boolean isUsable() дает вамгибкость использования Table::isUsable там, где требуется Predicate<Table>, или использования Table::isUsable в качестве реализации некоторых других функциональных интерфейсов (что соответствует сигнатуре этого метода) или прямого вызова t.isUsable() для определенного экземпляра Table.Поэтому я считаю эту альтернативу более полезной.

0 голосов
/ 22 октября 2018
static List<Predicate<Table>> predicateList = Arrays.asList(Table::hasChair, Table::isClean);

static boolean isUsable(Table table) {
    return predicateList.stream().allMatch(p -> p.test(table));
}

использовать можно:

List<Table> tablesList = ...
Stream<Table> usableTables = tablesList.stream().filter(Table::isUsable);
0 голосов
/ 22 октября 2018

Я думаю, вы имели в виду второй пример

public static Predicate<Table> isUsable(){
    return table -> table.isEmpty() && table.isClean() && table.hasChair();
}

, который может уже предполагать, что эта форма может запутать читателя.Без static вы могли бы написать table.isUsable() или Table::isUsable, но это не сработало бы так, как вы думаете.

Какая правильная реализация?

Я быпредпочитайте Table::isUsable, так как он может также использоваться как table.isUsable для экземпляра.

Почему выбирают одно вместо другого?

Мне кажется, что первый пример более естественный и менее запутанный.

Вторая форма более полезна для манипулирования предикатами, например, Predicate.or (Predicate)

Есть ли большая разница?

В этом случае использование потока, вероятно, будет медленнее, но, что более важно, более вероятным, чтобы сбить с толку.

Одно преимущество методавозвращает предикат, если он может быть добавлен в любой класс, например, по какой-то причине вы не можете изменить таблицу.

...