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

Имам ArrayList от модел на данни, който има 10 полета въз основа на въведеното от потребителя, което ми трябва, за да приложа динамично предикатното условие върху избраното от потребителя поле към филтъра на потока.

Фрагментът по-долу се прилага с едно от полето 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