分组的多个字段有:员工ID、员工编码、员工名称、考勤配置ID、考勤配置名称。
统计的多个字段有:总条数、总工作小时数、实际的小时数。
list 集合对象通过多个分组字段,统计多个字段,合并行,返回list集合。
二 代码实例
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @className: AttendanceStatisticByDayDTO
* @description: 包含 分组字段 和 统计字段
* @date: 2021/3/14
* @author: cakin
*/
@Data
class AttendanceStatisticByDayDTO {
// 分组字段开始
/**
* 员工ID
*/
private String userId;
/**
* 员工编码
*/
private String userCode;
/**
* 员工名称
*/
private String userName;
/**
* 考勤配置ID
*/
private String attendanceTypeId;
/**
* 考勤配置名称
*/
private String attendanceTypeName;
// 分组字段结束
// 统计字段开始
/**
* 应上时长
*/
private Double workDueHour;
/**
* 实上时长
*/
private Double workRealHour;
/**
* 统计次数
*/
private Long statisticTimes;
// 统计字段结束
}
/**
* @className: ComputeGroupByDTO
* @description: 统计字段
* @date: 2021/3/14
* @author: cakin
*/
@Data
class ComputeGroupByDTO {
/**
* 总条数
*/
private Long totalCount;
/**
* 总的工作小时数
*/
private Double dueHourSum;
/**
* 真实的小时数
*/
private Double realHourSum;
}
/**
* @ClassName: GroupSumManyToMany
* @Description: 多字段分组,多字段求和 参考:https://blog.csdn.net/qq_38428623/article/details/103754446
* @Date: 2021/3/14
* @Author: cakin
*/
public class GroupSumManyToMany {
/**
* 功能描述:得到分组字段
*
* @param attendanceStatisticByDayDTO 考勤统计
* @return 返回分组的KEY
*/
private static AttendanceStatisticByDayDTO fetchGroupKey(final AttendanceStatisticByDayDTO attendanceStatisticByDayDTO) {
final AttendanceStatisticByDayDTO statisticByDay = new AttendanceStatisticByDayDTO();
statisticByDay.setUserId(attendanceStatisticByDayDTO.getUserId()); // 员工ID
statisticByDay.setUserCode(attendanceStatisticByDayDTO.getUserCode()); // 员工编码
statisticByDay.setUserName(attendanceStatisticByDayDTO.getUserName()); // 员工名称
statisticByDay.setAttendanceTypeId(attendanceStatisticByDayDTO.getAttendanceTypeId()); // 考勤配置ID
statisticByDay.setAttendanceTypeName(attendanceStatisticByDayDTO.getAttendanceTypeName()); // 考勤配置名称
return statisticByDay;
}
/**
* 功能描述:测试多字段分组,多字段求和
*
* @param args 命令行
* @author cakin
* @date 2021/3/14
*/
public static void main(final String[] args) {
final List<AttendanceStatisticByDayDTO> attendanceStatisticByDayDTOS = new ArrayList<>();
// 初始化数据
for (long i = 0; i < 100; i++) {
final AttendanceStatisticByDayDTO attendanceStatisticByDayDTO = new AttendanceStatisticByDayDTO();
attendanceStatisticByDayDTO.setUserId("" + (i % 5));
attendanceStatisticByDayDTO.setUserCode("" + (i % 5));
attendanceStatisticByDayDTO.setUserName("" + (i % 5));
attendanceStatisticByDayDTO.setWorkDueHour((double) (i % 5));
attendanceStatisticByDayDTO.setWorkRealHour((double) (i % 5));
attendanceStatisticByDayDTO.setStatisticTimes(i);
attendanceStatisticByDayDTO.setAttendanceTypeId("" + (i % 5));
attendanceStatisticByDayDTO.setAttendanceTypeName("" + (i % 5));
attendanceStatisticByDayDTOS.add(attendanceStatisticByDayDTO);
}
/**
* 获取分组结果
* 分组字段:员工ID、员工编码、员工名称、考勤配置ID、考勤配置名称,通过 fetchGroupKey 获取
* 统计字段:通过 collectingAndThen 的第2个参数定义统计方式
*/
final Map<AttendanceStatisticByDayDTO, ComputeGroupByDTO> groupByMap =
attendanceStatisticByDayDTOS
.stream()
.collect(Collectors.groupingBy(n -> fetchGroupKey(n), Collectors.collectingAndThen(Collectors.toList(), m -> {
// totalCount 采用计数方式
final long totalCount = m.stream().count();
// dueHourSum 采用求和方式
final Double dueHourSum = m.stream().mapToDouble(AttendanceStatisticByDayDTO::getWorkDueHour).sum();
// realHourSum 采用求和方式
final Double realHourSum = m.stream().mapToDouble(AttendanceStatisticByDayDTO::getWorkDueHour).sum();
final ComputeGroupByDTO computeGroupBy = new ComputeGroupByDTO();
computeGroupBy.setTotalCount(totalCount); // 计数
computeGroupBy.setDueHourSum(dueHourSum); // 求和
computeGroupBy.setRealHourSum(realHourSum); // 求和
return computeGroupBy;
})));
System.out.println("===============结果大小===============================");
System.out.println("groupByMap=" + groupByMap.size());
List<AttendanceStatisticByDayDTO> list = new ArrayList<>();
System.out.println("===============中间结果===============================");
groupByMap.forEach((k, v) -> {
System.out.println(k);
System.out.println(v);
AttendanceStatisticByDayDTO attendanceStatisticByDayDTO = new AttendanceStatisticByDayDTO();
BeanUtils.copyProperties(k, attendanceStatisticByDayDTO);
attendanceStatisticByDayDTO.setStatisticTimes(v.getTotalCount());
attendanceStatisticByDayDTO.setWorkDueHour(v.getDueHourSum());
attendanceStatisticByDayDTO.setWorkRealHour(v.getRealHourSum());
list.add(attendanceStatisticByDayDTO);
});
System.out.println("===============最终结果===============================");
for (AttendanceStatisticByDayDTO attendanceStatisticByDayDTO : list) {
System.out.println(attendanceStatisticByDayDTO);
}
}
}
三 代码测试结果
===============结果大小=============================== groupByMap=5 ===============中间结果=============================== AttendanceStatisticByDayDTO(userId=2, userCode=2, userName=2, attendanceTypeId=2, attendanceTypeName=2, workDueHour=null, workRealHour=null, statisticTimes=null) ComputeGroupByDTO(totalCount=20, dueHourSum=40.0, realHourSum=40.0) AttendanceStatisticByDayDTO(userId=4, userCode=4, userName=4, attendanceTypeId=4, attendanceTypeName=4, workDueHour=null, workRealHour=null, statisticTimes=null) ComputeGroupByDTO(totalCount=20, dueHourSum=80.0, realHourSum=80.0) AttendanceStatisticByDayDTO(userId=0, userCode=0, userName=0, attendanceTypeId=0, attendanceTypeName=0, workDueHour=null, workRealHour=null, statisticTimes=null) ComputeGroupByDTO(totalCount=20, dueHourSum=0.0, realHourSum=0.0) AttendanceStatisticByDayDTO(userId=3, userCode=3, userName=3, attendanceTypeId=3, attendanceTypeName=3, workDueHour=null, workRealHour=null, statisticTimes=null) ComputeGroupByDTO(totalCount=20, dueHourSum=60.0, realHourSum=60.0) AttendanceStatisticByDayDTO(userId=1, userCode=1, userName=1, attendanceTypeId=1, attendanceTypeName=1, workDueHour=null, workRealHour=null, statisticTimes=null) ComputeGroupByDTO(totalCount=20, dueHourSum=20.0, realHourSum=20.0) ===============最终结果=============================== AttendanceStatisticByDayDTO(userId=2, userCode=2, userName=2, attendanceTypeId=2, attendanceTypeName=2, workDueHour=40.0, workRealHour=40.0, statisticTimes=20) AttendanceStatisticByDayDTO(userId=4, userCode=4, userName=4, attendanceTypeId=4, attendanceTypeName=4, workDueHour=80.0, workRealHour=80.0, statisticTimes=20) AttendanceStatisticByDayDTO(userId=0, userCode=0, userName=0, attendanceTypeId=0, attendanceTypeName=0, workDueHour=0.0, workRealHour=0.0, statisticTimes=20) AttendanceStatisticByDayDTO(userId=3, userCode=3, userName=3, attendanceTypeId=3, attendanceTypeName=3, workDueHour=60.0, workRealHour=60.0, statisticTimes=20) AttendanceStatisticByDayDTO(userId=1, userCode=1, userName=1, attendanceTypeId=1, attendanceTypeName=1, workDueHour=20.0, workRealHour=20.0, statisticTimes=20)
发表评论