hashmap 在开发中用的很多,看下源码实现学习一下,
字段
static final int DEFAULT_INITIAL_CAPACITY = 16;//默认的数组长度
static final int MAXIMUM_CAPACITY = 1 << 30;//最大的数组长度
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认负载比率,数组不会全部填满数据
transient Entry[] table;//hashmap内部也是用数组来存储数据
transient int size;//实际存的数据的个数
int threshold;//实际当前可以存的数据量 = loadFactor*table.length
final float loadFactor; //实际的负载比率
构造方法
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1; //不管你希望的初始长度是多少,系统都是对1做移位运算,最后的结果只能是2的次方
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor); //计算实际容量
table = new Entry[capacity]; // 初始数组
init(); //留给子类实现的一些操作,默认空
}
put方法
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
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;
}
// 首先根据内部的一个hash算法计算出key对应的hash值(防止key本身的hashcode实现很差),再根据这个hash值和表的长度算出一个数组的index值, 然后在数组的该index值上看有没有存东西,东西一不一致(equals),不一致查找entry链表下一个(关于链表下面有说明),直到找到一个null, 就可以确定没有了,然后准备插入
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
entry
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
entry实际上是在实现单向链表结构,每一个entry内部有一个next指向他的后面,所以hashmap的内部数组每个格子存放的是实际上是一个链表的火车头,在最开始的时候table[index]位置上肯定是null,这个就是火车尾了。所以get的时候查找操作是以null为循环终点判断依据的。
在插入的时候把新加的元素替代原来的成为链表火车头,把之前元素的放在新加的火车头后面,
这么做是因为不同的key是有可能算出相同的hash值的,这种情况的时候,他们都会存放在数组的同一个index位置上,相同的hash不同的key的值彼此用链表连接起来,
get
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
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.equals(k)))
return e.value;
}
return null;
}
get的时候就是算出key的hash值,算出数组的index位置,然后到数组的index位置上去遍历链表找到相应的key,如果hash重复的少的话,链表的长度就会很短,hashmap查找的速度就很快了,即使有重复,接下来就是遍历链表,所以要依靠好的算法保证hash重复的概率小,缩短链表的长度
假如2个对象的key最后算出来的index值一样呢, 就是这2个对象存在一条链表上, 那么get的时候会不会拿错了呢
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
看这行代码就知道了, 链表上的实体存了自己的key的, 所以即使不同的实体是放在一个index上,也可以通过不同的key来区分的
分享到:
相关推荐
在IT行业中,哈希表(HashMap)是一种高效的数据结构,它使用哈希函数将键(Key)映射到数组的特定位置,以便快速存取数据。...通过阅读和分析源代码,我们可以学习如何在实际项目中应用哈希表,提高数据操作的效率。
HashMap源码深度剖析,面试必备
HashMap源码(JDK1.7,含注释)
HashMap的部分源码解析
hashmap源码,可以看看http://blog.csdn.net/wabiaozia/article/details/50684556
HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...
HashMap源码流程图 一图解析HashMap源码流程 // 默认的HashMap中数组的长度 16 static final int DEFAULT_INITIAL_CAPACITY = 1 ; // aka 16 // HashMap中的数组的最大容量 static final int MAXIMUM_CAPACITY = 1 ...
精确的版本号是jdk-7u80。想不通,竟然很多人都收费,这个明明可以在安装JDK的目录中找到啊!自己下一个JDK就可以得到。
HashMap是Java编程语言中最常用的集合类之一,它提供了一种基于键值对(key-value pair)的数据存储方式,具有高效查找、插入和删除操作。...对于学习者来说,阅读源码并结合实践是掌握HashMap的最好方式。
HashMap 是 Java 中最常用的集合类之一,它是基于哈希表实现的,提供了高效的数据存取功能。HashMap 的核心原理是将键(key)通过哈希函数转化为数组...理解HashMap的内部机制对于优化代码性能和避免潜在问题非常重要。
精确的版本号是jdk-8u181。想不通,竟然很多人都收费,这个明明可以在安装JDK的目录中找到啊!自己下一个JDK就可以得到。
java代码-使用java解决手写hashMap的源代码 ——学习参考资料:仅用于个人学习使用!
本人源码阅读理解, 基于jdk1.7 和jdk 1.8的java HashMap源码的理解, 希望对你理解java源码有作用
在Java编程语言中,HashMap是集合框架中一个重要的类,用于存储键值对的数据结构。面试中,HashMap的源码分析与实现是一个常见的考察点,...深入学习和实践HashMap源码,能够帮助我们更好地理解和优化Java应用程序。
哈希映射(HashMap)是Java编程语言中广泛使用的...了解这些实现细节对于优化代码性能和避免潜在问题至关重要。在实际编程中,应充分考虑哈希冲突的处理、负载因子的选择以及预估容量的设定,以提高HashMap的使用效率。
在给定的压缩包“易语言源码易语言HashMap类源码.rar”中,包含了易语言实现的HashMap类的源代码。HashMap是一种常见的数据结构,在许多编程语言中都有实现,它提供了快速的键值对存储和查找功能。 HashMap类是基于...
本文将深入探讨HashMap的源码,解析其内部实现机制,包括底层数据结构、哈希冲突解决、1.7和1.8版本的区别、扩容机制以及红黑树的左右旋操作。 首先,HashMap的底层数据结构是一个动态调整大小的位桶数组(bucket ...