我们习惯于说HashMap,get/put次运算是O(1).但是,这取决于散列实现.默认对象散列实际上是JVM堆中的内部地址.我们真的可以说get/put是O(1)吗?

可用内存是另一个问题.正如我从javadocs中了解到的,HashMap负载系数应该是0.75.如果JVM中没有足够的内存,并且负载因子超过了限制,该怎么办?

所以,看起来O(1)是不能保证的.这有意义吗,还是我错过了什么?

推荐答案

这取决于很多事情.它是usuallyo(1),有一个不错的散列,它本身就是常数时间...但是你可能有一个需要很长时间来计算的散列,and如果散列映射中有多个项目返回相同的散列码,get将不得不对它们进行迭代,并对每个项目调用equals来找到匹配项.

在最坏的情况下,由于遍历同一散列桶中的所有条目(例如,如果它们都有相同的散列代码),HashMap具有O(n)查找.幸运的是,根据我的经验,这种最坏的情况在现实生活中并不经常出现.所以不,O(1)当然不能保证——但这通常是在考虑使用哪些算法和数据 struct 时应该假设的.

在JDK 8中,对HashMap进行了调整,这样如果可以比较密钥进行排序,那么任何密集的bucket都将实现为一棵树,这样即使有许多条目具有相同的哈希代码,复杂性也为O(logn).当然,如果您有一个等式和顺序不同的键类型,这可能会导致问题.

是的,如果你没有足够的内存来存储哈希映射,你会有麻烦...但不管你使用什么样的数据 struct ,这都是事实.

Java相关问答推荐

如何在多个设备上同时运行Android Studio的项目?

Spring Boot找不到Mapper bean

Cosmos Change Feed Process Lag远远超过收集中的记录数量

无法传递消费者<;>;实例

Apache POI:使用反射获取zoom 级别

@org.springframework.beans.factory.annotation.Autowired(required=true)-注入点有以下注释:-SpringBoot

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

如何获取Instant#of EpochSecond(?)的最大值

如何只修改父类ChroniclerView位置0处的第一个嵌套ChroniclerView(child)元素?

Sack()步骤中的合并运算符未按预期工作

在Eclipse中调试未导出的JDK模块的Java包

如何配置空手道以使用FeignClient或RestTemplate代替ApacheHttpClient

通过Java列表中的某些字段搜索值

无法使用Java PreparedStatement在SQLite中的日期之间获取结果

在Spring Boot JPA for MySQL中为我的所有类创建Bean时出错?

在不使用instanceof或强制转换的情况下从父类变量调用子类方法

Maven-Dependency-Plugin 3.6.+开始查找在依赖关系:分析目标期间找到的新的使用的未声明依赖关系

Java HashMap保留所有时间复杂性

OAuth:登录后无法查看Google邮箱地址

为什么没有加载java.se模块?