我当前使用Streams API和forEach循环的方法:
public Map<String, Client> clientsWithMostPurchasesInEachCategory(Map<Client, Map<Product,Integer>> shopping) {
Map<String, Client> result = new HashMap<>();
Map<Client, Map<String, BigDecimal>> temp =
shopping.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.flatMapping(e -> e.getValue().entrySet().stream(),
Collectors.groupingBy(e -> e.getKey().getCategory(),
Collectors.mapping(ee -> ee.getKey().getPrice().multiply(BigDecimal.valueOf(ee.getValue())),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))))));
/*curious, how could I refactor that piece of code, so the method uses only one stream chain? */
temp.forEach((client, value)
-> value.forEach((category, value1)
-> {
if (!result.containsKey(category) ||
temp.get(result.get(category)).get(category).compareTo(value1) < 0)
result.put(category, client);
}));
return result;
}
正如该方法的名称所暗示的,我希望找到一个mapmap
,其中包含每个产品类别中指定类别(作为键)中最多购买(作为值)的客户机
购物基本上是一个地图:map
,
你被客户分组的那一刻就注定了你的命运。顶级集合器.groupingby
必须使用类别作为分组依据键。
为此,您需要在收集之前flatmap
,这样您就得到了一个由client+category+spend元素组成的平面流。
这里有一个方法。我将首先为扁平流的元素定义一个POJO:
static class ClientCategorySpend
{
private final Client client;
private final String category;
private final BigDecimal spend;
public ClientCategorySpend(Client client, String category, BigDecimal spend)
{
this.client = client;
this.category = category;
this.spend = spend;
}
public String getCategory()
{
return category;
}
public Client getClient()
{
return client;
}
public BigDecimal getSpend()
{
return spend;
}
}
现在的函数是:
public static Map<String, Client> clientsWithMostPurchasesInEachCategory(Map<Client, Map<Product, Integer>> shopping)
{
// <1>
Collector<? super ClientCategorySpend, ?, BigDecimal> sumOfSpendByClient = Collectors.mapping(ClientCategorySpend::getSpend,
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add));
// <2>
Collector<? super ClientCategorySpend, ?, Map<Client, BigDecimal>> clientSpendByCategory = Collectors.groupingBy(
ClientCategorySpend::getClient,
sumOfSpendByClient
);
// <3>
Collector<? super ClientCategorySpend, ?, Client> maxSpendingClientByCategory = Collectors.collectingAndThen(
clientSpendByCategory,
map -> map.entrySet().stream()
.max(Comparator.comparing(Map.Entry::getValue))
.map(Map.Entry::getKey).get()
);
return shopping.entrySet().stream()
// <4>
.flatMap(
entry -> entry.getValue().entrySet().stream().map(
entry2 -> new ClientCategorySpend(entry.getKey(),
entry2.getKey().category,
entry2.getKey().price.multiply(BigDecimal.valueOf(entry2.getValue())))
)
).collect(Collectors.groupingBy(ClientCategorySpend::getCategory, maxSpendingClientByCategory));
}
一旦我有了clientcategoryspens
(4)的流,我就按类别对其进行分组。我使用ClientSpendByCategory
收集器(2)在客户端和类别中的总支出之间创建一个映射。这又取决于sumToSpendByClient(1),它基本上是一个将花费相加的减速器。然后,您可以按照您的建议使用collectingandthen
,使用max
将每个map
简化为单个客户端。
我试图动态解析一些JSON到一个Map 但是当我尝试使用一些更复杂的JSON和嵌套信息时失败了。我试图从json解析示例数据。组织 我得到以下错误 异常在线程"main"com.fasterxml.jackson.databind.JsonMapping异常:不能反序列化实例的java.lang.字符串START_OBJECT令牌 有没有办法将复杂的JSON数据解析成映射?
我如何在下面的场景中使用Mapstruct进行bean映射。 现在我想把sourceId映射到targetId,courseName映射到subjectName,studentName映射到memberName(list到list)。
我用的是Protobuf 3。从文档来看,似乎无法定义嵌套贴图: 我正在尝试创建一种消息类型来表示期权链的定价信息(出价和要价)。对于那些不熟悉这些金融工具的人,基本上我有一套“到期日期(YYYYMMDD)”。在每个过期日期中,我都有一组“strikes(float number;如果需要,可以用字符串表示,我同意)”。在每次行使中,我有两个期权,一个“看跌”和一个“看涨”(这被称为期权的“右”)
我尝试使用MapStruct编写映射器类,如下所示: 目前它显示了“未知属性”“customer.customerid”和“usertypes.usertype.userid”等错误。有人能帮我用MapStruct映射所有这些元素吗? 问题2:我们如何绘制跟踪图?1)customerId usertypes->user->userid 2)pdtPrice offers->OffersType->
我用下面的方法尝试了嵌套映射。 我在声明“root_cause”时出错:[{“type”:“mapper_parsing_exception”,“reason”:“root映射定义有不支持的参数:[type:nested]。” 感谢您的帮助。
我尝试在两个列表上循环,过滤嵌套列表,并使用java8特性将结果写回主对象。 因此,到目前为止,位置内部的子列表不会更改,这是显而易见的,因为流和收集确实会创建一个新列表,该列表不会写回位置对象中。所以我的问题是,如果有一种方法可以调用位置对象的setSubList(...)方法并将新列表写入其中。 感谢