在Map中key-value组合成Map.Entry对象存放,所有的Entry存放在数组table中
/** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
HashMap中Entry的结构如下:
final K key; V value; Entry<K,V> next; int hash;
可以看出,相同hashCode的key会以链表的形式存放在table的同一个slot中。
HashMap中可以存放null,null存放在table[0]中
/** * Offloaded version of put for null keys */ private V putForNullKey(V value) { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return null; }
从此可以看出,在HashMap中,null只会有一个value。
public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
从put方法可以看出,相同hashCode的所有key占用同一个slot,并以链表的形式存在。
public V get(Object key) { if (key == null) return getForNullKey(); Entry<K,V> entry = getEntry(key); return null == entry ? null : entry.getValue(); } final Entry<K,V> getEntry(Object key) { if (size == 0) { return null; } int hash = (key == null) ? 0 : hash(key); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } return null; }
从get方法可以看出,如果(k = e.key) == key,即是同一个对象的引用(不管该对象是否在put后发生变化,这是通过equals方法的结果可能不同了)都会去除e.key中的e.value。否则就需要调用它们的equals方法来判断是否相同。
相关推荐
9. ** equals() 和 hashCode()**:插入HashMap的键对象必须正确地重写`equals()`和`hashCode()`方法,以确保键的比较逻辑与哈希码的计算一致,否则可能会导致预期之外的行为。 10. **resize()**:当HashMap达到其...
HashMap的put逻辑(1.7) .svg
- 自定义键类时,确保正确实现equals()和hashCode()方法,以确保对象的比较逻辑和哈希计算一致。 - 选择合适的初始容量(initialCapacity)和负载因子,以优化HashMap的性能。初始容量越大,扩容次数越少,但内存...
### Hashtable与HashMap的区别 在Java编程语言中,`Hashtable`和`HashMap`是两种非常重要的数据结构,它们都属于`Map`接口的实现类,用于存储键值对数据。尽管两者在功能上相似,但在实际应用中却存在显著差异。 #...
HASHMap迭代集合的例子好用,逻辑算法
在"ListDemo"这个文件中,可能包含了实现以上逻辑的具体代码。通过分析和运行这个示例,我们可以更深入地理解如何利用HashMap来构建一个简单但功能齐全的游戏排名系统。这涉及到HashMap的基本操作、Stream API的使用...
### Java使用WebService读取HashMap里的数值 ...这种做法不仅适用于简单的数据交换场景,还能够扩展到更复杂的业务逻辑处理中。对于开发者而言,理解和掌握这一技术是构建稳定可靠的分布式系统的基石之一。
在本文中,我们将对 HashMap 的 put 方法的源码进行详细解读,分析put 方法源码中的内在逻辑关系,欣赏源码独特之美,从中学习更为精致的编程思维。 首先,让我们看一下 put 方法的源码: ```java public V put(K ...
- **参数检查**:首先对传入的`initialCapacity`和`loadFactor`进行有效性检查,确保它们符合逻辑要求。 - **确定容量**:为了提高散列表的性能,`HashMap`要求容量必须为2的幂。因此,这里通过循环左移的方式找到...
HashMap允许将null作为键或值,但考虑到性能和逻辑清晰度,通常避免这样做。作为一种非线程安全的数据结构,HashMap非常适合单线程环境下的快速访问需求。如果在多线程环境中使用,需要额外的同步措施来确保数据的...
这段代码的核心逻辑在于通过散列函数和数组索引将键值对映射到数组的某个位置上。如果多个键值对散列到了同一个位置,则它们会被存储为一个链表。 ##### 源码分析 下面是一段简化的 `put` 方法源码示例,用于展示...
《手写HashMap源码解析——深入理解数据结构与算法》 HashMap是Java编程语言中一个常用的集合类,它提供了一种高效、灵活的键值对存储方式。在面试过程中,尤其是2020年及以后的技术面试中,深入理解HashMap的实现...
1. "mind reader.txt":这可能是一个关于理解HashMap内部工作机制的文档,帮助读者像读心术一样理解其内部逻辑。 2. "HashMap in Java with Examples.pdf":这显然是一份详细阐述Java中HashMap的教程,很可能包含了...
`get`方法的逻辑类似,也是通过哈希码找到数组位置,然后遍历链表找到对应的键值对。 HashMap的性能和效率依赖于良好的哈希函数。哈希函数应尽可能使得不同键值的哈希码分布均匀,减少冲突。虽然这里没有给出具体的...
通过实现Comparable接口,我们能够自定义对象的比较规则,进而实现特定的排序逻辑,这对于数据处理和分析场景非常有用。同时,理解HashMap内部如何利用Comparable接口进行排序也是优化代码性能的关键。
Java HashMap 遍历和删除元素方法小结 Java HashMap 是一种常用的数据结构,用于存储键值对儿,但是在遍历和删除元素时,需要注意一些特殊的情况,否则可能会出现异常或错误。本文将介绍 Java HashMap 遍历和删除...
MyCartBO.java 是一个用于实现购物车逻辑的业务对象,该类中定义了一个 HashMap 来存放用户想买的商品信息,键是商品的 ID,值是商品的数量。该类中还定义了一些方法来实现添加、删除、修改和查看购物车的逻辑。 在...
7. **重构逻辑**:一旦理解了HashMap的实现,可以尝试重构或模拟这个逻辑,以达到特定目的,如绕过安全检查、篡改数据或分析漏洞。 在这个过程中,音乐学家方大刚可能分享了一些独特的技巧或方法,帮助听众更高效地...
在实际应用中,双关键字HashMap可以用于处理多维度的数据索引,例如在数据库查询优化、地理信息系统或复杂业务逻辑中。同时,自定义的HashMap实现也可以帮助我们更好地控制内存占用和性能,满足特定场景下的需求。 ...