OptaPlanner执行groupBy操作时出现ClassCastException异常求助
问题1解答
这个异常是OptaPlanner 8.12.0.Final版本内置的Drools约束流实现的已知缺陷,不是你的业务代码错误导致的。
该版本对BiStream调用带收集器的双参数groupBy()方法时,存在类型推导bug:底层Drools生成规则字节码时,会错误将单值的分组键识别为Object数组类型,执行时就会抛出ImmutableStudent cannot be cast to class [Ljava.lang.Object的类型转换异常,这和你用toMap还是toSet收集器没有关系。
问题2解答
直接规避问题的方案
- 更换约束流实现为Bavet,不需要编译为Drools规则,报错可直接定位到用户代码。
在solver配置文件的scoreDirectorFactory节点下添加配置即可开启:
8.12.0.Final版本已经完整支持Bavet实现,替换后要么约束直接正常运行,要么异常栈会直接指向你编写的lambda代码行,不会出现只有底层Drools栈的问题。<constraintStreamImplType>BAVET</constraintStreamImplType> - 升级OptaPlanner版本到8.19.0.Final及以上的稳定8.x版本,该
groupBy类型推导bug已经在后续版本修复,不需要修改你的约束代码即可正常运行。
临时调试技巧
如果要保留当前版本和Drools约束流实现,可通过以下方式尝试绕开bug:
- 给
groupBy的lambda参数添加明确的类型声明,不要依赖编译器自动推导,例如将(l, s) -> ImmutableStudentAndDay.of(s, l.getStartTimeslot().getDay())修改为(RecurringLecture l, ImmutableStudent s) -> ImmutableStudentAndDay.of(s, l.getStartTimeslot().getDay()),强制指定参数类型可以帮助Drools的类型推导器正确识别类型,避免生成错误的类型转换逻辑。 - 拆分
groupBy逻辑,去掉内置收集器,先拿到分组后的元组再手动处理集合收集,也能绕开收集器相关的类型bug。
内容的提问来源于stack exchange,提问作者aioobe
相关产品推荐
相关产品推荐

