JDK - HashMap
来源:互联网 发布:中万网络工资怎么样 编辑:程序博客网 时间:2024/05/21 09:57
HashMap是以数组的形式存放,存放内容的方式,根据当前key的(经过特殊处理)hashCode来决定,当前对象存储的位置。获取值时在通过(经过特殊处理)hashCode进行取值,而不需要遍历总个数组来获取,这也就是为什么hashMap性能高的原因。
但值得注意的一点就是,hashCode不一定会唯一,而这时怎么做到的,这也就是为什么称HashMap 为 链表散列,因为在数组里面存储的是一个Entry(内部类) 对象 ,对像其中有一个Entry<K,V> next的对象,这个对象就是最新的,hashCode相冲突的保存到这个对象最后,这个是无尽的。
而我们怎么才能使HashMap性能达到最大化了,首先得说他怎么存储,在存储过程中会做哪些处理,和对源码的分析。
一. 抓住会影响到性能的点
第一个性能点resize() ,当我们使用默认的HashMap 时分配的空间时(16), 当我们超过时threshold =(DEFAULT_INITIAL_CAPACITY(16) * DEFAULT_LOAD_FACTOR(0.75f)),
if (size++ >= threshold)
会重新分配空间(2 * table.length),然后将以前内容,通过hashCode重新指定存储位置。所以在当我们知道的大概大小的情况下,不使用默认 new HashMap(),而是用new HashMap(length);
下面是主要JDK源码
1.
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;
}
2.
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);
}
3.
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);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
TestHashMap.java 可执行文件
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unchecked")
public class TestHashMap<K,V> {
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int MAXIMUM_CAPACITY = 1 << 30;
int threshold;
final float loadFactor;
transient int size;
transient Entry[] table;
public TestHashMap() {
table = new Entry[DEFAULT_INITIAL_CAPACITY];
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
public static void main(String[] args) {
TestHashMap hashMap = new TestHashMap();
System.out.println(hashMap.put("123", "asdasd"));
System.out.println(hashMap.get("123"));
new HashMap();
}
public V put(K key,V 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;
return oldValue;
}
}
this.addEntry(hash,key, value,i);
return value;
}
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;
}
private V getForNullKey() {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null)
return e.value;
}
return null;
}
private void addEntry(int hash,K key,V value,int bucketIndex) {
Entry e = table[bucketIndex];
table[bucketIndex] = new Entry<K, V>(hash,key,value,e);
if (size ++ >= threshold) {
resize(table.length * 2);
}
}
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);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}
static int indexFor(int h, int length) {
return h & (length-1);
}
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
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;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
}
}
- JDK - HashMap
- jdk:HashMap
- jdk-HashMap
- JDK HashMap源代码分析
- JDK HashMap源代码分析
- JDK源码-HashMap
- 【JDK】:HashMap详解
- JDK源码之-HashMap
- JDK源代码阅读:HashMap
- JDK源码-HashMap
- JDK源码学习之HashMap
- JDK——HashMap实现
- jdk集合源码之HashMap
- jdk:HashSet基于HashMap实现
- JDK的HashMap源码解读
- JDK源码阅读之 HashMap
- jdk源码分析之HashMap
- jdk源码分析之HashMap
- presentModalViewControllerAnimated 和 dismissModalViewControllerAnimated
- 71道经典Android面试题和答案
- jquery 鼠标点击挪动div实现
- 关于递归原理
- Web发布cab文件打包的ActiveX控件总结
- JDK - HashMap
- 【使用指南】风起亚洲(Fengqi.Asia)上手指南
- jm86之get_block() 1/4亮度像素内插详述
- <fmt:formatDate 的显示格式
- 敏捷开发(转)
- 点击鼠标在textarea中光标当前位置插入指定字符
- IK-analyzer添加搜狗词库
- Oracle RAC的GES/GCS原理 (转)
- C++ How To Program整理(1)