`
sunqi
  • 浏览: 230833 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

map or switch

 
阅读更多

最近碰到个场景,还蛮有普遍性的,如简单工厂方法,需要依据入参选择不同的业务逻辑进行对应的处理

 

马上想到两个方案

方案一:采用map存放对应入口的处理方法,然后请求进来后经过get就行,map.get(et);

方案二:采用switch语句,

              switch (et) {

              case API3:

                     return api3service;

              case API4:

                     return api4service;

              case API2:

                     return api2service;

              ……

 

if else这种就不予考虑了

 

明显采用map显的更优雅,代码更具可维护性,如果用switch每次需要硬编码

那性能呢?

 

但用map,也可以做些优化处理,比如我发现一些入参在map默认大小为16下,其桶位置发生了碰撞,这样每次get

的时候就需要遍历了,这是不好,当然有两种方案,一是改key值避免碰撞,二是改map大小,让其不发生碰撞,

我采用map大小为64,避免碰撞,当然后面如要继续添加时候,需要关注

经测试,性能可以提升44%,(本机场景,并且这个key在桶的最尾部,也就是需要全部遍历桶全部数据的场景,并且全部预先执行1w次,摒弃了jit对结果的影响)

 

mapget操作,每次需要进行hash,位移操作,&操作,再比较操作,想想就需要很多的指令要执行完才能拿到

 

如果是switch呢?

Switch在编译后,有LookupSwitch TableSwitch,其中TableSwitchO(1)的,LookupSwitch O(log n) 

 

TableSwitch情况

int chooseNear(int i) {
    switch (i) {
        case 0:  return  0;
        case 1:  return  1;
        case 2:  return  2;
        default: return -1;
    }
}

编译后结果

Method int chooseNear(int)
0   iload_1             // Push local variable 1 (argument i)
1   tableswitch 0 to 2: // Valid indices are 0 through 2
      0: 28             // If i is 0, continue at 28
      1: 30             // If i is 1, continue at 30
      2: 32             // If i is 2, continue at 32
      default:34        // Otherwise, continue at 34
28  iconst_0            // i was 0; push int constant 0...
29  ireturn             // ...and return it
30  iconst_1            // i was 1; push int constant 1...
31  ireturn             // ...and return it
32  iconst_2            // i was 2; push int constant 2...
33  ireturn             // ...and return it
34  iconst_m1           // otherwise push int constant -1...
35  ireturn             // ...and return it

 

也就是TableSwitch只要计算一次偏移量,立即就能到case执行,其时间复杂度为O(1) 

 

LookupSwitch

int chooseFar(int i) {
    switch (i) {
        case -100: return -1;
        case 0:    return  0;
        case 100:  return  1;
        default:   return -1;
    }
}

编译后:

Method int chooseFar(int)
0   iload_1
1   lookupswitch 3:
         -100: 36
            0: 38
          100: 40
      default: 42
36  iconst_m1
37  ireturn
38  iconst_0
39  ireturn
40  iconst_1
41  ireturn
42  iconst_m1
43  ireturn

 

也就是LookupSwitch编译后会保证其顺序,并采用二分法查找对应的case,其时间复杂度为O(log n) 

本机,全部预先执行1w次跳过jit的影响,采用mapswitch各执行1亿次,执行时间是两位数的差距,map400msswitch5ms

 

当然测试的场景case都比较少,如果达到1k多个case条件呢? Jit还会把jvm指令缓存吗?,如果不缓存又是另外的情况了

大家可以把eclipse设置Xint,看看屏蔽jit后大量运行的效果

还有switch在什么场景下编译后会是TableSwitch,什么下会是LookupSwitch,毕竟两者的时间复杂度还是有差距

Java应用的性能,还是要详细分析其场景,至于要性能还是代码更优雅,要自己权衡了,呵呵,有更好的方案,还请分享哦

 

参考资料

 

http://stackoverflow.com/questions/10287700/difference-between-jvma-lookupswitch-and-tableswitch

 

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10

分享到:
评论

相关推荐

    bit map 苹果手机户外导航

    Store multiple maps on your iPhone or iPad, and switch between them. With Bit Map, you can view your own choice of maps, instead of generic maps chosen by somebody else, making it ideal

    ReactFastMap:单例地图组件,只需要初始化一次,就能无缝切换地图,避免组件切换带来的频繁地图初始化。A single instance map component that allow you switch the component frequently with no re-initialize

    Even if the pages switch frequently, the Map Component don't need to wait rendering. Basic Usage Install npm i react-fast-map // or yarn add react-fast-map 1. Import API file // 1. 在/public/index....

    Getting Notification of CD-ROM Insertion or Removal.ppt

    switch (nEventType) { case DBT_DEVICEARRIVAL: MessageBox("Media 已经放進來了 , 並且準備好了", "Device"); break; case DBT_DEVICEREMOVECOMPLETE: MessageBox("Media 被移除", "Device"); break; ...

    swstp 快速生成树协议

    based on the IEEE 802.1D standard and Cisco proprietary extensions, or the rapid per-VLAN spanning-tree plus (rapid-PVST+) protocol based on the IEEE 802.1w standard. For information about the ...

    javascript中break,continue和return语句用法小结

    - `break` 语句的作用是立即终止最内层的循环(如 `for`、`while` 或 `do...while` 循环)或 `switch` 语句的执行。一旦执行了 `break`,程序会跳出当前循环或 `switch` 体,继续执行之后的代码。 - 在示例代码中...

    RealToon 5.2.1 卡通动漫风格着色器.txt

    *(This is not a matcap style reflection or cubemap.) - Outline: *(Can change the Color and Width) *(With noise/distort outline for sketch style outline and dynamic) *(You can choose to use outline or...

    MS-DOS 5.0

    ROM BIOS to version 1.21 or later. The ROM BIOS version number is displayed when you start your computer. 2.14 LANtastic -------------- If you use a LANtastic network, disable it before running Setup...

    考试类精品--️每天花5分钟的时间,弄懂一道面试题 or Js小知识 来鞭策自己学习思考,每天进步一点,流年笑掷,未.zip

    "每天花5分钟的时间,弄懂一道面试题 or Js小知识"揭示了这份资源的目的,即通过每日的学习和思考,帮助用户逐步提升技能,每天进步一点点。"流年笑掷,未来可期"可能是这个学习计划的口号,鼓励持续努力,期待未来...

    jdk1[1].7_新特性.doc

    Map, Integer> map = {'key' : 1}; int value = map['key']; ``` 这使得代码更加直观和易读。 2、自动资源管理(try-with-resources) JDK 1.7 引入了 try-with-resources 语句,使得资源在使用完毕后能够自动关闭...

    Coffeescript中文手册

    28. **And/or**:`and`和`or`操作符提供短路逻辑,`&&`和`||`在CoffeeScript中仍可使用。 29. **解构赋值**:CoffeeScript支持数组和对象的解构赋值,用于从复杂数据结构中提取值。 30. **其他类库**:...

    最常见的VC++编译错误信息_fatal_error

    2. Fatal Error C1083:Cannot open include file: 'R…….h': No such file or directory 这是一个常见的编译错误,原因是编译器无法打开包含文件“R…….h”。解决方法是检查该文件是否存在于正确的路径下,如果...

    eac3to V3.17

    * added undocumented "-no2ndpass" switch to turn off 2nd pass processing * fixed: two pass processing sometimes produced superfluous sup files * fixed: MPG/EVO/VOB audio tracks with "PES extension 2" ...

    最新的jdk1.7

    - **Map接口的新方法**:如`putIfAbsent()`,`remove(Object key, Object value)`,`replace(K key, V oldValue, V newValue)`等,这些方法增强了Map的操作性。 - **新的集合工厂方法**:例如`Collections....

    MyBatis动态SQL详解.pdf

    `choose`元素类似于Java中的`switch`语句,可以用来选择多个条件中的一个。其中`when`元素对应于`if`条件,而`otherwise`元素则是在所有`when`条件都不满足时执行的默认语句。 ```xml and state = 0 and ...

    Groovy应用(基本操作)

    Groovy支持常见的控制结构,如if-else、for循环、while循环以及switch语句。其语法与Java相似但更简洁,例如: ```groovy def number = 10 if (number > 5) { println "Number is greater than 5" } else { ...

    JDK1.7_新特性

    - **并发安全的Map集合**:虽然标准库并没有直接提供 `{name: "xxx", age: 18}` 这样的语法来创建Map对象,但可以使用 `ConcurrentHashMap` 或其他并发安全的Map实现来达到类似的效果。 通过以上介绍可以看出,JDK ...

    OCaml的声明性事件和信号_OCaml_下载.zip

    4. **信号的组合**:react库允许通过操作符(如`map`、`switch`、`and`、`or`等)来组合信号。例如,`map`函数可以将一个信号的值传递给函数并返回一个新的信号,而`switch`则可以切换关注的信号源。 5. **反应式...

    lrucacheleetcode-thinking-in-algorithm:flag:7天入门数据结构与算法

    or map) 二维数据结构 基础:树tree,图graph 高级:二叉搜索树binary search tree(red-black tree,AVL),堆heap,并查集disjoint set,字典树Trie 特殊数据结构 位运算Bitwise,布隆过滤器BloomFilter LRU Cache ...

    MyBatis 深入浅出-动态SQL

    5. **`<choose>`, `<when>`, `<otherwise>`** - 类似于Java中的switch-case语句,提供多个条件选择。 6. **`<foreach>`** - 遍历集合或数组,生成IN子句等。 接下来将详细介绍这些标签的使用方法和应用场景。 ####...

Global site tag (gtag.js) - Google Analytics