HashMap与Switch语句性能

HashMap本质上具有O(1)性能,而开关状态可以具有O(1)或O(log(n)),具体取决于编译器是使用tableswitch还是查找开关。

可以理解的是,如果switch语句是这样编写的,

switch (int) { case 1: case 2: case 3: case 4: default: } 

那么它将使用一个tableswitch,并且显然比标准的HashMap具有性能优势。 但是如果switch语句稀疏怎么办? 这将是我将要比较的两个例子:

 HashMap example = new HashMap() {{ put(1, "a"); put(10, "b"); put(100, "c"); put(1000, "d"); }}; 

 switch (int) { case 1: return "a"; case 10: return "b"; case 100: return "c"; case 1000: return "d"; default: return null; } 

什么会提供更多的吞吐量,lookupswitch或HashMap? HashMap的开销是否能够尽早为lookupswitch提供优势,但随着案例/条目数量的增加最终逐渐减少?

编辑:我尝试使用JMH的一些基准测试,这里是我的结果和使用的代码。 https://gist.github.com/mooman219/bebbdc047889c7cfe612正如你们提到的,lookupswitch语句的表现优于HashTable。 我仍然想知道为什么。

这取决于:

  1. 如果有一些项目| 固定物品。 如果可以,使用开关(最坏情况为O(n))

  2. 如果有很多项目或者你想在不修改多少代码的情况下添加未来的项目—>使用hash-map(访问时间被视为常量时间)

  3. 对于你的情况。 您不应该担心性能,因为不同的执行时间非常短。 只关注代码的可读性/可维护性。 是否值得优化一个简单的案例来改善几纳秒?

接受的答案在这里是错误的。

http://java-performance.info/string-switch-implementation/

交换机总是和哈希映射一样快。 Switch语句转换为直接查找表。 在Integer值(int,enums,short,long)的情况下,它是语句的直接lookup / jmp。 不需要进行额外的散列。 在String的情况下,它预先计算case语句的字符串哈希,并使用输入String的哈希码来确定跳转的位置。 在碰撞的情况下,它会执行if / else链。 现在你可能会想“这和HashMap一样,对吧?” 但事实并非如此。 查找的哈希码在编译时计算,并且不会根据元素的数量减少(较低的冲突机会)。

交换机具有O(1)查找,而不是O(n)。 (好吧,实际上对于少量项目,交换机转换为if / else语句。这提供了更好的代码局部性并避免了额外的内存查找。但是,对于许多项目,交换机被更改为我上面提到的查找表)。

你可以在这里阅读更多关于它的信息Java的交换机是如何工作的?

在您的情况下,由于您使用的是HashMapInteger键和switch语句的简单’ int ‘,因此执行效果最佳的实现将是switch语句,除非通过此部分代码的次数非常高(数十或者数十万)。