Java-Hashcode相关问题

本文深入探讨了Java集合框架中的核心概念,包括Hashcode与equals的区别、HashMap与HashTable的对比,以及HashMap的工作原理。详细解释了hashcode碰撞问题及其解决策略,介绍了JDK1.8中红黑树的引入原因,以及加载因子的选择依据。

1.Hashcode和equals的区别?

   Hashcode如果相等的情况下,对象的值不一定相等。equals比较对象的内容相同,hashcode一定相等。

2.为什么重写equals一定要重写hashcode?

因为遵循hashcode相等的情况下对象的值不一定相等。equals比较对象的内容相同,hashcode一定相等的原则,所以重写equals一定要重写hashcode保证原则不变。

3.HashMap和HashTable的区别?

  1)线程安全上:HashMap是线程不安全的,HashTable被Synchronize修饰,所以线程安全

  2)数据存储:HashMap运行数据的key为null,存放在数组的第0个位置。HashTable不允许数据为null,会抛出异常。

4.HashMap的put是如何实现的?
(1)计算key的hashCode
(2)将key的hashCode作为计算因子,通过哈希算法计算HashMap的数组下标index
(3)如果index下标的数组元素为空,直接put(新增元素)
(4)如果index下标的数组元素不为空,调用key的equal方法,判断index位置的链表是否存在
(5)如果找到链表中某个元素与key的equals方法相等,则使用value更新
(6)如果未找到链表中某个元素与key的equals方法相等,则新增
一般面试的时

候,经常会问到HashMap的原理。起初一直不理解,搞清楚HashMap的原理很重要吗?我就知道HashMap是线程不安全的。后来仔细看了下HashMap的底层实现原理,
原来HashMap既具有数组的快速查询,又兼具链表的快速插入特性。虽然不是线程安全的,但通过线程安全处理之后,无论是查询还是添加元素都很高效,用途广泛,因此掌握HashMap的底层原理的重要性不言而喻了。

5.如何理解hashcode的碰撞问题和解决方法?

对象值可能不等但是hashcode可能相等,即碰撞,如下图的例子中

		String value1="a";
		Integer value2=97;
		System.out.println(value1.hashCode());
		System.out.println(value2.hashCode());
		System.out.println(value1.hashCode()==value2.hashCode());//结果为true

将所有关键字为同义词的记录存储在同一线性链表中。如下:

7.JDK1.8为什么引入红黑树?

Hashmap1.7采用数组+链表实现,采用HashEntry封装我们的键值对,Hashmap根据key查询没有冲突的情况下,时间复杂度为O(1),但是有冲突时时间复杂度为O(n),所以JDK1.8中,链表长度大于8,并且数组长度是64的情况下转为红黑树存放。

8.加载因子为什么是0.75不是其他?

Hashmap中jdk1.7的默认数组长度为16,加载因子为0.75,即当16x0.75=12时候开始扩容,扩容为原来的2倍(16x2=32)

如果加载因子太小,key的冲突概率会小,但是浪费内存空间

如果加载因子太大,key的冲突概率会大,但是利用的空间非常好

综上所述,空间利用率高,冲突概率低的情况下,取平衡值0.75

Java中,`hashCode()`方法是`Object`类的一个重要方法,所有Java类都继承自`Object`类,因此每个对象都具有`hashCode()`方法。该方法返回一个整数(`int`类型),用于标识对象的“哈希码”或“散列码”。这个哈希码在数据结构如`HashMap`、`HashSet`和`Hashtable`中起着关键作用。 ### hashCode方法的作用 `hashCode()`方法的主要作用是为对象提供一个整数值,用于快速识别对象,尤其是在哈希表等数据结构中。该方法的默认实现通常基于对象的内存地址计算哈希值,但开发者可以根据需要重写该方法,以基于对象的实际内容生成哈希码[^1]。 ### hashCode方法的契约 在重写`hashCode()`方法时,必须遵守以下契约: 1. **一致性**:只要对象用于`equals()`比较的信息没有被修改,多次调用`hashCode()`方法必须返回相同的整数值。 2. **相等性保证**:如果两个对象通过`equals()`方法比较是相等的,那么它们的`hashCode()`方法必须返回相同的哈希码。 3. **非相等性不强制**:如果两个对象通过`equals()`方法比较不相等,并不要求它们的`hashCode()`方法必须返回不同的值,但返回不同的值可以提高哈希表的性能[^2]。 ### 使用场景 1. **HashMap和HashSet**:在`HashMap`中,键对象的`hashCode()`方法决定了键值对存储的位置。`HashSet`也依赖于`hashCode()`来决定元素的存储位置。如果两个对象的`hashCode()`相同,则会进一步使用`equals()`方法来判断是否为同一个键或元素[^3]。 2. **缓存实现**:在缓存系统中,对象的哈希码可用于快速查找缓存项。 3. **唯一标识符**:某些场景下,可以结合`hashCode()`与`equals()`方法判断对象是否重复。 ### 示例代码 以下是一个重写`hashCode()`方法的示例: ```java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { return other.name == null; } else { return name.equals(other.name); } } } ``` ### 与equals方法的关系 当重写`equals()`方法时,必须同时重写`hashCode()`方法,以确保相等的对象具有相同的哈希码。如果不这样做,可能会导致在使用哈希结构(如`HashMap`或`HashSet`)时出现不一致的行为[^4]。 ### 总结 - `hashCode()`方法用于生成对象的哈希码,是`Object`类的一部分。 - 它在哈希表等数据结构中起关键作用。 - 在重写`hashCode()`方法时,必须遵循特定的契约,以确保一致性。 - 通常需要与`equals()`方法一起重写,以保持对象相等性和哈希码一致性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值