可以使用对象作为hashMap的key吗,需要注意些什么?
可以,但要注意重写equals和hashCode两个方法。HashMap在Put(K key,V value)方法和containsKey(Object key)方法都会进行当前HashMap中是否已有待放入的Key
为什么要重写?
要重写主要是为了保证在使用类似 HashMap 等数据结构时的正确性和一致性(保证Key唯一性)
一是让逻辑上相等的对象(即equals方法返回true)哈希值相同,避免因哈希值不同导致数据不一致或检索出错;
二是使检索时能通过准确的 equals 方法找到正确值;
三是满足 Java 规范中关于相等对象的 hashCode 与 equals 方法的关联约定,防止违反约定带来 HashMap 行为的不可预测性。
只有同时正确重写 equals 和 hashCode 方法,才能确保数据结构的正常运作。
hashcode的作用是什么
hashCode 方法返回对象哈希码,为哈希表带来优点,如支持 Hashtable。同一对象多次调用hashCode 应返回相同整数(对象 equals 信息未改),相等对象的 hashCode 必须相同。简单说它标识对象唯一性,重写 equals 时通常要重写 hashCode 以维护协定。
hashcode如何生成的?
通常来说,hashCode 的生成会涉及到对对象相关信息的某种运算。以字符串的 hashCode 生成来举例,它会先将字符串转换为字符数组,获取每个字符的 ASCII 编码值,然后通过一个循环计算,在循环中采用类似‘31*当前哈希值+当前字符编码值’这样的方式来逐步得出最终的 hashCode 值。
选择 31 这个倍数有几个原因,一是 31 是质数,能让结果更好地散列;二是能避免因所选倍数过大而导致溢出、精度损失和散列效果不佳的问题;三是 31 接近 2 的 5 次幂,这样有利于虚拟机进行自动移位优化,从而获得更好的性能。当然,具体的实现细节可能因不同的编程语言和运行环境而有所差异。
hashmap头插法和尾插法的区别
头插法是指新元素插入到链表的头部,这样在遍历 HashMap 时,元素的插入顺序和遍历顺序是相反的。JDK1.7是用单链表进行的纵向延伸,当采用头插法时会容易出现逆序且环形链表死循环问题。
尾插法则是将新元素添加到链表的尾部。使用尾插法时,元素的插入顺序和遍历顺序是一致的,相对来说在一些场景下更符合正常的逻辑顺序,并且在多线程环境下表现更为稳定,不容易出现因头插法可能引发的问题。JDK1.8之后是因为加入了红黑树使用尾插法,能够避免出现逆序且链表死循环的问题
hashmap在jdk1.7和1.8扩容上有什么区别
1.8是扩容前插入键值,连同旧的键值一起转移,一起计算,1.7是扩容后进行插入,1.8有红黑树为了减少链表转换。
详细说说hashmap为什么要扩容?何时要扩容吗?
HashMap 要扩容主要是为了避免因元素不断增加导致哈希冲突加剧,影响性能。当元素个数超过阈值(容量乘以加载因子)时就需要扩容。这样能保证有足够的空间存储新元素,维持相对合理的负载,确保 HashMap 能高效运行。