本文将介绍一下Drools7中accumulate的用法及其在遍历List时的一些问题,同时也会分享几个使用场景。
虽然 accumulate 虽然只是Drools中的一个关键字,但是它的功能很强大,在实际开发中我用于统计、多个List集合交叉校验、数据预处理、甚至是运行调试。但是个人感觉有些细节很难把握到,例如:循环;所以这篇文章写得比较啰嗦,既然要搞清楚它,那就请按捺住浮躁的情绪。
一、语法
语法结构:
accumulate( <source pattern>; <functions> [;<constraints>] )
accumulate 可以使用内置函数,也可以用自定义函数。
1.内置函数的使用,求和函数sum的使用例子如下:
entity
public class Order {
private Integer id;
private Integer customerId;
private Double total;
private Double discount;
private Double pay;
private Date createDate;
private List<Item> items;
}
rule
//所有订单的金额低于800时,触发规则
rule "order_0"
when
accumulate(
Order(total>0.00, $total:total);
$sum:sum($total);
$sum <800.00
)
then
System.out.println("销售业绩太差了");
end
//所有订单的金额低于800时,触发规则,并返回合计金额
rule "order_0"
enabled false//rule可触发状态,false为不可触发但是会匹配,true为可触发,默认为true,
when
//doubleValue > 0.00 表示返回值要大于0.00
$n:Number(doubleValue > 0.00) from accumulate(
Order(total>0.00, $total:total),//注意这里是逗号,不是分号
sum($total)//当作为返回值时,不能对函数绑定引用;
)
then
System.out.println($n);
end
内置函数还有以下几个,就不一一举例了:
average 求平均数
min 最小值
max 最大值
count 计数器
variance 方差,这里用的是增量方差算法
standardDeviation 标准差,继承了variance函数方法 ,直接对variance函数 结果开平方
collectList 数据列表收集,这个翻译有点晦涩,其实就是把符合条件的source归集起来,可接受重复数据
collectSet 数据列表收集。
2.自定义accumulate函数
有两种自定义accumulate函数的方法。
第一种:只需要创建一个java类并实现org.kie.api.runtime.rule.AccumulateFunction接口,然后在.drl文件中impor就可以了。
对import的语法结构做一下简要说明 import accumulate <class_name> <function_name> ,<class_name>必须是自定义函数类的完整包名+类名,<function_name>是给自定的函数设置个名字,然后函数就用这个<function_name>调用自定义函数,语法与调用内置函数一样。
这里由于篇幅和主题问题就不再细说了,这种方式的优点是代码可以重复利用,便于维护使用该函数的规则,但是我个人在实际开发当中业务逻辑不尽相同,很难做到重复利用,硬套这种方式不是不可以,但是工作量还是挺大的,自定义实现AccumulateFunction接口的细节可以点击这里查看,因为篇幅原因这里就不再写了,后便将会再介绍另一种语法结构,它会更适合我的实际开发的情况。
第二种:这里其实不是自定义accumulate函数了,而是另一种语法结构,之所以放在这里是为了让知识点更紧凑。
语法结构如下:
<result pattern> from accumulate( <source pattern>,
init( <init code> ),
action( <action code> ),