HashMap containsKey toString equals hashCode

HashMap containsKey toString equals hashCode
HashMap的key一般是自定义类,一定要重载toString、equals和hashCode方法,
这样才能使用HashMap.containsKey()方法判断是否包含该该键值,否则永远都是假!
这里要巧妙利用重载toString方法,来提供自定义类的唯一标识。

RecordNumber是自定义类,由3个字段组成,如果这3个字段都相同,就认为该类实例相同,
toString方法非常容易构造这种这个条件。

//如果 Main.hmMyDB 包含 Main.hmDS.keySet(),就不需要动作,不含就动作
System.out.println("需要压栈的任务是");
for (RecordNumber v_rn : Main.hmDS.keySet()) {
if (!Main.hmMyDB.containsKey(v_rn)) {
Main.taskStack.add(v_rn);
System.out.println("压栈"+v_rn);
} else {
System.out.println("MyDB已经包含");
}
}

public boolean equals(Object O) {
return (O instanceof MyClass) &&
toString().equals(((MyClass)O).toString());
}

//数据源 表名 时间 (记录数量)
public class RecordNumber {

public final String DataSource;
public final String TableName;
public final Date DateTime;

public RecordNumber(String DataSource, String TableName, Date DateTime) {
this.DataSource = DataSource;
this.TableName = TableName;
this.DateTime = DateTime;
}

[b]@Override
public String toString() {
return (this.DataSource + "**" + this.TableName + "**" + this.DateTime);
}[/b]

@Override
public boolean equals(Object o) {
return (o instanceof RecordNumber)
&& toString().equals(((RecordNumber) o).toString());
}

@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + (this.DataSource != null ? this.DataSource.hashCode() : 0);
hash = 37 * hash + (this.TableName != null ? this.TableName.hashCode() : 0);
hash = 37 * hash + (this.DateTime != null ? this.DateTime.hashCode() : 0);
return hash;
}
}
①根据原材料物料编码,原材料规格型号,零件的规格值(零件的一个动态属性),零件的工艺路线进行分组并合并数量 ②获取套料配置表,根据母排定尺采购配置,筛选出定尺寸数据,注意需同时满足长度和数量两个条件,直接将原材料物料编码,规格型号,长度(即对应零件的规格值),数量加入到母排套料结果中 ③对于非定尺数据的,按物料编码,规格型号,类型(是直线还是弯头,看输入中是否要区分)进行分组,每组中先按工艺路线序号,再按长度(规格值)进行正排(按长度正排的目的是使得小尺寸的先加工出来,避免机器夹不住) ④对每组进行计算,通过配置表获取单根长度,固定损耗,每刀损耗,并新建一根初始铜排(铜排的可用长度为标准长度-固定损耗-已用长度)加入到可选铜排库中,遍历分组中的数据,遍历每个数据的数量,遍历可选铜排库,若铜排的可用长度大于等于长度(规格值)+每刀损耗(铜排的第一个零件不用考虑每刀损耗),则把这个零件套到这根铜排里,若零件是套到铜排上的第二个零件或之后的,则铜排的已用长度加上零件长度和每刀损耗,否则只加零件长度,若套不到任何一根铜排中,则新增一根初始铜排,把这个零件套到初始铜排中,最后输出可选铜排库与其上套的零件(每组都有可选铜排库) ⑤输出套料结果,遍历可选铜排库,对原先定义的浮点数转成整型,累加固定损耗和各零件的长度,累加 (零件数量-1)*每刀损耗,若累加值是50的倍数则不用再处理,若不是,则进位到下一个50的倍数,对这根铜排上套的零件进行hash,根据母排相序和零件长度,相同零件的个数形成备注信息,将定尺寸数据加到显示结果中,按物料编码,规格型号,长度进行排序,将相同的结果进行合并,数量累加,生成序号,进行展示 (2)型材套料: ①根据原材料物料编码、原材料规格型号、零件的规格值(零件的一个动态属性)、零件的工艺路线进行分组并合并数量 ②不同工艺路线的在不同组,相同工艺路线的按锯切工序的锯切类型是否相同判断是否在不同组,直线段的锯切工序的锯切类型为空,那12种特殊单元代号的盖侧板零件的锯切工序的锯切类型为GB,CB ③根据定尺采购配置,筛选出定尺寸数据,并且工序代码不为CB、GB(CB、GB为特殊的单元代号的侧板、盖板的加工代号,考虑直接从模型中获取,在物料的某个属性直接体现)的数据 ④对于其他数据,直线段在同个组的,先按数量模2后余数为0的,加入到偶数组,数量减1后大于0的部分加入到偶数组,1的部分加入到奇数组,其余数量为1的加入到奇数组对于CB、GB的加入到偶数组,这个一定可以成对套,对于其他的,先都放到奇数组,即放一根排上,如果型材套料加工工艺配置做了,按配置将锯切类型都是可以机器做的先套在一起,最后套完以后需要判断这跟是否都是符合可以机器做的再考虑根据工序将其他的中可以成对套的偶数部分加入到偶数组中 ⑤对偶数组和奇数组分别进行套料计算 ⑥偶数组的数量先除以2,按物料编码,规格型号,工艺路线代码分组,每组中先按长度正排,再按工艺路线代码正排(按长度正排的目的是使得小尺寸的先加工出来,避免机器夹不住) ⑦对每组进行计算,通过配置表获取单根长度,固定损耗,每刀损耗,并新建一根初始型材(型材的可用长度为标准长度-固定损耗-已用长度)加入到可选型材库中,遍历分组中的数据,遍历每个数据的数量,遍历可选型材库,若型材的可用长度大于等于长度(规格值)+每刀损耗(型材的第一个零件不用考虑每刀损耗),则把这个零件套到这根型材里,若零件是套到型材上的第二个零件或之后的,则型材的已用长度加上零件长度和每刀损耗,否则只加零件长度,若套不到任何一根型材中,则新增一根初始型材,把这个零件套到初始型材中,最后输出可选型材库与其上套的零件,然后将型材的数量设为2(1乘以2,即将数量恢复),对一组套完后,考虑最小套料长度(340),若长度小于最小套料长度,则这根排上应该继续套其他零件 ⑧对奇数组直接按物料编码,规格型号,工艺路线代码分组,每组中先按长度正排,再按工序代码正排 ⑨进行套料计算,逻辑同偶数组 输出套料结果,遍历可选型材库,对原先定义的浮点数转成整型,累加固定损耗和各零件的长度,累加 (零件数量-1)*每刀损耗,形成长度,对这根铜排上套的零件进行hash,根据母排相序和零件长度,相同零件的个数形成备注信息,这根型材上总的零件数作为段数,将定尺寸数据加到显示结果中,按物料编码,规格型号,长度进行排序,生成序号,进行展示 @Override public List<NestResultHeadVO> countNestResult(TaskBomVO taskBomVO,String tenantId,String isDiff) { //已经根据task获取到bom信息 遍历bom构建套料计算所需数组 List<NestResultInfoVO> nestResults = new ArrayList<>(); if (taskBomVO != null) { for (BomInfoVO item : taskBomVO.getBomInfoVOS()) { processBomItem(item, nestResults); } } List<NestConfig> nestConfigs = nestConfigMapper.selectAll(tenantId); // 为每个分组创建筛选逻辑 Map<String, List<NestResultInfoVO>> resultMap = new LinkedHashMap<>(); // 按nest_type分组筛选条件 Map<String, List<NestConfig>> groupedFilters = nestConfigs.stream() .collect(Collectors.groupingBy( NestConfig::getNestType, Collectors.toList() )); groupedFilters.forEach((nestType, conditions) -> { resultMap.put(nestType, nestResults.stream() .filter(item -> conditions.stream().anyMatch(cond -> Objects.equals(item.getMaterialCategory(), cond.getMaterialCategory()) && Objects.equals(item.getMaterialSubcategory(), cond.getMaterialSubcategory()) )) .collect(Collectors.toList())); }); List<NestResultInfoVO> mList= resultMap.get("母排套料"); if("0".equals(isDiff)){//即母排的直线和弯头需要分开套 for (NestResultInfoVO nest: mList) { NestUnitCodeInfoVO nestUnitCodeInfoVO = nestResultCountMapper.getType(nest.getUnitCode()); //TODO 在这里做母排的直接和弯头的分组标识 绑定计算行中一条 计算成完成后 将带标识的数据存入套料结果行表中 if (nestUnitCodeInfoVO != null) { nest.setType(nestUnitCodeInfoVO.getType()); } } } //数据的组装到此结束,现在开始计算逻辑 List<NestResultVO> mListResult = autoMNest(mList);//母排计算 List<NestResultVO> xListResult = autoXNest(resultMap.get("型材套料"));//型材计算 //封装数据返回 List<NestResultHeadVO> nestResultHeadVO = new ArrayList<>(); TaskMast taskMast = taskMastMapper.selectByPrimaryKey(taskBomVO.getTaskId()); if(mListResult != null && mListResult.size() > 0){ NestResultHeadVO mResult = new NestResultHeadVO(); mResult.setNestNo(null); mResult.setSoNo(taskMast.getSoNo()); mResult.setSubProjectNo(taskMast.getBatchNo()); mResult.setTaskId(taskMast.getId()); mResult.setType(1); List<NestResultLineVO> mLineResult = new ArrayList<>(); for (NestResultVO m: mListResult) { NestResultLineVO mLine = new NestResultLineVO(); List<NestResultLineMaterialVO> nestResultLineMaterialVOList = new ArrayList<>(); mLine.setMaterialId(m.getSmaterialId()); mLine.setMaterialNo(m.getMaterialNo()); mLine.setMaterialName(m.getMaterialName()); mLine.setMaterialDesc(m.getMaterialDescription()); mLine.setLength(m.getValue()); mLine.setNumber(m.getCompQty()); mLine.setChildrenCount(m.getCount()); mLine.setIsInventory(false); if(m.getType().equals("ZX")){ mLine.setMpType("1"); mLine.setMpTypeText("直线"); }else if(m.getType().equals("WT")){ mLine.setMpType("2"); mLine.setMpTypeText("弯通"); }else{ mLine.setMpType("3"); mLine.setMpTypeText("混合"); } mLineResult.add(mLine); } nestResultHeadVO.add(mResult); } if(xListResult != null && xListResult.size() > 0) { NestResultHeadVO xResult = new NestResultHeadVO(); xResult.setNestNo(null); xResult.setSoNo(taskMast.getSoNo()); xResult.setSubProjectNo(taskMast.getBatchNo()); xResult.setTaskId(taskMast.getId()); xResult.setType(2); List<NestResultLineVO> mLineResult = new ArrayList<>(); for (NestResultVO x: mListResult) { NestResultLineVO xLine = new NestResultLineVO(); List<NestResultLineMaterialVO> nestResultLineMaterialVOList = new ArrayList<>(); xLine.setMaterialId(x.getSmaterialId()); xLine.setMaterialNo(x.getMaterialNo()); xLine.setMaterialName(x.getMaterialName()); xLine.setMaterialDesc(x.getMaterialDescription()); xLine.setLength(x.getValue()); xLine.setNumber(x.getCompQty()); xLine.setChildrenCount(x.getCount()); xLine.setIsInventory(false); mLineResult.add(xLine); } nestResultHeadVO.add(xResult); } return nestResultHeadVO; } // 递归处理每个BomInfoVo节点及其嵌套组件 private static void processBomItem(BomInfoVO item, List<NestResultInfoVO> collector) { if (item == null) return; // 添加当前节点的static_attrs collector.add(new NestResultInfoVO(item)); // 处理嵌套组件 if (item.getComponents() != null) { for (BomComponent component : item.getComponents()) { processComponent(component, collector); } } } // 递归处理每个Component节点及其嵌套组件 private static void processComponent(BomComponent component, List<NestResultInfoVO> collector) { if (component == null) return; // 添加当前组件的static_attrs collector.add(new NestResultInfoVO(component)); // 递归处理嵌套组件 if (component.getComponents() != null) { for (BomComponent subComponent : component.getComponents()) { processComponent(subComponent, collector); } } } /** * 母排计算逻辑 * @return */ private List<NestResultVO> autoMNest(List<NestResultInfoVO> param){ Map<String, NestResultInfoVO> mergedDemandMap = new HashMap<>(); for (NestResultInfoVO copperDemand : param) { String key = copperDemand.getMaterialNo() + "|" + copperDemand.getSpecification() + "|" + copperDemand.getValue() + "|" + copperDemand.getRouteName(); if (mergedDemandMap.containsKey(key)) { NestResultInfoVO existingData = mergedDemandMap.get(key); existingData.setCompQty(existingData.getCompQty() + copperDemand.getCompQty()); } else { mergedDemandMap.put(key, copperDemand); } } // Print merged results for (NestResultInfoVO data : mergedDemandMap.values()) { // logger.debug("merged results: {}", data); } //2. 筛选长度>=1000, 数量大于10的,作为定尺寸数据 List<NestResultInfoVO> fixedCopperDemands = new ArrayList<>(); for (NestResultInfoVO data : mergedDemandMap.values()) { if (data.getCompQty() >= 1 && data.getValue() >= 6000) { fixedCopperDemands.add(data); } } List<NestResultInfoVO> unfixedCopperDemands = new ArrayList<>(); for (NestResultInfoVO data : mergedDemandMap.values()) { if (fixedCopperDemands.contains(data)) { continue; } unfixedCopperDemands.add(data); } //3. 单W/L分别套料计算 List<CopperBin> copperBins = new ArrayList<>(); unfixedCopperDemands.stream().collect(Collectors.groupingBy(NestResultInfoVO::getAnGroupKey)).forEach((materialAndSpec, g) -> { g.sort(Comparator.comparing(NestResultInfoVO::getRouteName).thenComparingDouble(NestResultInfoVO::getValue).reversed()); copperBins.addAll(calculateM(g)); }); //5. 输出结果 List<NestResultVO> results = new ArrayList<>(); for (int i = 0; i < copperBins.size(); i++) { CopperBin copperBin = copperBins.get(i); NestResultVO copperNesting = new NestResultVO(); NestResultInfoVO md = copperBin.getCopperDemands().get(0); copperNesting.setMaterialNo(md.getMaterialNo()); copperNesting.setMaterialDescription(md.getMaterialDescription()); //TODO: 物料描述 copperNesting.setSpecification(md.getSpecification()); copperNesting.setUnitCodeName(md.getUnitCodeName()); // copperNesting.setValue(copperBin.getUsed() + copperBin.getFixedLoss()); // 舍位 AtomicInteger sum = new AtomicInteger(Double.valueOf(copperBin.getFixedLoss()).intValue()); copperBin.getCopperDemands().stream().collect(Collectors.groupingBy(NestResultInfoVO::hashCode)).forEach((hc, mds) -> { double groupSum = mds.stream().mapToDouble(NestResultInfoVO::getValue).sum(); sum.addAndGet(Double.valueOf(groupSum).intValue()); } ); sum.addAndGet(Double.valueOf((copperBin.getCopperDemands().size() - 1) * copperBin.getPerLoss()).intValue()); copperNesting.setValue(roundUpToNearestFifty(sum.get())); copperNesting.setCompQty(copperBin.getCount()); StringBuilder sbr = new StringBuilder(); copperNesting.setRemark(sbr.toString()); copperNesting.setCount(copperBin.getCopperDemands().size()); results.add(copperNesting); } fixedCopperDemands.forEach(md -> { NestResultVO copperNesting = new NestResultVO(); copperNesting.setMaterialNo(md.getMaterialNo()); copperNesting.setMaterialDescription(md.getMaterialDescription()); //TODO: 物料描述 copperNesting.setSpecification(md.getSpecification()); copperNesting.setValue(md.getValue().intValue()); copperNesting.setUnitGroupName(md.getUnitCodeName()); copperNesting.setCompQty(md.getCompQty()); copperNesting.setCount(1); results.add(copperNesting); }); results.sort(Comparator.comparing(NestResultVO::getMaterialNo). thenComparing(NestResultVO::getSpecification).thenComparing(NestResultVO::getValue)); // 合并同类项 Map<String, NestResultVO> mergedResult = new HashMap<>(); results.forEach(r -> { String key = r.getMaterialNo() + "|" + r.getSpecification() + "|" + r.getValue() + "|" + r.getUnitCodeName() + "|" + r.getRemark() + "|" + r.getCompQty(); if (mergedResult.containsKey(key)) { NestResultVO existingData = mergedResult.get(key); existingData.setCompQty(existingData.getCompQty() + r.getCompQty()); } else { mergedResult.put(key, r); } }); List<NestResultVO> finalResults = new ArrayList<>(mergedResult.values()); for (int i = 0; i < finalResults.size(); i++) { finalResults.get(i).setIndex(i + 1); } return finalResults; } public List<CopperBin> calculateM(List<NestResultInfoVO> CopperDemands) { List<CopperBin> copperBins = new ArrayList<>(); copperBins.add(new CopperBin(6000, 15, 5)); for (NestResultInfoVO copperDemand : CopperDemands) { for (int i = 0; i < copperDemand.getCompQty(); i++) { boolean placed = false; for (CopperBin copperBin : copperBins) { if (copperBin.getRemaining() >= copperDemand.getValue() + copperBin.getFixedLoss()) { copperBin.addDemand(copperDemand); placed = true; break; } } if (!placed) { CopperBin newCopperBin = new CopperBin(6000, 15, 5); newCopperBin.addDemand(copperDemand); copperBins.add(newCopperBin); } } } return copperBins; } public static int roundUpToNearestFifty(int number) { // 如果number已经是50的倍数,直接返回 if (number % 50 == 0) { return number; } // 否则,进位到下一个50的倍数 return ((number / 50) + 1) * 50; } private List<NestResultVO> autoXNest(List<NestResultInfoVO> param) { //1. 要将Excel数据按物料编码、规格、规格值和备注进行合并并汇总数量 Map<String, NestResultInfoVO> mergedDemandMap = new HashMap<>(); for (NestResultInfoVO extrusionsDemand : param) { String key = extrusionsDemand.getMaterialNo() + "|" + extrusionsDemand.getSpecification() + "|" + extrusionsDemand.getValue() + "|" + extrusionsDemand.getRouteName(); if (mergedDemandMap.containsKey(key)) { NestResultInfoVO existingData = mergedDemandMap.get(key); existingData.setCompQty(existingData.getCompQty() + extrusionsDemand.getCompQty()); } else { mergedDemandMap.put(key, extrusionsDemand); } } // Print merged results for (NestResultInfoVO data : mergedDemandMap.values()) { // LOGGER.debug("merged results: {}", data); } //2. 筛选长度>=1000, 数量大于10的,作为定尺寸数据 List<NestResultInfoVO> fixedExtrusionsDemands = new ArrayList<>(); for (NestResultInfoVO data : mergedDemandMap.values()) { if (data.getCompQty() >= 10 && data.getValue() >= 1000 // && data.isNotCBOrGB() ) { fixedExtrusionsDemands.add(data); } } //3. 分组数据 // 3.1 第一组包含 // - 数量为偶数的 // - 数量为奇数并减1后仍大于0的项 // 3.2 第二组包含数量为奇数并不在第一组中的项 // 双数 List<NestResultInfoVO> evenGroup = new ArrayList<>(); // 单数 List<NestResultInfoVO> oddGroup = new ArrayList<>(); for (NestResultInfoVO data : mergedDemandMap.values()) { if (fixedExtrusionsDemands.contains(data)) { continue; // Skip already filtered data } int quantity = data.getCompQty(); if (quantity % 2 == 0) { evenGroup.add(data); } else if (quantity - 1 > 0) { NestResultInfoVO modifiedData = new NestResultInfoVO(); modifiedData.setMaterialNo(data.getMaterialNo()); modifiedData.setMaterialDescription(data.getMaterialDescription()); modifiedData.setSpecification(data.getSpecification()); modifiedData.setValue(data.getValue()); modifiedData.setCompQty(quantity - 1); modifiedData.setUnitCodeName(data.getUnitCodeName()); modifiedData.setRouteName(data.getRouteName()); evenGroup.add(modifiedData); data.setCompQty(1); oddGroup.add(data); } else { oddGroup.add(data); } } //4. 单/双分别套料计算 List<ExtrusionsBin> extrusionsBins = new ArrayList<>(); evenGroup.forEach(data -> data.setCompQty(data.getCompQty() / 2)); evenGroup.stream().collect(Collectors.groupingBy(NestResultInfoVO::getAnGroupKey)).forEach((materialAndSpec, g) -> { g.sort(Comparator.comparingDouble(NestResultInfoVO::getValue).reversed().thenComparing(NestResultInfoVO::getRouteName)); List<ExtrusionsBin> evenExtrusionsBins = calculateX(g); for (ExtrusionsBin extrusionsBin : evenExtrusionsBins) { extrusionsBin.setCount(2); } extrusionsBins.addAll(evenExtrusionsBins); }); oddGroup.stream().collect(Collectors.groupingBy(NestResultInfoVO::getAnGroupKey)).forEach((materialAndSpec, g) -> { g.sort(Comparator.comparingDouble(NestResultInfoVO::getValue).reversed().thenComparing(NestResultInfoVO::getRouteName)); extrusionsBins.addAll(calculateX(g)); }); //5. 输出结果 List<NestResultVO> results = new ArrayList<>(); for (int i = 0; i < extrusionsBins.size(); i++) { ExtrusionsBin extrusionsBin = extrusionsBins.get(i); NestResultVO extrusionsNesting = new NestResultVO(); NestResultInfoVO md = extrusionsBin.getExtrusionsDemands().get(0); extrusionsNesting.setMaterialNo(md.getMaterialNo()); extrusionsNesting.setMaterialDescription(md.getMaterialDescription()); extrusionsNesting.setSpecification(md.getSpecification()); extrusionsNesting.setUnitGroupName(md.getUnitCodeName()); // nesting.setValue(bin.getUsed() + bin.getFixedLoss()); // 舍位 AtomicInteger sum = new AtomicInteger(Double.valueOf(extrusionsBin.getFixedLoss()).intValue()); extrusionsBin.getExtrusionsDemands().stream().collect(Collectors.groupingBy(NestResultInfoVO::hashCode)).forEach((hc, mds) -> { double groupSum = mds.stream().mapToDouble(NestResultInfoVO::getValue).sum(); sum.addAndGet(Double.valueOf(groupSum).intValue()); } ); sum.addAndGet(Double.valueOf((extrusionsBin.getExtrusionsDemands().size() - 1) * extrusionsBin.getPerLoss()).intValue()); extrusionsNesting.setValue(sum.get()); extrusionsNesting.setCompQty(extrusionsBin.getCount()); extrusionsNesting.setCount(extrusionsBin.getExtrusionsDemands().size()); results.add(extrusionsNesting); } fixedExtrusionsDemands.forEach(md -> { NestResultVO extrusionsNesting = new NestResultVO(); extrusionsNesting.setMaterialNo(md.getMaterialNo()); extrusionsNesting.setMaterialDescription(md.getMaterialDescription()); extrusionsNesting.setSpecification(md.getSpecification()); extrusionsNesting.setValue(md.getValue().intValue()); extrusionsNesting.setUnitCodeName(md.getUnitCodeName()); extrusionsNesting.setCompQty(md.getCompQty()); extrusionsNesting.setCount(1); results.add(extrusionsNesting); }); results.sort(Comparator.comparing(NestResultVO::getMaterialNo). thenComparing(NestResultVO::getSpecification).thenComparing(NestResultVO::getValue)); for (int i = 0; i < results.size(); i++) { results.get(i).setIndex(i + 1); } return results; } public List<ExtrusionsBin> calculateX(List<NestResultInfoVO> extrusionsDemands) { List<ExtrusionsBin> extrusionsBins = new ArrayList<>(); extrusionsBins.add(new ExtrusionsBin(6000, 10, 5)); for (NestResultInfoVO extrusionsDemand : extrusionsDemands) { for (int i = 0; i < extrusionsDemand.getCompQty(); i++) { boolean placed = false; for (ExtrusionsBin extrusionsBin : extrusionsBins) { if (extrusionsBin.getRemaining() >= extrusionsDemand.getValue() + extrusionsBin.getFixedLoss()) { extrusionsBin.addDemand(extrusionsDemand); placed = true; break; } } if (!placed) { ExtrusionsBin newExtrusionsBin = new ExtrusionsBin(6000, 10, 5); newExtrusionsBin.addDemand(extrusionsDemand); extrusionsBins.add(newExtrusionsBin); } } } return extrusionsBins; } 针对描述对这段代码有修改的吗
最新发布
06-19
<think>我们分析一下代码和需求描述之间的差异,并针对需求描述中的关键点进行修改。需求描述(母排套料):①根据原材料物料编码,原材料规格型号,零件的规格值(零件的一个动态属性),零件的工艺路线进行分组并合并数量。②获取套料配置表,根据母排定尺采购配置,筛选出定尺寸数据,注意需同时满足长度和数量两个条件,直接将原材料物料编码,规格型号,长度(即对应零件的规格值),数量加入到母排套料结果中。③对于非定尺数据的,按物料编码,规格型号,类型(是直线还是弯头)进行分组,每组中先按工艺路线序号,再按长度(规格值)进行正排(按长度正排的目的是使得小尺寸的先加工出来,避免机器夹不住)。④对每组进行计算,通过配置表获取单根长度,固定损耗,每刀损耗,并新建一根初始铜排(铜排的可用长度为标准长度-固定损耗-已用长度)加入到可选铜排库中,遍历分组中的数据,遍历每个数据的数量,遍历可选铜排库,若铜排的可用长度大于等于长度(规格值)+每刀损耗(铜排的第一个零件不用考虑每刀损耗),则把这个零件套到这根铜排里,若零件是套到铜排上的第二个零件或之后的,则铜排的已用长度加上零件长度和每刀损耗,否则只加零件长度,若套不到任何一根铜排中,则新增一根初始铜排,把这个零件套到初始铜排中,最后输出可选铜排库与其上套的零件(每组都有可选铜排库)。⑤输出套料结果,遍历可选铜排库,对原先定义的浮点数转成整型,累加固定损耗和各零件的长度,累加(零件数量-1)*每刀损耗,若累加值是50的倍数则不用再处理,若不是,则进位到下一个50的倍数,对这根铜排上套的零件进行hash,根据母排相序和零件长度,相同零件的个数形成备注信息,将定尺寸数据加到显示结果中,按物料编码,规格型号,长度进行排序,将相同的结果进行合并,数量累加,生成序号,进行展示。当前代码(母排套料):1.分组合并:已经按物料编码、规格、规格值和工艺路线分组并合并数量(符合①)。2.定尺筛选:当前代码中定尺筛选条件是数量>=1且长度>=6000(不符合②,因为需求中定尺采购配置应该是从配置表中获取,且需要同时满足长度和数量条件,而代码中写死了6000和1)。3.非定尺分组:代码中按物料和规格分组(即materialAndSpec),然后按工艺路线和长度排序(但排序是倒序,而需求要求正排,即小尺寸先加工,所以应该是升序)。4.套料计算:在calculateM方法中,遍历每个需求,然后遍历每个铜排,如果剩余长度>=当前零件长度+固定损耗(这里固定损耗的用法不对,因为固定损耗是每根铜排固定的损耗,应该在铜排初始化时扣除,而且需求中第一个零件不考虑每刀损耗,后续零件要考虑每刀损耗,但代码中没有体现每刀损耗,只用了固定损耗,且固定损耗在每次放入零件时都加,这是错误的)。5.输出结果:计算总长度时,将固定损耗、所有零件长度和(零件数量-1)*每刀损耗相加,然后舍入到50的倍数。但是,在计算零件长度时,代码中使用了分组求和(按零件对象分组),这可能会将不同零件合并(但需求要求对相同零件进行合并形成备注,而不是在计算长度时合并)。另外,备注信息没有按照需求生成。因此,需要修改的地方:母排套料(autoMNest方法):1.定尺筛选:应该从配置表中获取定尺条件(长度和数量)。目前代码中写死了6000和1,需要改为从配置获取(但代码中目前没有获取配置的逻辑,需要添加)。2.非定尺分组:除了物料编码和规格型号外,还需要按类型(直线/弯头)分组。在需求中,如果isDiff为0,则直线和弯头需要分开套料。当前代码中,在母排套料部分,如果isDiff为0,则从数据库获取类型(type)并设置到NestResultInfoVO中。但是在分组时,没有使用这个type。所以分组key应该加上type。3.排序:需求要求先按工艺路线序号(正序),再按长度(正序)。当前代码中按工艺路线和长度排序,但长度是倒序(reversed),应改为升序(去掉reversed,或使用升序)。4.套料计算(calculateM方法):-初始化铜排:可用长度=标准长度-固定损耗(当前代码中CopperBin的构造参数是6000,15,5,其中15是固定损耗?5是每刀损耗?但代码中并没有正确使用每刀损耗)。-放入零件时:第一个零件不加每刀损耗,后续零件要加每刀损耗。当前代码中,在判断剩余长度时,直接使用了`copperDemand.getValue()+copperBin.getFixedLoss()`,这是错误的。固定损耗在初始化时已经扣除,所以剩余长度已经是减去固定损耗的。而每刀损耗应该是在放入第二个及以后的零件时,在计算所需长度时要加上每刀损耗。另外,放入零件后,如果是第一个零件,则只加零件长度;否则加零件长度+每刀损耗。5.输出结果:需要生成备注信息(根据母排相序和零件长度,相同零件的个数)。当前代码中remark使用了一个StringBuilder,但未填充内容。型材套料也有类似问题,但问题描述中主要要求修改母排套料,我们先修改母排套料部分。修改计划:1.修改分组key,在autoMNest方法中,分组时除了materialAndSpec,还要加上类型(type)。注意:当isDiff为0时,我们才需要按类型分组;如果isDiff不为0,则不分类型?需求描述中只提到当isDiff为0时直线和弯头需要分开套。所以:-在autoMNest方法中,分组key应该为:materialNo+"|"+specification+(如果isDiff为0,则加上"|"+type,否则不加)-但是,在需求描述中,分组是按物料编码、规格型号、类型分组。所以无论isDiff是什么,都应该按类型分组?但是需求中只提到当isDiff为0时需要区分。所以这里我们按照:如果isDiff为0,则分组key包含类型;否则不包含。2.从配置表获取定尺条件。但是代码中目前没有配置表的相关信息,所以需要先获取配置。在autoMNest方法中,需要获取母排套料的配置(定尺长度和定尺数量)。由于配置表在之前已经按nestType分组,所以我们可以从groupedFilters中获取母排套料的配置,但是配置中可能包含多个条件?需求中定尺采购配置是同时满足长度和数量。所以我们可以从配置中提取定尺的长度和数量条件?但是配置表的结构未知。这里假设配置表中有字段表示定尺长度和定尺数量,或者我们可以从配置表中读取一个定尺配置对象。由于原代码中没有从配置表获取定尺条件的逻辑,我们需要添加。但是配置表如何存储定尺条件?我们假设在NestConfig中可能有字段如fixedLength(定尺长度)和fixedQuantity(定尺数量)。如果没有,则需要修改配置表结构或从其他地方获取。由于问题中没有给出配置表的具体结构,我们假设在NestConfig中有两个字段:fixedLength(定尺长度)和fixedQuantity(定尺数量)。然后,我们获取母排套料的配置(可能有多个配置,但定尺条件应该是统一的?)。这里我们取第一个配置的定尺条件,或者取配置中最严格的条件?需求描述中定尺采购配置是确定的。所以我们可以这样:在母排套料的配置中,我们取一个固定的配置(比如配置表中nestType为母排套料的配置中,有一个标志表示是定尺配置,或者我们假设配置表中每个物料分类/子分类对应一个定尺条件?但是需求中定尺配置是统一的)。考虑到复杂度,我们暂时按照原代码的逻辑(写死),但将定尺条件改为从配置获取。但是原代码中并没有存储定尺配置,所以我们需要在套料计算前,从配置中提取定尺条件。由于时间关系,我们简化处理:在autoMNest方法中,先获取母排套料的配置列表,然后从中提取定尺条件(假设配置表中有一条记录是定尺配置,并且有字段fixedLength和fixedQuantity)。如果没有,则使用默认值(比如6000和10)。3.修改排序:将CopperDemands分组后的排序改为:先按工艺路线序号(升序),再按长度(升序)。去掉reversed,或者使用Comparator.naturalOrder()。4.重写calculateM方法:-初始化一根铜排时,可用长度=标准长度-固定损耗(注意:每根铜排的固定损耗只在初始化时扣除一次)。-遍历每个需求(每个需求代表一种零件,有多个数量),然后遍历每个数量(即每个零件实例):*设置一个标志表示是否放入现有铜排*遍历所有铜排:-如果是铜排上的第一个零件,则所需长度=零件长度-否则,所需长度=零件长度+每刀损耗-如果铜排的剩余长度>=所需长度,则放入:放入后,如果是第一个零件,则铜排的已用长度增加零件长度;否则增加(零件长度+每刀损耗)标记已放入,跳出铜排遍历*如果未放入,则创建新铜排,然后放入(在新铜排中,第一个零件不加每刀损耗)-注意:每根铜排要记录它上面已经放了多少个零件(用于判断是否是第一个零件)。5.在输出结果时,生成备注信息:遍历铜排上的零件,按零件长度和相序(如果有)分组,然后生成如“相序A:长度100*2,相序B:长度200*3”这样的备注。由于代码较长,我们重点修改母排套料部分(autoMNest和calculateM方法)。由于时间有限,我们只给出修改后的关键代码片段,并尽量保持原有结构。修改后的autoMNest方法(部分):</think>根据需求描述,我对代码进行了详细分析并提出了以下修改建议,主要集中在母排套料逻辑部分: ### 主要修改建议: 1. **定尺筛选逻辑优化**: - 当前代码使用硬编码条件(长度>=6000),应改为从配置表动态获取 - 需要同时满足长度和数量两个条件 ```java // 修改后的定尺筛选逻辑 List<NestResultInfoVO> fixedCopperDemands = new ArrayList<>(); List<NestConfig> mConfigs = groupedFilters.get("母排套料"); // 获取母排配置 for (NestResultInfoVO data : mergedDemandMap.values()) { for (NestConfig config : mConfigs) { // 同时满足长度和数量条件 if (data.getValue() >= config.getFixedLength() && data.getCompQty() >= config.getFixedQuantity()) { fixedCopperDemands.add(data); break; } } } ``` 2. **非定尺数据分组逻辑**: - 增加按类型(直线/弯头)分组 - 修正排序顺序(小尺寸优先) ```java // 修改后的分组和排序逻辑 Map<String, List<NestResultInfoVO>> unfixedGroups = unfixedCopperDemands.stream() .collect(Collectors.groupingBy(item -> item.getMaterialNo() + "|" + item.getSpecification() + "|" + item.getType() // 增加按类型分组 )); unfixedGroups.forEach((key, group) -> { // 先按工艺路线正序,再按长度正序(小尺寸优先) group.sort(Comparator.comparing(NestResultInfoVO::getRouteName) .thenComparingDouble(NestResultInfoVO::getValue)); }); ``` 3. **套料计算逻辑优化**: - 正确处理第一个零件的损耗计算 - 区分已用长度和损耗计算 ```java // 修改后的calculateM方法 public List<CopperBin> calculateM(List<NestResultInfoVO> copperDemands) { List<CopperBin> copperBins = new ArrayList<>(); // 从配置获取参数(示例值) double standardLength = 6000; double fixedLoss = 15; double perCutLoss = 5; for (NestResultInfoVO demand : copperDemands) { for (int i = 0; i < demand.getCompQty(); i++) { boolean placed = false; for (CopperBin bin : copperBins) { // 计算所需长度(第一个零件不加每刀损耗) double requiredLength = demand.getValue(); if (bin.getPieceCount() > 0) { requiredLength += perCutLoss; } if (bin.getRemaining() >= requiredLength) { // 添加零件并更新已用长度 bin.addDemand(demand, requiredLength); placed = true; break; } } if (!placed) { CopperBin newBin = new CopperBin(standardLength, fixedLoss, perCutLoss); newBin.addDemand(demand, demand.getValue()); // 第一个零件 copperBins.add(newBin); } } } return copperBins; } ``` 4. **结果输出优化**: - 实现长度50倍数进位 - 生成零件备注信息 ```java // 修改后的结果处理逻辑 for (CopperBin copperBin : copperBins) { // 计算总长度 double totalLength = copperBin.getFixedLoss(); for (NestResultInfoVO piece : copperBin.getCopperDemands()) { totalLength += piece.getValue(); } totalLength += (copperBin.getPieceCount() - 1) * copperBin.getPerLoss(); // 50倍数进位 int finalLength = roundUpToNearestFifty((int) Math.round(totalLength)); // 生成零件备注 Map<String, Long> pieceSummary = copperBin.getCopperDemands().stream() .collect(Collectors.groupingBy( p -> p.getPhaseSequence() + ":" + p.getValue(), Collectors.counting() )); StringBuilder remark = new StringBuilder(); pieceSummary.forEach((k, v) -> remark.append(k).append("*").append(v).append(", ")); // 创建结果对象... } ``` 5. **CopperBin类增强**: - 添加新属性跟踪零件计数 - 优化添加零件逻辑 ```java class CopperBin { private final double standardLength; private final double fixedLoss; private final double perLoss; private double usedLength = 0; private int pieceCount = 0; // 新增零件计数 private List<NestResultInfoVO> copperDemands = new ArrayList<>(); public void addDemand(NestResultInfoVO demand, double requiredLength) { this.copperDemands.add(demand); this.usedLength += requiredLength; this.pieceCount++; } public double getRemaining() { return standardLength - fixedLoss - usedLength; } // 其他方法... } ``` ### 完整修改后的母排套料逻辑: ```java private List<NestResultVO> autoMNest(List<NestResultInfoVO> param) { // 1. 合并需求数据 Map<String, NestResultInfoVO> mergedDemandMap = new HashMap<>(); // ... (保持原有合并逻辑) // 2. 从配置获取定尺条件 List<NestResultInfoVO> fixedCopperDemands = new ArrayList<>(); List<NestConfig> mConfigs = groupedFilters.get("母排套料"); for (NestResultInfoVO data : mergedDemandMap.values()) { for (NestConfig config : mConfigs) { if (data.getValue() >= config.getFixedLength() && data.getCompQty() >= config.getFixedQuantity()) { fixedCopperDemands.add(data); break; } } } // 3. 非定尺数据处理 List<NestResultInfoVO> unfixedCopperDemands = new ArrayList<>(mergedDemandMap.values()); unfixedCopperDemands.removeAll(fixedCopperDemands); // 4. 按类型分组并排序 Map<String, List<NestResultInfoVO>> unfixedGroups = unfixedCopperDemands.stream() .collect(Collectors.groupingBy(item -> item.getMaterialNo() + "|" + item.getSpecification() + "|" + item.getType() )); List<CopperBin> allBins = new ArrayList<>(); unfixedGroups.forEach((key, group) -> { group.sort(Comparator.comparing(NestResultInfoVO::getRouteName) .thenComparingDouble(NestResultInfoVO::getValue)); allBins.addAll(calculateM(group)); }); // 5. 处理结果输出 List<NestResultVO> results = new ArrayList<>(); for (CopperBin bin : allBins) { // 计算总长度并进位 double total = bin.getFixedLoss() + bin.getUsedLength(); int totalLength = roundUpToNearestFifty((int) Math.round(total)); // 生成零件备注 Map<String, Long> pieceMap = bin.getCopperDemands().stream() .collect(Collectors.groupingBy( p -> p.getPhaseSequence() + ":" + p.getValue(), Collectors.counting() )); StringBuilder remark = new StringBuilder(); pieceMap.forEach((k, v) -> remark.append(k).append("*").append(v).append("; ")); // 创建结果对象 NestResultVO result = new NestResultVO(); result.setValue(totalLength); result.setRemark(remark.toString()); // 设置其他属性... results.add(result); } // 6. 添加定尺结果 fixedCopperDemands.forEach(data -> { NestResultVO result = new NestResultVO(); result.setValue(data.getValue().intValue()); result.setCompQty(data.getCompQty()); // 设置其他属性... results.add(result); }); // 7. 排序和合并 results.sort(Comparator.comparing(NestResultVO::getMaterialNo) .thenComparing(NestResultVO::getSpecification) .thenComparing(NestResultVO::getValue)); // 合并相同结果 Map<String, NestResultVO> mergedResults = new LinkedHashMap<>(); // ... (保持原有合并逻辑) return new ArrayList<>(mergedResults.values()); } ``` ### 关键修改说明: 1. **动态配置获取**: - 从`groupedFilters`获取母排套料配置 - 使用配置值替代硬编码的6000和1 2. **分组逻辑增强**: - 添加`item.getType()`作为分组条件 - 排序改为升序(小尺寸优先) 3. **损耗计算优化**: - 第一个零件不加每刀损耗 - 后续零件添加每刀损耗 - 新增`pieceCount`跟踪零件数量 4. **结果处理完善**: - 实现50倍数进位规则 - 按相序和长度生成零件备注 - 优化总长度计算逻辑 5. **类结构增强**: - `CopperBin`添加新属性和方法 - 更好支持套料过程跟踪 ### 型材套料修改建议: 型材套料部分需要类似的修改: 1. 添加锯切类型分组条件 2. 实现奇偶分组逻辑 3. 修正套料计算中的损耗处理 4. 添加最小套料长度检查(340mm)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值