在Drools的内部集合上累积

在Drools的内部集合上累积,drools,drools-planner,Drools,Drools Planner,假设我有红色和绿色的篮子,里面装着一盒盒草莓和葡萄: public class Basket { public enum Color { RED, GREEN }; private Color color; private List<FruitBox> fruitBoxes; //Assume appropriate constructors, getters exist } public class FruitBox { public

假设我有红色和绿色的篮子,里面装着一盒盒草莓和葡萄:

public class Basket {
    public enum Color { RED, GREEN };

    private Color color;
    private List<FruitBox> fruitBoxes;

    //Assume appropriate constructors, getters exist
}

public class FruitBox {
    public enum Fruit { STRAWBERRY, GRAPE };

    private Fruit fruit;

    //Assume appropriate constructors, getters exist
}
成功打印一个测试数据集的输出,如:

com.sample.DroolsTest$Basket@10cd6753 has 4 of the fruit STRAWBERRY
com.sample.DroolsTest$Basket@10cd6753 has 3 of the fruit GRAPE
com.sample.DroolsTest$Basket@2e060819 has 2 of the fruit GRAPE
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
我担心的是,我的规则既长又复杂,似乎要对每个篮子重复几次(一次是为了找到其中唯一的水果,然后再次对每个水果进行计数)。我怀疑这是我缺乏口水知识的结果,还有更好的解决办法。在普通Java中,我将使用HashMap在一次传递中存储每个水果及其计数,这将是简单而快速的。有没有办法重写Drools代码以提高性能和可读性?同样的问题也适用于我的第二条规则:

rule "Totals by fruit and by basket color"
    when
        //Calculate the cross product of all fruits and colors
        $fruit : FruitBox.Fruit()
        $color : Basket.Color()

        //Count the number of FruitBoxes of the chosen fruit in Baskets of the chosen color
        $count : Number() from accumulate(
            $fb : FruitBox(fruit == $fruit) 
            and exists Basket(color == $color, fruitBoxes contains $fb),
            count($fb) )
    then
        System.out.println($count + " " + $fruit + " in " + $color + " baskets");
end
产生如下输出:

com.sample.DroolsTest$Basket@10cd6753 has 4 of the fruit STRAWBERRY
com.sample.DroolsTest$Basket@10cd6753 has 3 of the fruit GRAPE
com.sample.DroolsTest$Basket@2e060819 has 2 of the fruit GRAPE
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
但是,不幸的是,它看起来像是在所有篮子中搜索每个水果盒,而在篮子上迭代一次,将一种(或全部)水果盒汇总起来则更有意义。就性能而言,该规则是否有更好的语法


谢谢你的帮助

您好,对于第一个问题,我将使用两个单独的规则:

rule "strawberriesInBasket"
dialect "mvel"
when
    $basket : Basket($fruitBoxes : fruitBoxes)
    Number($count : intValue() > 2) from accumulate ($fruitBox : FruitBox(fruit.name == "strawberry") from $fruitBoxes, count($fruitBox)) 
then
    System.out.println("Count of strawberry boxes in basket is: " + $count )
end


请注意,我将enum水果更改为字段名为的数据对象

谢谢,Jomarko!我积累这些结果的原因是上面的代码是一个更大问题的小例子,其中'fruit.name'的值是动态确定的(可能有几百个值)。如果'fruit.name'只有两个值是可能的,那么我同意这将是一个更好的解决方案。好的,我现在更好地理解了。几百个值真是太多了。但是,如果值的域是有限的,我建议您在kie workbench中查看xls决策表或引导决策表。在这两种情况下,您只需编写一次规则(规则的模板),然后将特定规则中不同的值填充到简单表中。