利用Stream API对List集合进行分组求和统计(2种方式)
一、根据String类型字段分组,求BigDecimal类型的和
1.原始数据及需求
需求:发货地和收货地相同的数据,合并这两项,并计算其他两项的数据之和
拿到的原始数据如下图所示:
2.利用StreamAPI处理List集合
代码如下:
@Override
public Map<String, Object> countCarLine(String begin, String end) {
// 线路统计
List<CarLineVO> carLineVOS = dashboardMapper.countCarLine(begin, end);
// 接收处理后的数据
List<CarLineVO> newCarLineVOs = new ArrayList<>();
// 数据分组统计处理
carLineVOS.parallelStream()
.collect(Collectors.groupingBy(item -> (item .getDeliverAddress() + item .getCollectAddress()), Collectors.toList()))
.forEach((id, transfer) -> {
transfer.stream()
.reduce((a, b) -> new CarLineVO(a.getDeliverAddress(), a.getCollectAddress(), a.getCollectNetWeight().add(b.getCollectNetWeight()), a.getTotalFreightPrice().add(b.getTotalFreightPrice())))
.ifPresent(newCarLineVOs::add);
});
Map<String, Object> map = new HashMap<>();
map.put("carLine", newCarLineVOs);
return map;
}
3.处理后得到符合需求的数据
处理后的数据:
4.实体类
CarLineVO类:
/**
* @Author: Ron
* @Create: 2020 10:14
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarLineVO {
private String deliverAddress;
private String collectAddress;
private BigDecimal collectNetWeight;
private BigDecimal totalFreightPrice;
}
实体类使用lombok插件
二、根据String类型字段分组,求int类型的和
1.实体类
package com.qs.modules.formMaterial.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.qs.db.base.model.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 申请单和物料中间表
*
* @author Charles
* @since 2021/09/30
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("form_material")
@ApiModel(value="申请单和物料中间表", description="申请单和物料中间表")
public class FormMaterial extends BaseModel {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 申请单id
*/
@ApiModelProperty(value = "申请单id")
private String applicationFormId;
/**
* 申请物料的id
*/
@ApiModelProperty(value = "申请物料的id")
private String materialId;
/**
* 申请物料的数量
*/
@ApiModelProperty(value = "申请物料的数量")
private int materialCount;
/**
* 取出的物料总数
*/
@ApiModelProperty(value = "取出的物料总数")
private int takeTotalCount;
/**
* 剩余物料数量
*/
@ApiModelProperty(value = "剩余物料数量")
private int remainingCount;
/**
* 此物料是否被领取完:0即未领取完,1即领取完
*/
@ApiModelProperty(value = "此物料是否被领取完")
private String materialFlag;
@TableField(exist = false)
private String materialNumber;
@TableField(exist = false)
private String materialName;
/**
* 传入的查询条件:物料数量
*/
@TableField(exist = false)
private String queryMaterialCount;
/**
* 入参
*/
public static final String APPLICATION_FORM_ID = "application_form_id";
public static final String MATERIAL_COUNT = "material_count";
}
2.需求
传过来的数据是这样的,物料id-materialId相同的话,物料数量求和materialCount
[
{
"materialId": "1453637685838372866",
"materialCount": "15"
},
{
"materialId": "1453638065183809538",
"materialCount": "21"
},
{
"materialId": "1482879355628838914",
"materialCount": "8"
}
]
3.Stream处理
// 申请的重复物料信息,根据物料id,申请的物料数量求和合并成一条数据
// formMaterialList就是来源的集合
List<FormMaterial> newList = new ArrayList<>();
formMaterialList.parallelStream()
.collect(Collectors.groupingBy(FormMaterial::getMaterialId, Collectors.toList()))
.forEach(
(materialId, list) ->
list.stream()
.reduce(
(a, b) ->
new FormMaterial()
.setMaterialId(a.getMaterialId())
.setMaterialCount(a.getMaterialCount() + b.getMaterialCount()))
.ifPresent(newList::add));
三、总结
感觉和for循环差不多,流式运算里也是带了.forEach
的方法了。
分类:
Stream流式运算
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!