You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Drools遍历List集合并依据业务规则筛选最优对象

实现方案

Drools 完全支持多实例集合的筛选、比对、最优值评选能力,完全匹配你剥离业务硬编码、支持业务人员自主维护规则的需求,不需要回退到手写Stream过滤的实现方式。

前置准备:补全可正常使用的Java模型

你贴的类定义缺字段名和泛型声明,补全后遵循JavaBean规范补全构造方法、getter/setter即可直接使用:

public class BesPeople {
    private List<Person> personList;
    // 无参构造、全参构造、getter、setter省略
}

// 类名建议遵循大驼峰规范,首字母大写
public class Person {
    private int height;
    private int weight;
    private int shoesize;
    private String votingRecord;
    // 可选:规则计算临时用的分数字段,标记为瞬时字段不影响业务存储
    private transient int score;
    // 无参构造、全参构造、getter、setter省略
}

传参时两种方式都支持:既可以把包装了人员列表的BesPeople实例插入规则会话,也可以把5个Person实例逐个insert到会话中。

核心实现逻辑

你之前查到的单对象规则示例只是Drools最基础的用法,针对多实例选优的场景,Drools原生支持三类成熟写法,不需要额外开发复杂插件:

  • 用from关键字直接遍历集合,配合not条件做极值匹配,零侵入原有业务模型
  • 先按业务规则给每个实例计算综合得分,再匹配得分最高的实例,逻辑清晰最适合业务人员维护
  • 用accumulate聚合函数直接计算全局阈值,再匹配符合阈值的目标实例,适合大数据量的高性能场景

可直接运行的规则示例

最推荐用评分法实现,规则可读性最高,业务人员调整权重、加减规则项的学习成本最低。比如业务规则为「身高每高1cm加1分、体重在60-70kg区间加20分、投票记录无异常加30分、鞋码在40-42区间加10分,选总分最高的为最优人员」,对应的drl规则文件内容如下:

package com.business.rules
import com.yourpackage.Person;
import com.yourpackage.BesPeople;

// 定义全局变量,用来向Java侧返回最终选出的最优人员
global Person bestPerson;

// 规则1:计算所有人员的综合评分,优先级最高先执行
rule "calc_every_person_score"
    salience 100
    when
        $person : Person()
    then
        int score = 0;
        // 以下所有评分规则都可由业务人员自主调整,不需要修改Java源码、不需要重新打包业务服务
        score += $person.getHeight();
        if ($person.getWeight() >= 60 && $person.getWeight() <=70) score += 20;
        if ("NORMAL".equals($person.getVotingRecord())) score +=30;
        if ($person.getShoesize() >=40 && $person.getShoesize() <=42) score +=10;
        $person.setScore(score);
        update($person);
end

// 规则2:选出评分最高的人员,评分计算完成后再执行
rule "pick_up_best_person"
    salience 10
    when
        $candidate : Person( $candidateScore : score )
        // 不存在比当前候选人分数更高的人员
        not Person( score > $candidateScore )
    then
        bestPerson = $candidate;
end

如果你不想给Person类加临时的score字段,也可以用零侵入的集合遍历写法,比如直接选身高最高的人员:

rule "pick_up_tallest_person"
    when
        $group : BesPeople( $personList : personList )
        $tallest : Person() from $personList
        not Person( height > $tallest.height ) from $personList
    then
        bestPerson = $tallest;
end

Java侧调用示例

// 初始化Drools运行环境
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession session = kieContainer.newKieSession("business-rules-session");

// 传入待处理的数据
BesPeople data = new BesPeople();
// 给data设置包含5个Person实例的列表
session.insert(data);
// 如果选择逐个传入Person实例,循环insert即可
// for (Person p : personList) session.insert(p);

// 绑定全局变量接收结果
Person finalBestPerson = null;
session.setGlobal("bestPerson", finalBestPerson);

// 执行全部规则
session.fireAllRules();
session.dispose();

// 此处finalBestPerson就是规则筛选出的最优人员,可直接用于后续业务逻辑

补充说明

  • 所有业务判断、筛选、排序逻辑全部存放在drl规则文件中,Java侧代码只负责传参、接结果,后续规则调整可以完全不碰业务源码,甚至可以对接可视化规则配置平台让业务人员自行修改发布规则
  • 支持任意复杂度的规则逻辑:一票否决项、多维度权重计算、同分时次级规则排序、多人同时入选等需求都可以直接在规则中实现
  • 性能有充足保障:即使待筛选的人员规模达到万级,Drools的Rete匹配算法的性能也远高于手写硬编码循环的实现

内容的提问来源于stack exchange,提问作者SoftwareSavant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:15:36