• 代码优化技巧


    这是个人在写代码时的一个优化心得,可以让代码更清晰,更具可维护性

     if 嵌套优化

    有时候我们会看到类似这样的代码:

    1. if (a = b) {
    2. if (c = d) {
    3. if (e = f) {
    4. // 代码执行逻辑
    5. .....
    6. }
    7. }
    8. }

    这种代码嵌套越多越是难以维护,在某些情况下我们可以更改成这样:

    1. if (a != b) {
    2. return;
    3. }
    4. if (c != d) {
    5. return;
    6. }
    7. if (e != f) {
    8. return;
    9. }
    10. // 代码执行逻辑
    11. ...........

    这样的代码就非常清晰了,但是在某些情况下我们不能直接return还需要将代码继续执行下去,例如:

    1. private void funName() {
    2. // 当这里执行完毕后
    3. if (a = b) {
    4. if (c = d) {
    5. if (e = f) {
    6. // 代码执行逻辑
    7. .....
    8. }
    9. }
    10. }
    11. // 继续往下执行
    12. // 第二层代码执行逻辑
    13. .........
    14. }

    此时我们可以封装一层方法将来处理上面那层代码逻辑例如:

    1. private void funName() {
    2. InvokedFun()
    3. // 继续执行代码逻辑
    4. .........
    5. }
    6. private void InvokedFun() {
    7. if (a != b) {
    8. return;
    9. }
    10. if (c != d) {
    11. return;
    12. }
    13. if (e != f) {
    14. return;
    15. }
    16. // 代码执行逻辑
    17. ...........
    18. }

    基本以上两种技巧如果应用得当代码会清晰很多,一定程度商可以帮自己理清思路,并降低bug 出现的几率。

    2022年11月25日 补充

    在写代码的过程中可能会出现这样一种情况:

    1. private void funName(Map entityMap,Integer id) {
    2. if (entityMap != null) {
    3. Entity entity = entityMap.get(id)
    4. if (entity != null) {
    5. // 执行代码逻辑A
    6. .......
    7. }
    8. } else {
    9. Entity entity = new Entity()
    10. // 设置相关属性
    11. .........
    12. // 执行代码逻辑A
    13. .........
    14. entityMap.put(id,entity)
    15. }
    16. }

    上面的代码逻辑A 执行的是完全相同的代码,代码流程问题不得不写两次或者重新写一个方法进行封装,可以改成下面这种方式:

    1. private void funName(Map entityMap,Integer id) {
    2. Entity entity = entityMap.get(id)
    3. if (entityMap == null) {
    4. Entity entity = new Entity()
    5. // 设置相关属性
    6. .........
    7. entityMap.put(id,entity)
    8. }
    9. // 执行代码逻辑A
    10. .........
    11. }

    因为代码逻辑A 在为空的情况下和不为空的情况下都必须执行,而这里的if else 只是为了保证数据不为空,这时候这样处理代码会清晰简洁很多
     

    for 循环嵌套优化

    同样的道理,for 循环也会产生相同的问题,不断嵌套导致代码不清晰,例如:

    1. List demo = new ArrayList<>;
    2. for(int i = 0;i < demo.size(); i++) {
    3. // 从数据库或其他地方获取数据
    4. List entityItemList = entityMapper.listByParentId(demo.getId());
    5. for (int n = 0; n < entityList.size(); i++){
    6. EntityItem entityItem = entityItemList.get(i);
    7. // 代码执行逻辑
    8. ...........
    9. }
    10. }

    两层代码嵌套看起来没有那么乱,但是如果从第三层嵌套开始代码清晰度就会直线下降,这时候可以这样写:
     

    1. List demo = new ArrayList<>;
    2. List entityItemListAll = new ArrayList();
    3. for(int i = 0;i < demo.size(); i++) {
    4. // 从数据库或其他地方获取数据
    5. List entityItemList = entityMapper.listByParentId(demo.getId());
    6. entityItemListAll.addAll(entityItemList);
    7. }
    8. for (int n = 0; n < entityList.size(); i++){
    9. EntityItem entityItem = entityItemList.get(i);
    10. // 代码执行逻辑
    11. ...........
    12. }

    算是以空间换代码整洁度,但是自己想想,这里真正占用到内存的只有entityItemListAll 的创建,因为即使用entityItemListAll.addAll(entityItemList);将数据添加到新的list 当中,其实只是将原list 的每个数据的内存地址进行了拷贝,并不会新建对象,为此我做了以下测试:
     

    1. List listA = new ArrayList<>();
    2. listA.add("1");
    3. listA.add("2");
    4. listA.add("3");
    5. List listB = new ArrayList<>();
    6. listB.addAll(listA);
    7. for (int i = 0; i < listA.size(); i++) {
    8. String item = listA.get(i);
    9. System.out.println(System.identityHashCode(item));
    10. }
    11. for (int i = 0; i < listB.size(); i++) {
    12. String item = listB.get(i);
    13. System.out.println(System.identityHashCode(item));
    14. }

    我使用了以下代码对内存地址进行了打印:

    打印内存地址参考:java打印对象内存地址 | kennedyhan

    System.identityHashCode(item)

    最终发现listB中的内存地址并没有发生改变:
     

    1. Connected to the target VM, address: '127.0.0.1:62988', transport: 'socket'
    2. 93122545
    3. 2083562754
    4. 1239731077
    5. 93122545
    6. 2083562754
    7. 1239731077
    8. Disconnected from the target VM, address: '127.0.0.1:62988', transport: 'socket'
    9. Process finished with exit code 0

    所以这里并没有占用新的对象,而创建一个List 个人认为成本可以忽略不计,因为方法一旦完结则方法内的所有对象将会被gc 回收。

    2022年12月20日 补充

    for 循环嵌套优化技巧(二)

    还有一种情况如下所示:

    1. for (Entity entity: entityList) {
    2. for (SearchEntity search: searchEntitylist) {
    3. if (entity.seatchId == search.id) {
    4. // 执行任务流程
    5. ......
    6. }
    7. }
    8. }

    可以看出,每次entity 循环都会遍历一次SearchEntity这是没必要的,可以通过以下方式降低循环次数,并提高代码清晰度:
     

    1. Map searchEntityMap = new HashMap();
    2. for (SearchEntity search: searchEntitylist) {
    3. searchEntityMap.put(search.id,search);
    4. }
    5. for (Entity entity: entityList) {
    6. SearchEntity search = searchEntityMap.get(entity.searchId);
    7. if (search == null) {
    8. continue;
    9. }
    10. // 执行业务逻辑
    11. .......
    12. }

  • 相关阅读:
    物联网之ESP32与微信小程序实现指示灯、转向灯
    Win11 Excel文件变成白板图标怎么解决?
    git根据文件改动将文件自动添加到缓冲区
    java计算机毕业设计食品销售网站源码+数据库+系统+lw文档+mybatis+运行部署
    HTML5与CSS3学习笔记【第二十一章 发布网站】
    HarmonyOS应用开发-组件状态管理
    200 套基于Java开发的Java毕业设计实战项目(含源码+说明文档)
    C++设计模式之单例模式、模板模式、状态模式、原型模式、CRTP 模式、组件模式、观察者模式、发布-订阅模式、访问者模式
    Java 序列化原理
    SpringBoot通过自定义注解实现日志打印
  • 原文地址:https://blog.csdn.net/qq_40929531/article/details/128004508