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

如何在TimeFold约束流中遍历数组并计算分数?

问题:在OptaPlanner约束中遍历StandardWorkAmounts计算分数

定义的Java类

DaySetting类

public class DaySetting {
    String businessDate;
    Integer weekNo;
    Integer monthNo;
    ArrayList<StandardWorkAmount> standardWorkAmounts;
}

StandardWorkAmount类

public class StandardWorkAmount {
    String jobType;
    Integer workMinutes;
    
    public String getJobType() {
        return jobType;
    }
    public void setJobType(String jobType) {
        this.jobType = jobType;
    }
    public Integer getWorkMinutes() {
        return this.workMinutes;
    }
    public void setWorkMinutes(Integer workMinutes) {
        this.workMinutes = workMinutes;
    }
}

待完善的Constraint代码

用户已编写的部分代码如下:

Constraint daySettingStandardNumberOfHours(ConstraintFactory constraintFactory) {
        return constraintFactory.forEach(DaySetting.class)
               .filter((daySetting)->daySetting.getStandardWorkAmounts()!= null)
               // Iterate through daySetting.getStandardWorkAmounts and find the optimal choice.
               .penalize(HardMediumSoftScore.ONE_SOFT,

               .asConstraint("Day Settings Standard Number Hours");
    }

实现方案

根据需求,分两种常见场景给出实现:

场景1:针对单个StandardWorkAmount元素计算分数

如果需要对每个StandardWorkAmount单独校验(比如特定工种的工作时长不符合要求就扣分),可以用flatMap展开集合,再进行过滤和扣分:

Constraint daySettingStandardNumberOfHours(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(DaySetting.class)
           // 过滤掉standardWorkAmounts为空的情况,避免空指针
           .filter(daySetting -> daySetting.getStandardWorkAmounts() != null && !daySetting.getStandardWorkAmounts().isEmpty())
           // 将每个DaySetting展开为其包含的StandardWorkAmount元素
           .flatMap(daySetting -> daySetting.getStandardWorkAmounts().stream())
           // 示例:筛选出工作时长小于120分钟的记录(可根据实际需求调整条件)
           .filter(workAmount -> workAmount.getWorkMinutes() < 120)
           // 每条不符合条件的记录扣1个软分数
           .penalize(HardMediumSoftScore.ONE_SOFT)
           .asConstraint("Day Settings Standard Number Hours");
}

场景2:针对DaySetting的总工作时长计算分数

如果需要基于DaySetting下所有StandardWorkAmount的总时长与标准值对比扣分,直接在penalize的分数计算逻辑中处理:

Constraint daySettingStandardNumberOfHours(ConstraintFactory constraintFactory) {
    // 定义标准日工作时长(示例为8小时=480分钟)
    final int STANDARD_DAILY_MINUTES = 480;
    return constraintFactory.forEach(DaySetting.class)
           .filter(daySetting -> daySetting.getStandardWorkAmounts() != null && !daySetting.getStandardWorkAmounts().isEmpty())
           .penalize(HardMediumSoftScore.ONE_SOFT,
               // 计算总时长与标准值的差值绝对值,以此作为扣分数量
               daySetting -> {
                   int totalWorkMinutes = daySetting.getStandardWorkAmounts().stream()
                       .mapToInt(StandardWorkAmount::getWorkMinutes)
                       .sum();
                   return Math.abs(totalWorkMinutes - STANDARD_DAILY_MINUTES);
               })
           .asConstraint("Day Settings Standard Number Hours");
}

关键说明

  • 必须在filter中增加!daySetting.getStandardWorkAmounts().isEmpty()判断,避免空集合导致的计算异常
  • flatMap用于将集合元素展开,适合处理单个元素的校验逻辑
  • penalize的第二个参数是分数计算函数,可根据实际业务需求调整(比如固定扣分、按差值比例扣分等)

内容的提问来源于stack exchange,提问作者I. Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:56:16