开发中遇到填坑
List<ExcelTemplate> excelTemplatesList = new ArrayList<>();
Map<String,List<ExcelTemplate>> mpList=excelTemplatesList.stream().collect(Collectors.groupingBy(ExcelTemplate::getBusinseeType));
for(Map.Entry<String,List<ExcelTemplate>> mp:mpList.entrySet()){
List<ExcelTemplate> templates=mp.getValue();
List<String> disList= ToolUtils.getDuplicateValue(templates,lst->lst.getColumnExcelName());
}
/**校验集合对象,筛选出重复值
* */
public static <E, R> List<R> getDuplicateValue(List<E> list, Function<E, R> function) {
Map<R, Long> frequencies = list.stream().collect(Collectors.groupingBy(function, Collectors.counting()));
return frequencies.entrySet().stream()
.filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()).collect(Collectors.toList());
}
上面方法经过改造如下:
public static int matchStrValue(List<ExcelTemplate> list) {
Map<String, Long> frequencies = list.stream().collect(Collectors.groupingBy(lst->lst.getColumnExcelName(), Collectors.counting()));
List<String> list1=new ArrayList<>();
//key中有多个字段逗号字符串格式,需要校验key中是否有重复,同一个数据类型中,数据中心字段对应文件字段,允许一对多,但不允许一个文件字段对应多个数据中心字段
for(Map.Entry<String,Long> mp:frequencies.entrySet()){
list1.add(mp.getKey());
}
long count = list1.stream().distinct().count();
return new Long(count).intValue();
}
其实list打印出来是
[供应商名称, 单价, 有效期,型号1, 采购表主键, 生产厂家,厂家1,厂家2, 单位, 产品批号, 采购行为, 数量, 通用名, 子公司名称, 日期, 供应商代码, 产品型号,型号1,型号2, 产品规格, 经销商名称, 采购备注, 原厂发货清单, 经销商代码, 采购单号, 仓库, 进货单号, 产品代码, 生产日期, 订单日期, 产品名称, 物权, 产品线, 金额]
但是去重校验却不生效,问题出在map解析上
因为原始的map结构如下,key有一个字符串,也有多个字符串逗号分隔的
{供应商名称=1, 单价=1, 有效期,型号1=1, 采购表主键=1, 生产厂家,厂家1,厂家2=1, 单位=1, 产品批号=1, 采购行为=1, 数量=1, 通用名=1, 子公司名称=1, 日期=1, 供应商代码=1, 产品型号,型号1,型号2=1, 产品规格=1, 经销商名称=1, 采购备注=1, 原厂发货清单=1, 经销商代码=1, 采购单号=1, 仓库=1, 进货单号=1, 产品代码=1, 生产日期=1, 订单日期=1, 产品名称=1, 物权=1, 产品线=1, 金额=1}
但是其实当赋值的时候,mp.getkey(),添加到list<string>中,看似是一个个字符串,其实真正的隐藏的数据结构还是以每一个mp.getkey()获取的string串的,也就是说这时候去重比较,比如看着型号1,型号1,有两个,其实真正原始数据结构为:
有效期,型号1
产品型号,型号1,型号2
这两个其实是两个独立的一组string字符串,所以去重比较会把它当做
(有效期,型号1),(产品型号,型号1,型号2)这样去比较,所以造成根本不重复,所以要一个个拆分成独立的string串才可以,最终修改如下即可:
public static int matchStrValue(List<ExcelTemplate> list) {
Map<String, Long> frequencies = list.stream().collect(Collectors.groupingBy(lst->lst.getColumnExcelName(), Collectors.counting()));
List<String> list1=new ArrayList<>();
//key中有多个字段逗号字符串格式,需要校验key中是否有重复,同一个数据类型中,数据中心字段对应文件字段,允许一对多,但不允许一个文件字段对应多个数据中心字段
for(Map.Entry<String,Long> mp:frequencies.entrySet()){
if(mp.getKey().contains(",")){
String[] split = mp.getKey().split(",");
for(int i=0;i<split.length;i++){
list1.add(split[i]);
}
}else {
list1.add(mp.getKey().toString());
}
}
long count = list1.stream().distinct().count();
return new Long(count).intValue();
调用方法:
List<ExcelTemplate> excelTemplatesList = new ArrayList<>();
Map<String,List<ExcelTemplate>> excelNum = excelTemplatesList.stream().collect(Collectors.groupingBy(e ->e.getDataType()));
校验同一个数据类型中,字段对应是否重复
for(Map.Entry<String,List<ExcelTemplate>> mp:excelNum.entrySet()){
String kk=mp.getKey();
int numCount=ToolUtils.matchStrValue(mp.getValue());
if(numCount!=mp.getValue().size()){
throw new BusinessException(new ErrorInfo("field_distinct","文件字段名称不能重复"));
}
}
如上:再次失误,会导致判断误差,因为拿mp的长度去跟去重后比,肯定不对,细节失误。如数据如下:
mp的原值:
{供应商名称=1, 单价=1, 有效期,型号1=1, 采购表主键=1, 生产厂家,厂家1,厂家2=1, 单位=1, 产品批号=1, 采购行为=1, 数量=1, 通用名=1, 子公司名称=1, 日期=1, 供应商代码=1, 产品型号,型号1,型号2=1, 产品规格=1, 经销商名称=1, 采购备注=1, 原厂发货清单=1, 经销商代码=1, 采购单号=1, 仓库=1, 进货单号=1, 产品代码=1, 生产日期=1, 订单日期=1, 产品名称=1, 物权=1, 产品线=1, 金额=1}
由此可以看出,map长度其实是没有拆分前的长度,比如,有效期,型号1这一组多个字符串,而list计算去重,是将mp的key多个值一个个拆分后,然后在去重,长度肯定不一样,所以修改如下:
public static Map<Integer,Integer> matchStrValue(List<ExcelTemplate> list) {
Map<String, Long> frequencies = list.stream().collect(Collectors.groupingBy(lst->lst.getColumnExcelName(), Collectors.counting()));
List<String> list1=new ArrayList<>();
Map<Integer,Integer> countMap=new HashMap<>();
for(Map.Entry<String,Long> mp:frequencies.entrySet()){
if(mp.getKey().contains(",")){
String[] split = mp.getKey().split(",");
for(int i=0;i<split.length;i++){
list1.add(split[i]);
}
}else {
list1.add(mp.getKey().toString());
}
}
long count = list1.stream().distinct().count();
return countMap;
}
for(Map.Entry<String,List<ExcelTemplate>> mp:excelNum.entrySet()){
String kk=mp.getKey();
Map<Integer,Integer> numCount=ToolUtils.matchStrValue(mp.getValue());
for(Map.Entry<Integer,Integer> num:numCount.entrySet()){
if(num.getKey()!=num.getValue()){
throw new BusinessException(new ErrorInfo("field_distinct","文件字段名称不能重复"));
}
}
}
网友评论