4

我正在寻找一种简单的方法来对 Java 集合执行聚合函数以确定例如产品集合的最低价格。但我不想用纯 java 来做,而是某种可以由用户输入的 DSL / 脚本 / 表达式语言,因此需要尽可能简单。

假设我有以下对象结构:

Product:
id: product1
offers: [offer1, offer2]


Offer1:
id: offer1
data:
  price: 10.99
  shipCost: 3.99

Offer2:
id: offer2
data:
  price: 5.99
  shipCost: 3.99

在上面的示例中,最终结果将是这样的:

minPriceOfProduct1 = 5.99

现在我的应用程序的用户可以显示产品列表。对于每种产品,他希望获得最低价格,这是所有报价中的最低值。用户无权访问底层数据存储,因此不能选择 SQL。我们唯一拥有的是 java 对象。我希望用户使用某种表达语言来表达这一点。

目前,我能够将 Freemarker 代码片段应用于每个产品以获取数据或根据以下属性进行更多操作以计算新值:

<#if (item.isProduct() && item.offers??) >
   <#assign offerMinPrice = -1>
   <#list item.offers as o>
     <#if (offerMinPrice == -1 || ( o.data.priceCents?? && o.data.priceCents < offerMinPrice ) )>
       <#assign offerMinPrice=o.data.priceCents! >
     </#if> 
   </#list> 

   <#if offerMinPrice != -1>
       ${offerMinPrice}
   <#else>
       ${priceCents}
   </#if> 
<#else>
   ${priceCents!}
</#if>

这行得通,但它是丑陋的代码,不仅让我的大脑流血。我宁愿有一些更简单的表达语言方法,看起来像这样:

minOffersPrice = min(product.offers.data.price)

这对用户来说看起来要简单得多,并且应该在引擎盖下进行相同的聚合。

你想到了什么方法?通过网络搜索,我想到了以下几点:

谢谢克里斯托夫

4

2 回答 2

3

LambdaJ 是一个使用纯 Java api 解决此问题的库:https ://code.google.com/p/lambdaj/wiki/LambdajFeatures

Person maxAgePerson = selectMax(personsList, on(Person.class).getAge() );

whereselectMax和是来自Lambdaon的静态导入。

于 2013-04-21T12:15:57.363 回答
1

Java 8 流以相当流畅的语法提供了其中的一些功能:

import static java.util.Comparator.comparingBy;
/* ... */
BigDecimal minPrice = product1.offers.stream()
    .min(comparingBy(o -> o.data.price));
于 2014-10-11T14:48:45.867 回答