如何解决如何使用流口水将列表中的元素分组
我是Drools的新手,我正在努力寻找以下问题的解决方案:
class Account {
private String name;
private float amount;
}
我想使用流口水中的名称对“帐户”列表进行分组。 例如:
Account a = new Account("Science",100);
Account b = new Account("Science",200);
List<Account> list = new ArrayList<String>();
list.add(a);
list.add(b);
现在我需要一个流口水的规则,该规则应该使用名称将列表中的元素分组并提供具有“ Science,300”的列表。
请提出建议。
解决方法
正如Ironluca在评论中指出的那样,您正在使用错误的工具来完成工作。正确的解决方案是使用Java流。即使是简单的for循环也可以解决您的问题。
当然,由于您可以在锤子上使用锤子,因此可以使用Drools来完成。我将提供一个示例规则和解释,尽管它比基于流的解决方案(甚至是for循环)效率要低得多。
我将假设此模型具有适当的getter,setter和all-args构造函数:
class Account {
String name;
int quantity;
}
然后,此规则将使用“分组”帐户填充“输出”列表。我已经将此“输出”列表声明为全局列表,这并不是最佳做法,但是无论如何都建议不要这样做,因为它不是该工作的合适工具。
global List $output;
rule "Consolidate duplicates"
when
$inputs: List()
Account( $name: name ) from $inputs
$duplicates: List()
from collect( Account( name == $name ) from $inputs )
$total: Number()
from accumulate( Account( $value: quantity ) from $duplicates,sum( $value ) )
then
$output.add(new Account($name,$total));
end
规则的第一部分标识输入列表中共享相同名称的Account实例的子集。我使用collect
是因为这是原始输入的简单子集。下一步是使用accumulate
汇总这些重复项中的数量。然后,我们将新实例与合并数量和共享名一起添加到规则RHS的输出列表中。请注意,该规则适用于具有唯一名称的帐户; $duplicates
的长度没有限制,累积量只是一个确定的数量。
就地修改$inputs
也是可行的,但是很棘手,因为您必须担心并发修改异常。更清洁的实现是使用
当然,这比必须的复杂得多。 Java 8流提供了一个groupingBy
收集器,该收集器允许您通过对象内的属性来轻松创建地图:
Map<String,List<Account>> accountsByName = accounts.stream()
.collect(groupingBy(Account::getName));
然后可以通过遍历值集轻松地对其进行转换。
对于其他“流中重复项的总和”方案,此问题也有详细说明:Java 8 stream sum entries for duplicate keys
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。