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

时间:2019-01-27 20:33:28

标签: java list predicate steam

我需要您的帮助以找出什么是在Java 8中解决此问题的最佳方法

我有一个必须分类的对象X的列表。

这是我的规则集:

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

情况1:我有一个对象X,其中包含(值1 = abc,值2 = def,   value3 = ghi),因此代码应返回包含规则1、2、3的列表

     

案例2:我有一个对象X,其中包含(值1 = abc,值2 = def,   value3 = hij),因此代码应返回包含规则1、2的列表

谢谢

1 个答案:

答案 0 :(得分:0)

虽然“最佳方法”非常模糊。这是一种解释,至少是结合用于过滤对象中可扩展字段的规则列表的良好起点,而不限于字段或对象的数量,易于互换的类型等。

首先让我们定义一些数据对象以捕获数据模型:

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;
    }
}

然后是将它们与数据提示一起使用的主要方法:

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);
}

预期结果:

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}]

和分类方法的“魔术”。

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;
}

没什么大不了的。 rule.valueFilters.length > i在那里,因此您不必在全部返回true的规则中指定尾随过滤器。

我确定可以使用流,但是可读性会受到质疑,并且对于像这样的批处理作业,如果没有提前终止/惰性评估的好处,很可能效率不高。

环回X类对象。