最近一个项目需求,后台录入市、区的经纬度信息,然后需要按照市、区来进行分组统计数量,去求如下:
部分表数据如下:
需求分析:按照市,区嵌套分组,区的分组好说,市的分组稍微麻烦一点,要先知道区的分组数量后,汇总求和。可以借助stream流的groupingBy分组函数轻松实现。
实体类:
public class MAssistFarmerInfo {
/**
* 市code
*/
private String cityCode;
/**
* 市名称
*/
private String cityName;
/**
* 区code
*/
private String countyCode;
private String countyName;
private String areaInfo;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
}
定义数据返回实体:
@Data
public class AreaInfoDto {
/**
* 地区code
*/
private String code;
/**
* 地区名称
*/
private String name;
/**
* 总计数
*/
private Long total;
/**
* 子地区
*/
private List<AreaInfoDto> children;
}
代码实现:
List<MAssistFarmerInfo> list = getAllData();
List<AreaInfoDto> collect = list.stream()
//按照市区嵌套分组
.collect(Collectors.groupingBy(
MAssistFarmerInfo::getCityCode,
Collectors.groupingBy(MAssistFarmerInfo::getCountyCode, Collectors.counting())
))
//转换,上一步分组后,得到的是Map<String,Map<String,Long>>,需要转换成List<AreaInfoDto>,
//键是市的code,值是Map<String,Long>,即每个市下的区县code和数量
.entrySet().stream().map(item -> {
AreaInfoDto earaInfo = new AreaInfoDto();
earaInfo.setCode(item.getKey());
List<AreaInfoDto> children = new ArrayList<>();
long count = 0;
for (Map.Entry<String, Long> stringLongEntry : item.getValue().entrySet()) {
AreaInfoDto childrenInfo = new AreaInfoDto();
childrenInfo.setCode(stringLongEntry.getKey());
childrenInfo.setTotal(stringLongEntry.getValue());
children.add(childrenInfo);
count += stringLongEntry.getValue();
}
earaInfo.setTotal(count);
earaInfo.setChildren(children);
return earaInfo;
}).collect(Collectors.toList());