简体   繁体   English

如何通过 Java 8 中过滤器/谓词的多个组合来检索列表对象?

[英]How to retrieve a list objects by multiple combination of filters/predicates in Java 8?

I need your help to find out what would be the best way to solve this in java 8我需要你的帮助来找出在 java 8 中解决这个问题的最佳方法

I have a list of objects X that must be classified.我有一个必须分类的对象 X 列表。

This is my ruleset:这是我的规则集:

ID  | Filtre1 | Filtre2 | Filtre3 | ValueToApply
1   |  'abc'  |  null   |  null   |  10
2   |  'abc'  |  'def'  |  null   |  25 
3   |  'abc'  |  null   |  'ghi'  |  20

Case 1: I have one object X that contain (value1=abc, value2=def, value3=ghi) so the code should return the list with the rules 1, 2, 3案例 1:我有一个包含 (value1=abc, value2=def, value3=ghi) 的对象 X,因此代码应该返回具有规则 1、2、3 的列表

Case 2: I have one object X that contain (value1=abc, value2=def, value3=hij) so the code should return the list with the rules 1, 2案例 2:我有一个包含 (value1=abc, value2=def, value3=hij) 的对象 X,因此代码应该返回具有规则 1、2 的列表

Thanks谢谢

While "best way" is very vague.而“最佳方式”是非常模糊的。 Here is one interpretation that at least is a good starting point combining a list of rules for filtering fields in objects that's extendable, not limited to the number of fields or objects, easily interchangeable types etc.这是一种解释,它至少是一个很好的起点,结合了用于过滤可扩展对象中的字段的规则列表,不限于字段或对象的数量、易于互换的类型等。

First let us define some data objects to capture the data model:首先让我们定义一些数据对象来捕获数据模型:

static class Rule {
    final int id;
    final int valueToApply;
    final Predicate<String>[] valueFilters;

    public Rule(int id, int valueToApply, Predicate<String>... valueFilters) {
        this.id = id;
        this.valueToApply = valueToApply;
        this.valueFilters = valueFilters;
    }

    @Override
    public String toString() {
        return "Rule{id="+id+", valueToApply="+valueToApply+"}";
    }
}

static class X {
    final String[] values;

    X(String... values) {
        this.values = values;
    }
}

Then a main method using them with the suggested in data:然后使用它们与数据中建议的主要方法:

public static void main(String[] args) {
    X x1 = new X("abc", "def", "ghi");
    X x2 = new X("abc", "def", "hij");

    List<Rule> rules = new ArrayList<>(Arrays.asList(
            new Rule(1, 10, v->"abc".equals(v)),
            new Rule(2, 25, v->"abc".equals(v), v->"def".equals(v)),
            new Rule(3, 20, v->"abc".equals(v), v->true, v->"ghi".equals(v))
    ));

    Collection<Rule> rulesResult = classify(x1, rules);
    System.out.println("Case 1:"+rulesResult);
    rulesResult = classify(x2, rules);
    System.out.println("Case 2:"+rulesResult);
}

Expected result:预期结果:

Case 1:[Rule{id=1, valueToApply=10}, Rule{id=2, valueToApply=25}, Rule{id=3, valueToApply=20}]
Case 2:[Rule{id=1, valueToApply=10}, Rule{id=2, valueToApply=25}]

And the "magic" of the classify method.以及分类方法的“魔力”。

static Collection<Rule> classify(X x, Collection<Rule> rules) {
    List<Rule> result = new ArrayList<>();

    for (Rule rule : rules) {
        for (int i = 0; i < x.values.length; i++) {
            if (rule.valueFilters.length > i && !rule.valueFilters[i].test(x.values[i]))
                continue;
            if (i == x.values.length-1)
                result.add(rule);
        }
    }

    return result;
}

Nothing major to remark on.没什么大不了的。 The rule.valueFilters.length > i is there so you don't have to specify trailing filters in the rules that all return true. rule.valueFilters.length > i就在那里,因此您不必在所有返回 true 的规则中指定尾随过滤器。

I'm sure streams could be used but the readability would be questionable and most likely not efficient for a batch job like this were there is no early termination/lazy eval benefits.我确信可以使用流,但可读性是有问题的,而且很可能对于像这样的批处理作业效率不高,因为没有提前终止/延迟评估的好处。

Loop over objects of class X.循环 X 类的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM