提问: ifelse 语句和 switch 语句,除了 if 可以更加具体的判断外,两者还有什么区别呢,各自在什么情况下使用更好 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hyd8323268
V2EX    程序员

提问: ifelse 语句和 switch 语句,除了 if 可以更加具体的判断外,两者还有什么区别呢,各自在什么情况下使用更好

  •  1
     
  •   hyd8323268 2019-06-25 10:22:26 +08:00 5685 次点击
    这是一个创建于 2351 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提问: ifelse 语句和 switch 语句,除了 if 可以更加具体的判断外,两者还有什么区别呢,各自在什么情况下使用更好

    42 条回复    2019-06-28 10:30:47 +08:00
    hyd8323268
        1
    hyd8323268  
    OP
       2019-06-25 10:25:12 +08:00
    刚刚看了看博客说 switch 会比 if 效率更好点,但是具体为什么好呢,好多少
    penisulaS
        2
    penisulaS  
       2019-06-25 10:26:52 +08:00
    我好像在一些地方看到推荐用 if/else 替换 switch
    chendy
        3
    chendy  
       2019-06-25 10:33:52 +08:00
    有的语言(我只知道 kotlin ),case 里可以放条件判断,效果相当于一串 if-else-if
    不考虑这个,switch 在一些情况下性能比一串判断好,毕竟只有一次判断,ifelse 可能要判断很多次才能走到复合条件的分支
    最后其实还是“具体情况具体分析”,用哪种写起来清晰已读就用哪种
    hyd8323268
        4
    hyd8323268  
    OP
       2019-06-25 10:35:18 +08:00
    if 语句会从第一个判断开始,挨个过,直到满足条件。而 switch 会创建一个类似数组的东西,然后把每个 case 内的条件放入,如果需要判断的值是数字,则去判断数组中最大值是否大于变量,小于则直接走 default,如果大于则再走指定 case。

    大概是这样吗
    misaka19000
        5
    misaka19000  
       2019-06-25 10:35:57 +08:00
    这个问题,要具体语言具体分析
    annielong
        6
    annielong  
       2019-06-25 10:53:13 +08:00   1
    反正个人用的时候判断条件超过 3 个就使用 switch,不超过就用 if
    glishijie
        7
    glishijie  
       2019-06-25 11:10:41 +08:00 via Android
    不同语言语义是不同的,c 语言 case 只能是常数值,不能是表达式,switch 实现的时候通常会有 switch table,可以减小 cache Miss,性能会好一点
    cnzjl
        8
    cnzjl  
       2019-06-25 11:14:59 +08:00
    使用 switch..case 应该是更好维护点,你想想 10 个条件在那使用 if...else,然后 switch 的匹配好像是随机的吧,确定了选择值就直接跳过去了,如果是 if 的话就要一步一步走下去,条件多的时候还是推荐 switch
    shendaowu
        9
    shendaowu  
       2019-06-25 11:29:04 +08:00   1
    switch 在一定条件下时间复杂度好像可以达到 O(1)。有兴趣可以搜搜“查表法”。这篇好像不错: https://www.jianshu.com/p/3efd6ca8011f。switch 在某些条件下应该是可以优化成类似查表法的东西,我不太确定。楼主如果懂汇编语言的话写一些不同的 switch 语句然后看汇编代码会很好玩的。我之前好像就是在看汇编代码的时候发现 switch 和 if 的区别的。
    shendaowu
        10
    shendaowu  
       2019-06-25 11:29:34 +08:00
    pkookp8
        11
    pkookp8  
       2019-06-25 11:30:12 +08:00 via Android
    什么语言
    试了下 c 语言,x86 的 gcc,差了一条指令
    对 x86 汇编不太熟还没仔细看
    shawndev
        12
    shawndev  
       2019-06-25 11:30:18 +08:00
    有模式匹配的语言,switch case 表达力更强。没有模式匹配的语言,多数情况下 switch case 可以使用表驱动法开发。
    xuanbg
        13
    xuanbg  
       2019-06-25 11:31:03 +08:00
    if()需要按顺序一个个 else if()进行判断执行代码块还是跳出,switch 直达条件所在代码块执行。所以只有一个 if/else 两者没区别,else if 越多区别越大。当然,switch 虽好,不符合条件也是用不了的。
    xuanbg
        14
    xuanbg  
       2019-06-25 11:36:01 +08:00
    @chendy case 里可以放条件判断,效果并不是相当于一串 if-else-if。case 里的条件只是第二次 match 罢了,不成功就结束了,不会再去 match 下一个 case
    dangyuluo
        15
    dangyuluo  
       2019-06-25 11:37:36 +08:00
    现代编译器足够聪明,在条件不造成其他影响的情况下,能够自动将二者转换,挑选效率最高的那个,放心交给编译器去做就可以了,实在害怕可以看一下出来的汇编代码。

    当然你也可以添加分支预测语句`likely(xxx)`,不过一般这时候你也成大牛了。
    wysnylc
        16
    wysnylc  
       2019-06-25 12:27:12 +08:00
    在 java 中 if else if else 是从上往下逐个匹配,在上百个判断时效率极低,此时 switch 可以站出来了因为时间复杂度是 O(1)
    然后还有一种是使用 treeMap 可以做范围条件匹配,简单讲是能用 switch 和 treeMap 就用不行再考虑 if else
    maokabc
        17
    maokabc  
       2019-06-25 12:42:00 +08:00 via Android
    其他不清楚,java 整数 switch 的话会被编译为 table-switch 或者 lookup-switch,对应查表法和二分法
    Shy07
        18
    Shy07  
       2019-06-25 12:54:59 +08:00
    弱类型的建议用 if else 严格判断
    switch 建议用 hash/array/map/object + closure 的方式更 FP
    ragnaroks
        19
    ragnaroks  
       2019-06-25 13:45:17 +08:00
    if 可以对应多个判断项,比如`object1!=null && object1.value1 is Int32`,不过如果是 C#的话,7+以上区别不大了,switch 也可以匹配多个表达式
    springmarker
        20
    springmarker  
       2019-06-25 14:06:36 +08:00
    一个是静态的,一个是动态的
    yedanten
        21
    yedanten  
       2019-06-25 15:07:21 +08:00
    可以写个小 demo,然后逆向一下就知道了。这里写两个 demo 给 LZ 解释一下。
    两个 demo 编译都是采用 gcc -O0 的方式
    先看 if 的,代码如下。
    ![ifcode]( https://imgur.com/3Nc8Nzl)

    在看逆向之后的结果
    ![ifreverse]( https://imgur.com/6IkQxQ2)
    和代码所写的判断顺序一样,逐个判断。

    在看 switch 的,代码如下。
    ![switchcode]( https://imgur.com/9PBOKmz)

    逆向结果
    ![switchreverse]( https://imgur.com/Ox2qH4C)
    第一次判断和数值 2 对比,后续采用大于还是小于,进行二分法逐层判断。

    所以在写 C/C++的时候,关闭编译器优化的情况下,如果判断分支比较多,采用 switch 效率会更高。

    然后在吐个槽……分支真的那么多的时候,是不是应该考虑优化业务逻辑了
    yedanten
        22
    yedanten  
       2019-06-25 15:08:32 +08:00
    @yedanten 摔,为什么 markdown 格式发图失败了……
    hyd8323268
        23
    hyd8323268  
    OP
       2019-06-25 15:58:45 +08:00
    @shendaowu 感谢 晚上回去看看
    hyd8323268
        24
    hyd8323268  
    OP
       2019-06-25 16:01:21 +08:00
    @yedanten 兄弟你链接挂了
    labnotok
        25
    labnotok  
       2019-06-25 16:05:16 +08:00 via Android
    由于每个 case 的出现概率不同,
    if else 可以利用先验知识优化,
    达到实际中的最小复杂度。
    yedanten
        26
    yedanten  
       2019-06-25 16:08:25 +08:00 via Android
    @hyd8323268 额,这个图床要搭梯子……
    psychoo
        27
    psychoo  
       2019-06-25 16:37:03 +08:00
    试了一下 C 语言 1 亿次的 11 条件 if 和 switch,if 比 switch 快一点,不知原因
    wym7223645
        28
    wym7223645  
       2019-06-25 17:10:52 +08:00
    java 项目,我们项目要求你使用 if-else 不建议使用 switch,原因就是 业务变化太快,分分钟的加上复杂条件
    jaskle
        29
    jaskle  
       2019-06-25 19:14:35 +08:00 via Android
    其实吧,与语言有关,如果是脚本类还是 if 吧,Java 判断量多的可以用用 switch,c 系的只有数值接近或递增规律明显才会用跳表。总结:哪个方便用哪个,除非你的性能瓶颈不在 io 上,这点性能损耗也就 12306 能用上
    secondwtq
        30
    secondwtq  
       2019-06-25 19:40:37 +08:00 via iPad
    secondwtq
        31
    secondwtq  
       2019-06-25 19:43:07 +08:00 via iPad
    @yedanten 为什么要关优化?
    你可以去看下 LLVM 的代码,大块的 switch 满天飞
    dremy
        32
    dremy  
       2019-06-25 19:56:54 +08:00 via iPhone
    自以为比编译器聪明系列
    yedanten
        33
    yedanten  
       2019-06-25 20:54:03 +08:00 via Android
    @secondwtq 这不是为了给楼主演示 if 和 switch 在编译后是怎么执行的,才关掉优化嘛,开着优化那反汇编出来的都是二分法判断。
    weixiangzhe
        34
    weixiangzhe  
       2019-06-25 22:23:42 +08:00
    python 就没有 switch 吧,还是看语言吧
    pan519
        35
    pan519  
       2019-06-26 01:41:14 +08:00
    小白也有类似疑问。。。switch 不是后面只能写 int string 类的嘛?
    csys
        36
    csys  
       2019-06-26 02:19:51 +08:00 via Android
    取决于有没有模式匹配
    msg7086
        37
    msg7086  
       2019-06-26 03:11:09 +08:00
    怎么写舒服怎么写。这种细节上的效率优化带来的性能提升太小了。真的遇到性能瓶颈了再做 Profiling 不迟。
    hallwoodzhang
        38
    hallwoodzhang  
       2019-06-26 05:04:49 +08:00 via Android
    switch 语句会直接通过条件查表,然后通过 offset 跳到对应指令,if 则没这么快
    zwh2698
        39
    zwh2698  
       2019-06-26 07:12:30 +08:00 via Android   2
    科普编译器跳转表,很多 switch 语句编译器在后期都把它转成跳转表,而一般的 if 语句就是汇编的大于等于小于跳转,两个执行的代码多少不同。关键来了:现代编译器对 if 语句一定多个一起的也会做成跳转表,比较少的,就在 peephole 优化阶段删掉更多的无用语句,也不会差很多。
    Mohanson
        40
    Mohanson  
       2019-06-26 09:32:05 +08:00 via Android
    语义不同
    ysn2233
        41
    ysn2233  
       2019-06-26 11:26:28 +08:00
    现在来说,不带模式匹配的语言感觉没什么区别了都
    hyd8323268
        42
    hyd8323268  
    OP
       2019-06-28 10:30:47 +08:00
    @zwh2698 感谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5116 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 68ms UTC 09:13 PVG 17:13 LAX 01:13 JFK 04:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86