首页 > 其他分享 >美团一面:项目中有 10000 个 if else 如何优化?想了半天,被问懵了!

美团一面:项目中有 10000 个 if else 如何优化?想了半天,被问懵了!

时间:2024-05-21 09:29:14浏览次数:25  
标签:逻辑 return 美团 else 10000 null 优化 代码

大家好,我是R哥。

最近做 Java 面试辅导,有个兄弟面试美团,遇到一个特别有意思的问题:

一万个 if else 如何优化,有好的解决方案吗?

我看到这问题都有点懵逼,现实项目中怎么可能会有 10000 个 if else 的代码,至少我工作 10 余年没见过样的代码。

关键要写完这 10000 行的 if else 代码,如果每天写 100 个,是不是意味着也要 100 天才能写完,并且每次请求都要执行几千上万次的判断,代码难以维护不说,还会严重影响系统性能

很显然,面试官考察的不是一般的八股文,这个问题可以看作是一道场景题,它考察一个程序员在面对复杂逻辑判断时的优化能力,也是在考察一个程序员临场发挥技术能力

这兄弟虽然说上了策略模式,但显然不是完美和唯一的解决方案,另外像责任链模式等其他设计模式都会存在这样的问题,所以具体的问题还得具体分析。

所以这题可以这样回答:

  • 如果这 1 万个 if else 是在同一个代码块流程里面,这就要考虑这 1 万 if else 存在的意义了,因为这么量极的 if else 会很难维护,也会极其影响性能,需要具体分析然后再去分析如何去分解和优化。
  • 如果这 1 万个 if else 分散在同一个项目里面,那么优化 if else 的方式有很多种,包括.……

下面我说说几种方案,欢迎大家拍砖。

if else 优化方案

方案1:策略模式

这个兄弟也说到了策略模式,策略模式介绍及实战看这篇:

别在再满屏的 if/ else 了,试试策略模式,真香!!

使用策略模式确实可以提升代码的优雅性,但也会存在以下问题:

  • 如果是大量的 if else 分支,比如这 1 万个,那就会有 1 万个策略类,此时就会造成类膨胀,并且随着时间的推移逐渐变得更加庞大而复杂
  • 如果是多层的 if else 嵌套,策略模式可能也无法派上用场了。

策略模式的优点是可以很方便的解耦,适用于有多种不同逻辑和算法的 if 场景,但不适用于大量的 if else 场景。

方案2:策略模式变体

这是策略模式的一种变体:

Map<Integer, Runnable> actionMap = new HashMap<>();
actionMap.put("condition1", () -> { /* 分支1的执行逻辑 */ });
actionMap.put("condition2", () -> { /* 分支2的执行逻辑 */ });
actionMap.put("conditionN", () -> { /* 分支N的执行逻辑 */ });

// 根据条件获取执行逻辑
Runnable action = actionMap.get("condition1");
if (action != null) {
    action.run();
}

这种把业务逻辑代码分离出去了,简化了单个类的代码,也省去了策略实现类,让策略类不会得到膨胀,但如果有大量的条件映射,依然会造成单个类的膨胀和难以维护。

这里使用的是线程异步执行的案例,还可以把要执行的逻辑代码存储在其他类、数据库中,然后再用反射或者动态编译的方式加载进去并执行。

方案3:多级嵌套优化

上面说的两种方案嵌套可能无法解决,如果是这种带层级的判断是可以优化的:

/*
* 来源公众号:Java技术栈 
*/
if(xxxOrder != null){
 if(xxxOrder.getXxxShippingInfo() != null){
  if(xxxOrder.getXxxShippingInfo().getXxxShipmentDetails() != null){
   if(xxxOrder.getXxxShippingInfo().getXxxShipmentDetails().getXxxTrackingInfo() != null){
    ...
   }
  }
 }
}

这种 if 嵌套层级太多,极不优雅,怎么优化见我之前写的这篇:

if else 太多?看我用 Java 8 轻松干掉!

方案4:使用三目运算符

如果判断条件不多,只有 2、3 个的情况下可以使用三目运算符简化 if else 分支。

比如以下代码:

String desc;
if (condition1) {
    desc = "XX1";
} else if (condition2) {
    desc = "XX2";
} else {
    desc = "XX3";
}

使用三目运算符一行搞定:

String desc = condition1 ? "XX1" : (condition2 ? "XX2" : "XX3");

超过 3 个条件就不建议使用了,不然代码可读性会大大降低。

方案5:使用枚举

