代码优化实际案例

一、业务场景

  项目中做的一个功能,需要查询几十张表中的数据,然后在处理这些查询出的数据,处理好之后在将数据

按照一定的规则放入缓存当中。做这个操作主要是为了系统迁移的时候使用,在使用新系统的时候,有些缓存

数据可能会丢失,因此需要做这个操作。接到这个任务后,自己稍微分析了一下,然后确定思路,大致思路为:

.1.使用循环查询出所有的列表数据;.2.循环处理数据,将数据放入一个Map容器中,形式为key-value.3.循环

将数据放入缓存中,完成功能。按照这个思路,自己经过反复调试,最终写的代码如下:

@Slf4j

public class ServiceTest {

 

    public boolean updateTest() {

        Map<Integer, List<TransmitActivityTotal>> transmitActivityTotalMap = new HashMap<>(30);

        List<TransmitActivityTotal> transmitActivityTotals = null;

        StopWatch stopWatch = new StopWatch();

        stopWatch.start();

        try {

            // 查询数据

            for(int i = 0; i < 30; i++){

                // 根据不同的分表信息查询不同的数据,查询方式省略

                transmitActivityTotals = null;

                transmitActivityTotalMap.put(i, transmitActivityTotals);

            }

 

            // 处理数据

            if (transmitActivityTotalMap.isEmpty()) {

                return false;

            }

            Map<Long, Integer> idTotalMap = new HashMap<>();

            Integer total = null;

            for(Map.Entry<Integer, List<TransmitActivityTotal>> item : transmitActivityTotalMap.entrySet()) {

                for(TransmitActivityTotal transmitActivityTotal : item.getValue()) {

                    total = transmitActivityTotal.getTotal() == null ? Integer.valueOf(0) : transmitActivityTotal.getTotal();

                    if (idTotalMap.keySet().contains(transmitActivityTotal.getId())) {

                        // 再次添加 原有数据 + 新数据

                        idTotalMap.put(transmitActivityTotal.getId(), idTotalMap.get(transmitActivityTotal.getId()) + total);

                    } else {

                        // 首次添加

                        idTotalMap.put(transmitActivityTotal.getId(), total);

                    }

                }

            }

 

            for(Map.Entry<Long, Integer> item : idTotalMap.entrySet()) {

                // 使用redis进行 恢复缓存 操作

                log.info("id-->{}, 数量--->", item.getKey(), item.getValue());

            }

            stopWatch.stop();

            log.info("缓存恢复耗时--->{}毫秒", stopWatch.getLastTaskTimeMillis());

            return true;

        } catch (Exception ex) {

            stopWatch.stop();

            log.error("缓存更新异常--->{}", ex);

            return false;

        }

    }

}

 

@Data

public class TransmitActivityTotal {

    /*

     *  id

     */

    private Long id;

    /*

     *  数量

     */

    private Integer total;

}

经过测试,发现这种方式代码能够正常执行,并且符合预期的要求。可是在负责人审核我写的代码的时候,让我好好去检查代码,

看看有没有可以优化的地方。听他这么一说,让我感觉有一丝意外,这已经是最好的代码,还要怎么优化呢?现在是按照步骤

一步一步的执行,整个程序都运行正常,并且也能够实现功能。可是既然负责人都说了,自己也只好继续改进,经过自己不断地

思考,最终想到优化办法。

二、优化方案

  最开始的方案是一个步骤一个步骤的进行,可是能不能几个步骤同时进行,这样不仅代码量减少,并且代码也更加地容易理解。

说干就干,一直朝着这个方向不断地去优化上面的代码,最终优化的代码结果如下:

    public boolean updateTest() {

        List<TransmitActivityTotal> transmitActivityTotals = null;

        StopWatch stopWatch = new StopWatch();

        Map<String, Integer> idTotalMap = new HashMap<>();

        stopWatch.start();

        try {

            // 查询数据

            for(int i = 0; i < 30; i++){

                // 根据不同的分表信息查询不同的数据 数据查询省略

                transmitActivityTotals = null;

                if (transmitActivityTotals == null || transmitActivityTotals.size() < 1) {

                    continue;

                }

                for(TransmitActivityTotal transmitActivityTotal : transmitActivityTotals) {

                    Integer total = transmitActivityTotal.getTotal() == null ? Integer.valueOf(0) : transmitActivityTotal.getTotal();

                    if (idTotalMap.keySet().contains(transmitActivityTotal.getId())) {

                        // 再次添加 原有数据 + 新数据

                        idTotalMap.put(transmitActivityTotal.getId().toString(), idTotalMap.get(transmitActivityTotal.getId()) + total);

                    } else {

                        // 首次添加

                        idTotalMap.put(transmitActivityTotal.getId().toString(), total);

                    }

                }

            }

 

            // 可以一次性添加缓存数据 this.redisTemplate.opsForHash().putAll(key, mapData);

            stopWatch.stop();

            log.info("缓存恢复耗时--->{}毫秒", stopWatch.getLastTaskTimeMillis());

            return true;

        } catch (Exception ex) {

            stopWatch.stop();

            log.error("缓存更新异常--->{}", ex);

            return false;

        }

    }

修改后的代码,大大地减少了代码量,更加容易阅读与理解,看起来也更加地简洁。思路已经简化为查询出代码后,立马

处理数据,存入缓存的方式也修改为一次性存入,而不再是一条一条的存入。简化后的代码在自己看来,好太多,效率也

高很多,减少了两个循环,数据也不用在在存储在一个大的容器中,然后在从容器中取出来。到此代码优化完成!

通过这次代码优化,自己又考虑到另外一个实际的优化案例。有好几个首页的列表查询,思路是:.1.从缓存中获取数据

或者是从数据库查询数据;.2.过滤数据;.3.对数据进行排序;.4.转换数据,将数据转换为需要返回的OutVo类型的数据;

.5.处理数据,比如类型翻译,使用日期做计算操作等等。按照步骤一步一步来,也没问题,最终功能实现。有一次测试负责人

在对我写的接口进行性能测试时,发现性能不达标提出BUG,需要我这边去做优化处理。自己一步一步分析,过滤数据时循环

一次,转换数据时循环一次,数据处理时又循环一次,这些操作能否一次性完成呢?优化后的思路为:.1.从缓存中获取数据或者

是从数据库查询数据;.2.对数据进行排序;.3.过滤、转换、处理数据;按照这种思路来进行修改后,效率果然大大地提升。最终

测试人员的测试结论,效率比之前有很大的提升,完全能够满足系统对性能的要求。

总结:从这两次代码优化中,自己学到一点,有的时候写代码可以按照设计好的思路一步一步来,写好之后,可以考虑某些

步骤是否可以合并完成。如果可以,则将其合并,能够提升代码的运行效率。有其他更好建议的小伙伴,欢迎留言讨论。

posted @ 2022-09-24 15:33  一只爱阅读的程序员  阅读(221)  评论(0编辑  收藏  举报