之前 , 听过很多次,重写equals()方法的时候,必须重写hashcode() ,
两个对象equals,hashcode()必然相等,两个对象hash值相等,当时不一定equals;
那么 究竟hashcode 是什么?起的作用又是什么?
hashcode() 和 equals() 方法都是Object(终极父类)中的方法;
如果子类 没有重写 , 那么就默认的调用父类中的方法;
Object 中的hashcode方法是通过本地方法实现的,并不是通过Java语言
public native int hashCode(); //This is typically implemented by converting the internal address of the object into an integer //通过把对象的地址空间转换成一个整数实现的
String 中的hashcode() :
public int hashCode() { int h = hash; // value 是 字符数组,字符串是一个字符数组构成的 if (h == 0 && value.length > 0) { char val[] = value; //散列公式: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
hashcode的作用就体现在构建hashMap , hashtable 这种集合的时候;
它们首先会根据对象hash值,找到相对应的数组下标,进行比较 , 插入和读取;
如下面的hashmap中的get(Object key) 方法:
public V get(Object key) { if (key == null) return getForNullKey(); //hashmap通过拉链法处理冲突的,Entry是链表节点类型 Entry<K,V> entry = getEntry(key); return null == entry ? null : entry.getValue(); }
final Entry<K,V> getEntry(Object key) { if (size == 0) { return null; } // 看,这一步获取该key的hash值,hash(key)方法就调用key的hashcode方法 //所以,为什么我们自定义的类型做key都要重写hashcode方法,下面会告诉你 //为什么要重写equals()方法 int hash = (key == null) ? 0 : hash(key); // 根据hash值找到index , 然后就是遍历链表 for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; //这里不就说明为什么要重写equals吗 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
final int hash(Object k) { int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); } //这里不就是根据key的hashcode来生成相应的hash值 h ^= k.hashCode(); // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
关于HashMap的扩容?
void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } //新建一个新数组将容量扩大两倍 Entry[] newTable = new Entry[newCapacity]; // 接下来就是怎样把原来数组的中的元素放入新数组中! transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); } /** * Transfers all entries from current table to newTable. */ void transfer(Entry[] newTable, boolean rehash) { int newCapacity = newTable.length; //对链表数组中的每个元素 for (Entry<K,V> e : table) { //对链表中的每个元素 while(null != e) { Entry<K,V> next = e.next; if (rehash) { //对key可能要再次hash!!! e.hash = null == e.key ? 0 : hash(e.key); } //根据e的hash值与数组的容量求的索引的位置! int i = indexFor(e.hash, newCapacity); // 这一步的意思就是 前面可能有元素在i位置了,那么就把i位置的元素加在他后面! e.next = newTable[i]; newTable[i] = e; e = next; } } }
相关推荐
### 深入理解 HashCode 方法 #### 一、HashCode 的基本概念与作用 在 Java 编程语言中,`HashCode` 是一个非常重要且基础的概念。简单来说,`HashCode` 是一个整数值,用于快速定位对象的位置。在 Java 中,每一个...
Java HashMap原理分析 Java HashMap是一种基于哈希表的数据结构,它的存储原理是通过将Key-Value对存储在一个数组中,每个数组元素是一个链表,链表中的每个元素是一个Entry对象,Entry对象包含了Key、Value和指向...
在 HashMap 的 Node 类中,hashCode 方法的实现是根据键值对的键和值来计算哈希码。 public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } equals 方法和 hashCode 方法都...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...
"关于Object中equals方法和hashCode方法判断的分析" 在 Java 中,Object 类提供了两个重要的方法:equals 方法和 hashCode 方法。这两个方法都是用于比较两个对象是否相等的,但它们的实现机理和作用域却有所不同。...
在深入探讨HashMap的实现原理之前,我们需要了解两个关键的接口方法:`hashCode()`和`equals()`。 根据《Effective JAVA》的建议,当重写`equals()`方法时,也应重写`hashCode()`方法。这是因为在HashMap中,`...
HashCode方法在Java编程中扮演着至关重要的角色,尤其是在涉及对象存储和查找效率的数据结构,如HashMap和Hashtable中。一个对象的HashCode是一个简单的哈希算法实现,尽管它相对复杂的哈希算法而言较为简单,但其...
插入HashMap的对象必须正确实现`equals()`和`hashCode()`方法,以确保键的比较和哈希计算符合预期。这两个方法的实现对于HashMap的正确性和效率至关重要。 8. **常用方法** - `put(K key, V value)`: 插入键值对...
### Java中`hashCode()`与`equals()`方法详解 #### 前言 在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将...
本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...
* 在 HashMap 中,hashCode 用于确定键的存储地址。 * 在排序算法中,hashCode 用于快速定位到目标对象。 equals() 和 hashCode() 的关系 equals() 和 hashCode() 是两个相关的概念。equals() 用于判断两个对象...
例如,在HashMap中,key的hashCode值将被用来确定其在表中的索引位置。如果两个对象的hashCode值相同,但它们不是同一个对象,那么它们将被存储在同一个索引位置上,这将导致严重的问题。 因此,在Java中,hashCode...
在本文中,我们将对 HashMap 的 put 方法的源码进行详细解读,分析put 方法源码中的内在逻辑关系,欣赏源码独特之美,从中学习更为精致的编程思维。 首先,让我们看一下 put 方法的源码: ```java public V put(K ...
在Java中的散列表(如HashMap、HashSet等)中,Hashcode扮演着关键角色。它可以快速地判断两个对象是否相等,从而提高散列表的性能。 证明Hashcode不是内存地址 有人认为Hashcode是对象在内存中的地址,但这是一种...
在Java中,`hashCode()` 方法是 `Object` 类的一个重要成员方法,它返回一个整数,这个整数通常用来表示对象的哈希值。哈希值在Java集合框架中扮演着至关重要的角色,尤其是在散列表(如 `HashMap` 和 `Hashtable`)...
面试中,可能会被问及HashMap的性能优化、内存占用分析、以及在特定场景下的选择,如并发环境、内存敏感的应用等。 总结,HashMap是Java编程中的基础工具,掌握其工作原理和常见面试题,不仅能帮助我们应对面试,更...
在自定义类中,为了使对象能被HashSet或HashMap正确处理,通常需要重写hashCode()和equals()方法,确保它们遵循一致性原则。 在ArrayList和HashSet的比较中,我们可以总结以下几点: 1. 数据结构:ArrayList基于...
- **集合框架**:在 `HashSet`, `HashMap`, `Hashtable` 等集合中,`hashCode` 方法用于快速查找和存储对象。 - **缓存机制**:在缓存中,`hashCode` 和 `equals` 方法一起用于识别缓存项,以便在需要时快速找到它们...
put 方法是 HashMap 中最重要的方法之一,它负责将键值对添加到 HashMap 中。put 方法的实现可以分为以下几个步骤: 1. 首先,根据键的 hashCode 值计算 Hash 码,Hash 码是用于确定键值对在数组中的索引。 2. 然后...