-
static final Entry<?,?>[] EMPTY_TABLE = {};
-
/**
-
* The table, resized as necessary. Length MUST Always be a power of two.
-
*/
-
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
-
/**
-
* The number of key-value mappings contained in this map.
-
*/
-
transient int size;
-
/**
-
* The next size value at which to resize (capacity * load factor).
-
* @serial
-
*/
-
// If table == EMPTY_TABLE then this is the initial capacity at which the
-
// table will be created when inflated.
-
int threshold;
下面讲解几个比较重要的方法
1)当我们进行put操作的时候
先贴出源码
[java] view plain copy
-
public V put(K key, V value) {
-
if (key == null)
-
return putForNullKey(value); //处理null值
-
int hash = hash(key.hashCode());//计算hash
-
int i = indexFor(hash, table.length);//计算在数组中的存储位置
-
//遍历table[i]位置的链表,查找相同的key,若找到则使用新的value替换掉原来的oldValue并返回oldValue
-
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;
-
}
-
}
-
//若没有在table[i]位置找到相同的key,则添加key到table[i]位置,新的元素总是在table[i]位置的第一个元素,原来的元素后移
-
modCount++;
-
addEntry(hash, key, value, i);
-
return null;
-
}
a HashMap会对null值key进行特殊处理,总是放到table[0]位置
b计算has值
c 找到在table数组中的索引
1)遍历table[i]位置的链表,查找相同的key,若找到则使用新的value替换掉原来的oldValue并返回oldValue
2)若没有在table[i]位置找到相同的key,则添加key到table[i]位置,新的元素总是在table[i]位置的第一个元素,原来的元素后调用addEntry方法
[java] view plain copy
-
void addEntry(int hash, K key, V value, int bucketIndex) {
-
if ((size >= threshold) && (null != table[bucketIndex])) {
-
resize(2 * table.length);
-
hash = (null != key) ? hash(key) : 0;
-
bucketIndex = indexFor(hash, table.length);
-
}
-
createEntry(hash, key, value, bucketIndex);
-
}
[java] view plain copy
-
void createEntry(int hash, K key, V value, int bucketIndex) {
-
Entry<K,V> e = table[bucketIndex];
-
table[bucketIndex] = new Entry<>(hash, key, value, e);
-
size++;
-
}
所做的工作就是:
1)判断当元素数量达到临界值(capactiy*factor)时,则进行扩容,是table数组长度变为table.length*2
2)当table[index]已存在其它元素时,会在table[index]位置形成一个链表,将新添加的元素放在table[index],原来的元素通过Entry的next进行链接,这样以链表形式解决hash冲突问题,
**2)get方法
**同样当key为null时会进行特殊处理,在table[0]的链表上查找key为null的元素
[java] view plain copy
-
public V get(Object key) {
-
if (key == null)
-
return getForNullKey();
-
Entry<K,V> entry = getEntry(key);
-
return null == entry ? null : entry.getValue();
-
}
get的过程是先计算hash然后通过hash与table.length取摸计算index值,然后遍历table[index]上的链表,直到找到key,
然后返回,找不到返回null
[java] view plain copy
-
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;
-
}
3)remove方法
remove方法和put get类似,计算hash,计算index,然后遍历查找,将找到的元素从table[index]链表移除
[java] view plain copy
-
public V remove(Object key) {
-
Entry<K,V> e = removeEntryForKey(key);
-
return (e == null ? null : e.value);
-
}
[java] view plain copy
-
final Entry<K,V> removeEntryForKey(Object key) {
-
if (size == 0) {
-
return null;
-
}
-
int hash = (key == null) ? 0 : hash(key);
-
int i = indexFor(hash, table.length);
-
Entry<K,V> prev = table[i];
-
Entry<K,V> e = prev;
-
while (e != null) {
-
Entry<K,V> next = e.next;
-
Object k;
-
if (e.hash == hash &&
-
((k = e.key) == key || (key != null && key.equals(k)))) {
-
modCount++;
-
size–;
-
if (prev == e)
-
table[i] = next;
-
else
-
prev.next = next;
-
e.recordRemoval(this);
-
return e;
-
}
-
prev = e;
-
e = next;
-
}
-
return e;
-
}
4)clear()方法
clear方法非常简单,就是遍历table然后把每个位置置为null,同时修改元素个数为0
需要注意的是clear方法只会清楚里面的元素,并不会重置capactiy
[java] view plain copy
-
public void clear() {
-
modCount++;
-
Arrays.fill(table, null);
-
size = 0;
-
}
5)containsKey和containsValue
containsKey方法是先计算hash然后使用hash和table.length取摸得到index值,遍历table[index]元素查找是否包含key相同的值
[java] view plain copy
-
public boolean containsKey(Object key) {
-
return getEntry(key) != null;
-
}
[java] view plain copy
-
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;
-
}
6)containsValue方法就比较粗暴了,就是直接遍历所有元素直到找到value,由此可见HashMap的containsValue方法本质上和普通数组和list的contains方法没什么区别,你别指望它会像containsKey那么高效
[java] view plain copy
-
public boolean containsValue(Object value) {
-
// Same idea as size()
-
if (value == null)
-
throw new NullPointerException();
-
final Segment<K,V>[] segments = this.segments;
-
boolean found = false;
-
long last = 0;
-
int retries = -1;
-
try {
-
outer: for (;😉 {
-
if (retries++ == RETRIES_BEFORE_LOCK) {
-
for (int j = 0; j < segments.length; ++j)
-
ensureSegment(j).lock(); // force creation
-
}
-
long hashSum = 0L;
-
int sum = 0;
-
for (int j = 0; j < segments.length; ++j) {
-
HashEntry<K,V>[] tab;
-
Segment<K,V> seg = segmentAt(segments, j);
-
if (seg != null && (tab = seg.table) != null) {
-
for (int i = 0 ; i < tab.length; i++) {
-
HashEntry<K,V> e;
-
for (e = entryAt(tab, i); e != null; e = e.next) {
-
V v = e.value;
-
if (v != null && value.equals(v)) {
-
found = true;
-
break outer;
-
}
-
}
-
}
-
sum += seg.modCount;
-
}
-
}
-
if (retries > 0 && sum == last)
-
break;
-
last = sum;
-
}
-
} finally {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
sum += seg.modCount;
-
}
-
}
-
if (retries > 0 && sum == last)
-
break;
-
last = sum;
-
}
-
} finally {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-4eDyxO4H-1710968938036)]
[外链图片转存中…(img-wZ23ilYn-1710968938037)]
[外链图片转存中…(img-kUPwECqi-1710968938037)]
[外链图片转存中…(img-PIuIKT9h-1710968938038)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-RbLb7tyi-1710968938038)]