枚举类型可以用来表示一组固定的值,例如星期几、月份、颜色等,它提供了一种更简洁、可读性更高的方式来表示一组相关的常量。

如以下示例代码:

/**
 * 公众号:Java技术栈
 */
public class Test {
    
    public static void main(String[] args) {
        Day today = Day.MONDAY;
        System.out.println("Today is " + today);
        System.out.println("Today is " + today.getChineseName());
    }

    enum Day {
        MONDAY("星期一"),
        TUESDAY("星期二"),
        WEDNESDAY("星期三"),
        THURSDAY("星期四"),
        FRIDAY("星期五"),
        SATURDAY("星期六"),
        SUNDAY("星期日");

        private String chineseName;

        Day(String chineseName) {
            this.chineseName = chineseName;
        }

        public String getChineseName() {
            return chineseName;
        }
    }
    
}

这里我只写了一个字段,我们可以在枚举属性里面定义多个字段,这样就无需大量的 if else 判断,直接通过枚举来获取某个某一组固定的值了。

方案6:使用 Optional

Java 8 提供了一个 Optional 新特性,它是一个可以包含 null 值的容器对象,可以用来代替 xx != null 的判断。

参考我之前写的这篇:

JDK 8 新特性之 Optional

如果项目中存在大量 xx != null 的判断,可以使用 Optional 来优化。

方案7:尽快返回

分析业务,根据 if else 的执行次数按降序排,把执行次数较多的 if 放在最前面,如果符合条件,就使用 return 返回,如下面代码:

if (条件1) {
    return
}

if (条件2) {
    return
}

...

这样改可能是比较简单的方式,在很大程度上可以提升系统的性能,但是还存在以下问题:

  • 有的条件不能按执行次数排序,存在先后或者互斥关系。
  • 如果新增一个条件,可能无法马上判定它的执行次数,如果放在后面可能也还会影响性能。
  • 对类的继续膨胀和代码维护没有任何帮助。

方案8:去除没必要的 if else

比如这种:

if (condition) {
    ...
} else {
    return;
}

优化后:

if(!condition){
    return;
}

或者是这样:

return !condition

方案9:合并条件

考虑这 1 万 if else 是不是真的每个都有必要,是不是可以合并归类,比如是不是可以把几百、几千个相似逻辑的归为一类,这样也能大大简化 if else 数量。

比如以下代码:

double calculateShipping() {
    if (orderAmount > 1000) {
        return 0.5;
    }
    if (customerLoyaltyLevel > 5) {
        return 0.5;
    }
    if (promotionIsActive) {
        return 0.5;
    }
}

优化后:

double calculateShipping() {
    if (orderAmount > 1000 || customerLoyaltyLevel > 5 || promotionIsActive) {
        return 0.5;
    }
}

这样就把返回相同值的 if 归为一类了,如果 if 较大就能大大简化代码量。

方案10:规则引擎

对于复杂的业务逻辑,业务规则经常变化,规则制定不依赖于技术团队,需要实现可配置的逻辑处理,此时可以考虑使用规则引擎来处理,比如 Drools。

规则引擎系统可用于执行一组规则,在许多业务应用程序中,业务决策可以通过一系列的逻辑规则来定义,规则引擎允许这些规则在运行时执行,而无需硬编码在应用程序之中。

规则引擎的好处是:

  • 业务逻辑可以和程序代码解耦;
  • 提高业务逻辑的可管理性;
  • 提高系统的灵活性和可扩展性;
  • 业务人员可参与决策过程;

总结

掌握优化 if else 的方法很重要,有时候面试官可能会换着法子问你,比如我们面试辅导这位兄弟遇到的这个面试官,你可以问清楚这一万个 if else 是在一个代码块中,还是在一个项目中,然后再去解答,如果不了解清楚业务场景,盲目回答又会被面试官绕进去。

本文我也总结了 10 种优化 if else 的方法,其实还不止,根据不同的场景还可以使用多态、责任链模式、模板方法模式等更多方法来消除 if else。

总之,消除 if else 并没有万能的方法,也不可能全部优化掉,在实际开发中需要根据实际场景使用不同的方法,以及多种方法组合使用,这样才是正确的方式。

像这样的面试题,我的小程序「Java面试库」还有许多,比如:

  • 如果把线程池 corePoolSize 设置为 0,会出现什么情况?
  • 线程池中的线程抛出了异常,如何处理?
  • MySQL 索引为什么选用 B+Tree 作为数据结构?
  • MySQL 的自增 ID 如果用完了,会怎么样?
  • 有了多线程,为什么还要消息队列?
  • ......

