Экстернализация предиката в Java Lambda Stream Filter

У меня есть ArrayList модели данных, которая имеет 10 полей на основе пользовательского ввода, который мне нужен для динамического применения условия Predicate к выбранному пользователем полю для фильтра Stream.

Фрагмент ниже применяется с одним из полей itemDesc, но во время выполнения пользователь может выбрать любое поле.

Predicate<DataModel> contains = (n) -> n.getItemDesc().contains(query);        
List filtered = data.stream().filter(contains).collect(Collectors.toList());

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


person Balaji    schedule 06.05.2015    source источник


Ответы (1)


Это зависит от того, насколько динамичным должно быть решение. Для десяти свойств может быть приемлемым иметь явный список свойств во время компиляции, а не динамическое (рефлексивное) обнаружение.

Объявление доступных свойств может выглядеть так

enum DataModelProperty {
    ITEM_DESC(DataModel::getItemDesc),
    FOO(DataModel::getFoo),
    BAR(DataModel::getBar)
    // the other seven properties…
    ;
    final Function<DataModel,String> getter;

    private DataModelProperty(Function<DataModel, String> f) {
        getter = f;
    }
    public Function<DataModel, String> getPropertyGetter() {
        return getter;
    }
    public Predicate<DataModel> asPredicate(String query) {
        return n -> getter.apply(n).contains(query);
    }
}

Затем вы можете использовать DataModelProperty.values(), чтобы представить пользователю список вариантов, но также возможно преобразование в постоянное представление String через Enum.name() и воссоздание объекта среды выполнения через DataModelProperty.valueOf(String).

Если у вас есть выбранное свойство, использовать его для фильтрации легко.

DataModelProperty p=DataModelProperty.valueOf("ITEM_DESC");// just as example

List<DataModel> filtered = data.stream()
                               .filter(p.asPredicate(query))
                               .collect(Collectors.toList());
person Holger    schedule 06.05.2015
comment
Спасибо, попробовал ваш подход, очень помогло. Может динамически создавать предикат с различными свойствами и условиями. Ваше здоровье. - person Balaji; 07.05.2015