最蠢的代码

最蠢的代码

/**
 * 插入商品规格信息
 */
private void insertSpeInfo(GoodsDetailVo model, Goods commonFields) {
    Long goodId = commonFields.getId();
    //为商品规格基本信息添加所属商品ID,填充公共字段
    List<GoodsSpecificationVo> goodsSpecificationVos = model.getGoodsSpecificationVos()
            .stream().peek(goodsSpecificationVo -> {
                goodsSpecificationVo.setGoodsId(goodId);
                fillCommonFields(commonFields, goodsSpecificationVo);
            }).collect(Collectors.toList());
    //spcID集合
    List<Long> spcIds = new ArrayList<>();
    //规格值对象集合
    List<GoodsSpecValues> goodsSpecValues = new ArrayList<>();
    //取出规格名与对应的规格值集合
    for (GoodsSpecificationVo goodsSpecificationVo : goodsSpecificationVos) {
        //保存规格名
        GoodsSpecification goodsSpecification = BeanUtil.copyProperties(goodsSpecificationVo, GoodsSpecification.class);
        goodsSpecificationService.save(goodsSpecification);
        //获取规格名ID
        Long spcID = goodsSpecification.getId();
        spcIds.add(spcID);
        List<String> specValue = goodsSpecificationVo.getSpecValue();
        //保存规格值
        for (String sv : specValue) {
            GoodsSpecValues values = new GoodsSpecValues(spcID, sv);
            fillCommonFields(commonFields, values);
            goodsSpecValues.add(values);
        }
        goodsSpecValuesService.saveBatch(goodsSpecValues);
        goodsSpecValues.clear();
    }
    String strIds = listToString(spcIds);
    //拿到规格值和对应ID
    Map<String, Long> spcValIds = goodsSpecValuesService
            .list(Wrappers.<GoodsSpecValues>lambdaQuery().in(GoodsSpecValues::getSpecId, spcIds))
            .stream().collect(Collectors.toMap(GoodsSpecValues::getSpecValue, GoodsSpecValues::getId));
    //获取商品sku集合
    List<GoodsSku> goodsSkus = model.getGoodsSkuVos().stream()
            .map(goodsSkuVo -> {
                GoodsSku goodsSku = BeanUtil.copyProperties(goodsSkuVo, GoodsSku.class);
                fillCommonFields(commonFields, goodsSku);
                goodsSku.setGoodsId(goodId);
                //设置规格名组合ID集合
                goodsSku.setGoodsSpec(strIds);
                //设置规格值组合ID集合
                List<Long> spcValCombinationIds = goodsSkuVo.getGoodsSpecValues().stream()
                        .map(spcValIds::get)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                goodsSku.setGoodsSpecValue(listToString(spcValCombinationIds));
                return goodsSku;
            })
            .collect(Collectors.toList());
    // 写入商品总库存信息
    model.getGood().setQuantity(goodsSkus.stream().mapToInt(GoodsSku::getQuantity).sum());
    updateById(model.getGood());
    //保存sku
    goodsSkuService.saveBatch(goodsSkus);
}

先大概解析一下这段代码的作用

它接受一个GoodsDetailVo对象和一个Goods对象作为参数,然后从GoodsDetailVo中提取商品规格信息并保存到数据库中。

具体而言,该代码执行以下主要步骤:

  1. GoodsDetailVo对象中获取商品规格信息,包括规格名、规格值、SKU(库存单位)等。
  2. 为商品规格基本信息添加所属商品ID和填充公共字段(例如创建时间、更新时间等)。
  3. 保存规格名到数据库,并获取规格名的ID。
  4. 保存规格值到数据库,并使用规格名的ID关联规格值。
  5. 将规格值和对应的ID存储在spcValIds映射中,用于后续的关联。
  6. 处理商品SKU信息,设置商品ID、规格名组合ID集合、规格值组合ID集合等。
  7. 计算并更新商品总库存信息。
  8. 保存商品SKU信息到数据库。

存在的主要问题

  • 在循环中使用了数据库操作:在循环内部进行数据库的保存操作,会导致频繁的数据库访问,影响性能。

    for (GoodsSpecificationVo goodsSpecificationVo : goodsSpecificationVos) {
        //保存规格名
        GoodsSpecification goodsSpecification = BeanUtil.copyProperties(goodsSpecificationVo, GoodsSpecification.class);
        goodsSpecificationService.save(goodsSpecification);
        //获取规格名ID
        Long spcID = goodsSpecification.getId();
        spcIds.add(spcID);
        List<String> specValue = goodsSpecificationVo.getSpecValue();
        //保存规格值
        for (String sv : specValue) {
            GoodsSpecValues values = new GoodsSpecValues(spcID, sv);
            fillCommonFields(commonFields, values);
            goodsSpecValues.add(values);
        }
        goodsSpecValuesService.saveBatch(goodsSpecValues);
        goodsSpecValues.clear();
    }
    
    • 在这里,循环调用 goodsSpecificationService.save(goodsSpecification);依次逐个保存规格名,之后再将获取到规格名ID逐个插入到规格值中,即这段代码GoodsSpecValues values = new GoodsSpecValues(spcID, sv);
    • 之后又犯了同样的错误,又一次在循环中来了数据库IO操作goodsSpecValuesService.saveBatch(goodsSpecValues);
  • 重复清空集合:在保存规格值的部分,使用了一个清空集合的操作goodsSpecValues.clear(),但该操作在每次循环中执行,并不需要如此频繁地清空集合。可以将清空集合的操作移到循环外部,在循环结束后进行一次清空即可。

goodsSpecValuesService.saveBatch(goodsSpecValues);
goodsSpecValues.clear();
  • 方法调用顺序问题:在更新商品总库存信息的部分,调用了updateById(model.getGood())来更新商品信息,但是该方法的调用在保存SKU之前,可能导致库存信息不准确。
// 写入商品总库存信息
model.getGood().setQuantity(goodsSkus.stream().mapToInt(GoodsSku::getQuantity).sum());
updateById(model.getGood());
//保存sku
goodsSkuService.saveBatch(goodsSkus);
  • 没必要的数据库查询:

    //拿到规格值和对应ID
        Map<String, Long> spcValIds = goodsSpecValuesService
                .list(Wrappers.<GoodsSpecValues>lambdaQuery().in(GoodsSpecValues::getSpecId, spcIds))
                .stream().collect(Collectors.toMap(GoodsSpecValues::getSpecValue, GoodsSpecValues::getId));
    
     //设置规格值组合ID集合
    List<Long> spcValCombinationIds = goodsSkuVo.getGoodsSpecValues().stream()
            .map(spcValIds::get)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    goodsSku.setGoodsSpecValue(listToString(spcValCombinationIds));
    
    public String listToString(List<Long> ids) {
        return ids.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
    }
    
    • 其实这次数据库查询是完全不必要的,应该直接从已经保存过后的goodsSpecValues局部变量中去筛选数据即可,不过此时的goodsSpecValues也不是完全的,原因就在于第一个问题中我采用在循环中保存规格值
    • 应该在构造这个spcValIds集合的时候就直接将value值转为String类型
  • 代码可读性:方法代码逻辑过多,应该对不同表不同数据的插入做拆分,抽离逻辑,抽离成单独的小方法,之后再拼接在一起增强可读性

优化后的代码

这是优化过后的最终版本,中间还有两次优化就不作展示了

private void insertSpeInfo(GoodsDetailVo model, Goods commonFields) {
    Long goodId = commonFields.getId();

    //为商品规格基本信息添加所属商品ID,填充公共字段,获取Vo对象
    List<GoodsSpecificationVo> goodsSpecificationVos = model.getGoodsSpecificationVos()
            .stream().peek(goodsSpecificationVo -> {
                goodsSpecificationVo.setGoodsId(goodId);
                fillCommonFields(commonFields, goodsSpecificationVo);
            }).collect(Collectors.toList());

    //保存规格名
    List<GoodsSpecification> goodsSpecifications = insertGoodsSpecification(goodsSpecificationVos);

    //规格名ID集合
    List<Long> spcIds = goodsSpecifications.stream().map(GoodsSpecification::getId).collect(Collectors.toList());

    //保存规格值
    List<GoodsSpecValues> goodsSpecValues = insertGoodsSpecValue(commonFields, goodsSpecificationVos, spcIds);

    // 保存sku
    List<GoodsSkuVo> goodsSkuVos = model.getGoodsSkuVos()
            .stream().peek(goodsSkuVo -> {
                fillCommonFields(commonFields, goodsSkuVo);
                goodsSkuVo.setGoodsId(goodId);
            })
            .collect(Collectors.toList());
    String strIds = listToString(spcIds);
    List<GoodsSku> goodsSkus = insertGoodsSku(strIds, goodsSpecValues, goodsSkuVos);

    // 写入商品总库存信息
    insertTotalQuantity(model, goodsSkus);
}

//保存商品的库存信息
private void insertTotalQuantity(GoodsDetailVo model, List<GoodsSku> goodsSkus) {
    //计算总库存
    int totalQuantity = goodsSkus.stream().mapToInt(GoodsSku::getQuantity).sum();
    Goods good = model.getGood();
    good.setQuantity(totalQuantity);
    //更新商品信息
    update(good);
}

//保存商品的sku信息
private List<GoodsSku> insertGoodsSku(String speIds, List<GoodsSpecValues> goodsSpecValues,
                                      List<GoodsSkuVo> goodsSkuVos) {
    // 拿到规格值和对应ID
    Map<String, String> spcValIds = goodsSpecValues.stream()
            .collect(Collectors.toMap(GoodsSpecValues::getSpecValue,
                    goodsSpecValue -> String.valueOf(goodsSpecValue.getId())));

    List<GoodsSku> goodsSkus = goodsSkuVos.stream()
            .map(goodsSkuVo -> {
                GoodsSku goodsSku = BeanUtil.copyProperties(goodsSkuVo, GoodsSku.class);
                // 设置规格名组合ID集合
                goodsSku.setGoodsSpec(speIds);
                // 设置规格值组合ID集合
                goodsSku.setGoodsSpecValue(
                        goodsSkuVo.getGoodsSpecValues().stream()
                                .map(spcValIds::get)
                                .collect(Collectors.joining(","))
                );
                return goodsSku;
            })
            .collect(Collectors.toList());
    //保存sku
    goodsSkuService.saveBatch(goodsSkus);
    return goodsSkus;
}

//保存商品的规格值信息
private List<GoodsSpecValues> insertGoodsSpecValue
        (Goods commonFields, List<GoodsSpecificationVo> goodsSpecificationVos, List<Long> spcIds) {
    //规格值列表
    List<GoodsSpecValues> goodsSpecValues = new ArrayList<>();
    int i = 0;
    for (GoodsSpecificationVo goodsSpecificationVo : goodsSpecificationVos) {
        Long spcID = spcIds.get(i++);
        List<String> specValue = goodsSpecificationVo.getSpecValue();
        List<GoodsSpecValues> specValuesList = specValue.stream().map(sv -> {
            GoodsSpecValues values = new GoodsSpecValues(spcID, sv);
            fillCommonFields(commonFields, values);
            return values;
        }).collect(Collectors.toList());
        goodsSpecValues.addAll(specValuesList);
    }

    goodsSpecValuesService.saveBatch(goodsSpecValues);
    return goodsSpecValues;
}

//保存商品的规格名信息
private List<GoodsSpecification> insertGoodsSpecification
                                                  (List<GoodsSpecificationVo> goodsSpecificationVos) {
List<GoodsSpecification> goodsSpecifications = BeanUtil.copyToList(goodsSpecificationVos,                                                                                             GoodsSpecification.class);
    goodsSpecificationService.saveBatch(goodsSpecifications);
    return goodsSpecifications;
}

以下是对代码进行优化的几个点

  • 增强可读性:对方法的整体做了拆分,对于不同的数据的插入拆分成了不同的独立小方法,增强了可读性

  • 减少数据库访问次数:将数据库操作尽量集中在一起,减少频繁的数据库访问。

//保存商品的规格值信息
private List<GoodsSpecValues> insertGoodsSpecValue
        (Goods commonFields, List<GoodsSpecificationVo> goodsSpecificationVos, List<Long> spcIds) {
    //规格值列表
    List<GoodsSpecValues> goodsSpecValues = new ArrayList<>();  //定义一个局部变量用来存储规格值
    int i = 0;
    for (GoodsSpecificationVo goodsSpecificationVo : goodsSpecificationVos) {
        Long spcID = spcIds.get(i++);
        List<String> specValue = goodsSpecificationVo.getSpecValue();
        List<GoodsSpecValues> specValuesList = specValue.stream().map(sv -> {
            GoodsSpecValues values = new GoodsSpecValues(spcID, sv);
            fillCommonFields(commonFields, values);
            return values;
        }).collect(Collectors.toList());
        goodsSpecValues.addAll(specValuesList);
    }

    goodsSpecValuesService.saveBatch(goodsSpecValues);//批量一次性保存规格值
    return goodsSpecValues;
}

//保存商品的规格名信息
private List<GoodsSpecification> insertGoodsSpecification
                                                  (List<GoodsSpecificationVo> goodsSpecificationVos) {
List<GoodsSpecification> goodsSpecifications = 
    BeanUtil.copyToList(goodsSpecificationVos,GoodsSpecification.class);                                   
    goodsSpecificationService.saveBatch(goodsSpecifications);     //批量一次性保存规格名信息     
    return goodsSpecifications;                       
}
  • 优化规格值和对应ID的获取方式:使用已批量保存的规格之集合获取规格值和对应ID的映射关系。
private List<GoodsSku> insertGoodsSku(String speIds, List<GoodsSpecValues> goodsSpecValues,
                                      List<GoodsSkuVo> goodsSkuVos) {
    // 拿到规格值和对应ID
    Map<String, String> spcValIds = goodsSpecValues.stream()   //减少了不必要的数据库查询
            .collect(Collectors.toMap(GoodsSpecValues::getSpecValue,
                goodsSpecValue -> String.valueOf(goodsSpecValue.getId()))); //直接将value值转为string类型

    List<GoodsSku> goodsSkus = goodsSkuVos.stream()
            .map(goodsSkuVo -> {
                GoodsSku goodsSku = BeanUtil.copyProperties(goodsSkuVo, GoodsSku.class);
                // 设置规格名组合ID集合
                goodsSku.setGoodsSpec(speIds);
                // 设置规格值组合ID集合
                goodsSku.setGoodsSpecValue(
                        goodsSkuVo.getGoodsSpecValues().stream()
                                .map(spcValIds::get)
                                .collect(Collectors.joining(",")) //减少了方法的调用
                );
                return goodsSku;
            })
            .collect(Collectors.toList());
    //保存sku
    goodsSkuService.saveBatch(goodsSkus);
    return goodsSkus;
}
  • 更新商品总库存信息:调整更新商品信息的位置,确保在保存SKU之后更新商品总库存信息。
// 保存sku
insertGoodsSku(strIds, goodsSpecValues, goodsSkuVos);
// 写入商品总库存信息
insertTotalQuantity(model, commonFields);
<think>好的,我现在需要帮用户优化他们的车牌识别Python代码。首先,我得看看用户提供的引用内容,了解他们当前使用的技术和方法。引用里提到他们用了YOLO V5进行车型识别,还有车牌识别系统支持多种车牌类型,代码结构看起来是基于YOLO的检测模型。另外,引用3提到基于TensorFlow的车牌识别,使用CNN进行端到端识别,可能用户现在用的是类似的方法,或者结合了YOLO和CNN? 用户的问题是如何优化或改进现有的车牌识别代码。我需要从几个方面考虑可能的优化点:模型性能、代码结构、数据处理、后处理等。 首先,模型优化。YOLO V5虽然快,但可能可以替换成更轻量级的版本,比如YOLOv5n或者YOLOv5s,或者用其他轻量模型如EfficientNet或MobileNet,这样在移动端或边缘设备上更高效。另外,模型蒸馏或量化也是常用的优化手段,可以减小模型大小,提升推理速度。 然后是数据增强。用户的数据集可能不够多样,增加合成数据,比如不同光照、模糊、旋转的车牌图片,能提升模型的鲁棒性。数据预处理方面,自动校正倾斜车牌,或者使用超分辨率技术恢复低分辨率图像,可能对检测有帮助。 多阶段检测优化。比如先用YOLO检测车牌区域,再用CRNN或LSTM+CTC进行字符识别,这样分工明确,可能提升准确率。或者集成多个模型,比如用YOLOv5检测车牌,再用更精准的模型进行字符分割。 后处理算法改进。比如用OpenCV的形态学操作优化车牌区域,或者用Tesseract OCR结合自定义规则来纠正识别错误。另外,采用基于规则的校验,比如车牌字符的合法组合,可以过滤掉明显错误的识别结果。 代码结构优化。将检测、预处理、识别模块解耦,方便单独优化和维护。使用多线程或异步处理,特别是在处理视频流时,可以提升实时性。还有缓存机制,比如缓存模型或常用数据,减少重复加载时间。 硬件加速。如果用户有GPU,可以启用TensorRT或OpenVINO来加速推理。没有GPU的话,量化模型到FP16或INT8也能提升速度,虽然可能会损失一点精度。 另外,错误处理和日志记录也很重要,加入详细的日志可以帮助调试和监控系统性能。异常处理机制能提升系统的稳定性,比如处理低质量输入图像时不会崩溃。 可能还需要考虑模型微调,定期用新数据重新训练模型,防止过时。或者加入在线学习机制,根据新数据动态调整模型。 用户的应用场景如果是实时监控,那么延迟和吞吐量是关键,可能需要优化模型的计算量。如果是离线处理,可能更注重准确率。 后,根据引用中的代码结构,用户可能已经用了YOLOv5,所以优化方向可能包括模型蒸馏、数据增强、多阶段处理和后处理优化。比如在检测到车牌后,使用超分辨率提升图像质量,再用CRNN进行字符识别,结合规则校验,这样整体准确率和速度都会提升。</think>以下是针对车牌识别Python代码的优化建议,从算法优化到工程实现分层次说明: $$算法优化层$$ 1. 模型轻量化改进: - 将YOLOv5替换为更轻量的$YOLOv5n-0.5$版本(参数量减少40%) - 添加模型蒸馏技术,使用预训练的大模型指导小模型训练 - 实施INT8量化,示例代码片段: ```python model = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8) ``` 2. 数据增强优化: - 添加合成数据增强模块,生成包含以下干扰的样本: $$x' = x + \alpha \cdot GaussianNoise(\sigma)$$ $$x' = MotionBlur(x, kernel\_size=(5,5))$$ - 实现自适应直方图均衡化提升低光照效果 $$工程实现层$$ 3. 多阶段处理优化: ```mermaid graph TD A[原始图像] --> B{YOLOv5检测} B -->|车牌区域| C[超分辨率重建] C --> D[CRNN字符识别] D --> E[规则校验] ``` 4. 并行计算优化: - 使用异步IO处理视频流 - 启用多GPU推理(示例代码): ```python model = torch.nn.DataParallel(model, device_ids=[0,1]) ``` $$后处理优化$$ 5. 基于OpenCV的形态学优化: ```python kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) processed = cv2.morphologyEx(plate_img, cv2.MORPH_CLOSE, kernel) ``` 6. 混合识别策略: - 当CNN置信度<0.9时,触发传统OCR+规则校验 - 建立车牌字符概率转移矩阵: $$P(c_t|c_{t-1}) = \begin{cases} 0.8 & \text{字母→字母} \\ 0.15 & \text{字母→数字} \\ 0.05 & \text{其他} \end{cases}$$ [^1]:引用[1]中提到的YOLOv5算法可通过模型压缩提升实时性 [^2]:引用[2]的项目结构建议采用模块化设计提升可维护性 [^3]:引用[3]的端到端方案可结合当前新Transformer架构改进 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值