共 2800+,都是平时我面试别人,或者学员面试复盘积累下来的真题,不要在网上找乱七八糟的面试题了,浪费时间还容易被误导。

最后,推荐一波我们的「面试辅导」,有在看机会的,离职的、迷茫的,都可以加入,大厂导师 1 v 1 辅导,帮你全面提升面试综合实力,少走很多弯路,最大化提升职场收益。

版权声明: 本文系公众号 "Java技术栈" 原创,转载、引用本文内容请注明出处,抄袭、洗稿一律投诉侵权,后果自负,并保留追究其法律责任的权利。

更多文章推荐:

1.Spring Boot 3.x 教程,太全了!

2.2,000+ 道 Java面试题及答案整理(2024最新版)

3.免费获取 IDEA 激活码的 7 种方式(2024最新版)

觉得不错,别忘了随手点赞+转发哦!

标签:逻辑,return,美团,else,10000,null,优化,代码
From: https://www.cnblogs.com/javastack/p/18203306

相关文章

  • 听说你是高手?说说你的 JVM调优方法论 吧?(美团面试,问的贼细)
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • 美团一面问我i++跟++i的区别是什么
    美团一面问我i++跟++i的区别是什么面试官:“i++跟++i的区别是什么?”我:“i++是先使用然后再执行+1的操作,++i是先执行+1的操作然后再去使用i”面试官:“那你看看下面这段代码,运行结果是什么?”publicstaticvoidmain(String[]args){intj=0;for(inti=0;i<10......
  • 美团面试:如何实现线程任务编排?
    线程任务编排指的是对多个线程任务按照一定的逻辑顺序或条件进行组织和安排,以实现协同工作、顺序执行或并行执行的一种机制。1.线程任务编排VS线程通讯有同学可能会想:那线程的任务编排是不是问的就是线程间通讯啊?线程间通讯我知道了,它的实现方式总共有以下几种方式:Object......
  • 美团二面:SpringBoot读取配置优先级顺序是什么?
    引言SpringBoot作为一种轻量级的Java应用程序框架,以其开箱即用、快速搭建新项目的特性赢得了广大开发者的青睐。其核心理念之一就是简化配置过程,使开发者能够快速响应复杂多变的生产环境需求。为了实现这一点,SpringBoot支持丰富的外部化配置机制,允许应用程序根据不同的部署环境......
  • SystemVerilog -- 3.7 SystemVerilog 'unique' and 'priority' if-else
    SystemVerilog'unique'and'priority'if-else条件语句用于决定是否执行语句。ifelseSystemVerilog引入了一下用于违规检查的构造。ifelseunique-ifunique0-ifpriority-ifunique-if,unique0-ifunique-if按任意顺序评估条件,并执行以下操作:当所有条件都不匹配时,报......
  • 【牛客】美团2024年春招第一场笔试【技术】
    【牛客】美团2024年春招第一场笔试【技术】1.小美的平衡矩阵#include<iostream>#include<vector>usingnamespacestd;intmain(){intn;cin>>n;vector<vector<int>>nums;for(inti=0;i<n;i++){fgetc(stdin);......
  • python教程2:if...else...+循环
    一、if判断有单分支、双分支、多分支,下面就是一个多分支的案例:二、缩进三、for循环四、while循环 五、其他random模块 string模块 ......
  • 这种运行结果里的10.100000001,怎么能最快改成10.1?
    大家好,我是Python进阶者。一、前言前几天在Python白银交流群【无敌劈叉小狗】问了一个Python基础的问题。问题如下:这种运行结果里的10.100000001,怎么能最快改成10.1,所有结果都最多一位小数。二、实现过程这里【论草莓如何成为冻干莓】和【.】给了一个指导:用round函数或者’%.......
  • 【康复训练1】2.24.4.13美团春招
    前言写在前面,由于很长一段时间没有敲代码了,上周写了华为的题目,debug半天也没有debug出一道来,属实狠狠的打击到我了,因此特开此专栏,以便开启老年选手康复之路!!!第一题-塔子哥的好子矩阵前3题,手速题水题#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongcon......
  • 实验一———美团APP
    墨刀、Axure、Mockplus等原型设计工具优缺点分析:一、墨刀优点:在轻量级的移动端原型制作更加迅速,展示更加方便。缺点:价格较贵,不能画流程图,相对于其他两款功能还不是很全面;应用局限性,专注于app原型设计,在后台和网页稍有乏力;归档能力不足,更倾向于链接、二维码形式输出,不能以文档输......