【BUG】循环中重复使用对象一定要注意

简介: 【BUG】循环中重复使用对象一定要注意


报错内容

报错信息显示ID重复。

原因分析

在最终添加的方法中,出现了重复ID的报错。对于为什么ID会重复,我思考了很久也没有想通。我沿着代码往上找到了saveList

int batchSize = 5000;
if (CollUtil.isNotEmpty(saveList)) {
    List<List<Map<String, Object>>> batchList = ListUtil.partition(saveList, batchSize);
    for (List<Map<String, Object>> batch : batchList) {
        if (CollUtil.isNotEmpty(batch)) {
            firstRecordMapper.insertJghzLdryList(batch.stream().filter(v -> v != null && ObjectUtil.isNotEmpty(v.get("ID"))).collect(Collectors.toList()));
        }
    }
}

代码大致如上所示。

for (Map<String, Object> item : list) {
    ...
    Map<String, Object> oneCellMap = new HashMap<String, Object>();
    // 遍历这一类型的10个二级指标,每个指标存成一行数据
    for (int i = 0; i < secIndexNameList.size(); i++) {
        ...
        oneCellMap.clear();
        oneCellMap.put("ID", IdUtilV2.getInstance().getId());
        ...
        saveList.add(oneCellMap);
        px++;
    }
    // 保存这一行数据的 综合得分
    oneCellMap.clear();
    oneCellMap.put("ID", IdUtilV2.getInstance().getId());
    ...
    saveList.add(oneCellMap);
}

我也不是很确定,但我怀疑问题出在这里,于是我做了以下修改:

for (Map<String, Object> item : list) {
    ...
    // 遍历这一类型的10个二级指标,每个指标存成一行数据
    for (int i = 0; i < secIndexNameList.size(); i++) {
        ...
        Map<String, Object> oneCellMap = new HashMap<String, Object>();
        oneCellMap.put("ID", IdUtilV2.getInstance().getId());
        ...
        saveList.add(oneCellMap);
        px++;
    }
    // 保存这一行数据的 综合得分
    Map<String, Object> oneCellMap = new HashMap<String, Object>();
    oneCellMap.put("ID", IdUtilV2.getInstance().getId());
    ...
    saveList.add(oneCellMap);
}

然后问题就解决了。我感到很奇怪,后来才反应过来...原来是使用了同一个对象。

解决方案

问题的根本原因是在循环中重复使用了同一个oneCellMap对象,导致了ID重复的问题。在第一个版本的代码中,每次循环都会清空oneCellMap对象并重新添加ID,但是由于saveList中保存的是引用,所以最终saveList中的所有oneCellMap对象的ID都是相同的。

在修改后的代码中,每次循环都创建了一个新的oneCellMap对象,确保了每个oneCellMap对象的ID都是唯一的,解决了ID重复的问题。



相关文章
|
7月前
|
Web App开发 存储
用9种办法解决 for 循环取 i
用9种办法解决 for 循环取 i
41 0
|
9月前
|
安全 搜索推荐
如何避免写重复代码?两种常见的方法:抽象和组合
如何避免写重复代码?两种常见的方法:抽象和组合
154 0
|
9月前
|
Python
#PY小贴士# for 循环定义的变量,循环外可以用吗?
我们知道,在 python 中要获取一个变量的值,必须是先给它赋值过,不然就是未定义。那么这个 i,代码中没有显式的赋值,在循环体之外还可以用吗?
|
11月前
生成器运行时机导致的难以察觉的 bug
生成器运行时机导致的难以察觉的 bug
44 0
|
12月前
|
设计模式 消息中间件 JavaScript
干掉 “重复代码”,这三种方式绝了!
干掉 “重复代码”,这三种方式绝了!
36911 2
干掉 “重复代码”,这三种方式绝了!
线程 - 这段危险代码90%的人都写过!
线程 - 这段危险代码90%的人都写过!
81 0
线程 - 这段危险代码90%的人都写过!
|
缓存 Java 数据库
如何避免无意间创建多余对象
6 避免创建不必要的对象 从字面意思上来看,大家肯定都知道创建不必要的对象是错误的做法。但这一节其实主要是提醒我们避免无意识的创建不必要对象的代码写法。
如何避免无意间创建多余对象
|
自然语言处理
在以阶段划分的编译过程中,判断程序语句的形式是否正确属于()阶段的工作。
在以阶段划分的编译过程中,判断程序语句的形式是否正确属于()阶段的工作。
127 0
|
程序员 索引
for 循环的 5 种写法,哪种最快?
几种遍历方法中for执行最快,它没有任何额外的函数调用栈和上下文。但在实际开发中我们要结合语义话、可读性和程序性能,去选择究竟使用哪种方案。下面来看for , foreach , map , for...in , for...of五种方法现场battle。
|
自然语言处理 JavaScript Java
从重复到重用
开发技术的发展,从第一次提出“函数/子程序”,实现代码级重用;到面向对象的“类”,重用数据结构与算法;再到“动态链接库”、“控件”等重用模块;到如今流行的云计算、微服务可重用整个系统。技术发展虽然日新月异,但本质都是重用,只是粒度不同。所以写代码的动机都应是把重复的工作变成可重用的方案,其中重复的工作包括业务上重复的场景、技术上重复的代码等。合格的系统可以简化当下重复的工作;优秀的系统还能预见未来重复的工作。
从重复到重用