利用Stream API對List集合進行分組求和統計(2種方式)


一、根據String類型字段分組,求BigDecimal類型的和

1.原始數據及需求

需求:發貨地和收貨地相同的數據,合並這兩項,並計算其他兩項的數據之和

拿到的原始數據如下圖所示:

image

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.處理后得到符合需求的數據

處理后的數據:

image

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的方法了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM