2014年10月13日星期一

HashMap其实就那么一回事儿之源码浅析 - 南轲梦

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
HashMap其实就那么一回事儿之源码浅析 - 南轲梦  阅读原文»

  上篇文章《LinkedList其实就那么一回事儿之源码分析》介绍了LinkedList, 本次将为大家介绍HashMap。

  在介绍HashMap之前,为了方便更清楚地理解源码,先大致说说HashMap的实现原理, HashMap 是基于数组 + 链表实现的, 首先HashMap就是一个大数组,在这个数组中,通过hash值去寻对应位置的元素, 如果遇到多个元素的hash值一样,那么怎么保存,这就引入了链表,在同一个hash的位置,保存多个元素(通过链表关联起来)。HashMap 所实现的基于<key, value>的键值对形式,是由其内部内Entry实现。 好啦,简单讲完HashMap的实现原理后,就开始正式分析源码啦:

public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{

//默认的HashMap的空间大小16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

//hashMap最大的空间大小
static final int MAXIMUM_CAPACITY = 1 << 30;

//HashMap默认负载因子,负载因子越小,hash冲突机率越低,至于为什么,看完下面源码就知道了
static final float DEFAULT_LOAD_FACTOR = 0.75f;

static final Entry<?,?>[] EMPTY_TABLE = {};

//table就是HashMap实际存储数组的地方
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

//HashMap 实际存储的元素个数
transient int size;

//临界值(即hashMap 实际能存储的大小),公式为(threshold = capacity * loadFactor)
int threshold;

//HashMap 负载因子
final float loadFactor;



//HashMap的(key -> value)键值对形式其实是由内部类Entry实现,那么此处就先贴上这个内部类
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
//保存了对下一个元素的引用,说明此处为链表
//为什么此处会用链表来实现?
//其实此处用链表是为了解决hash一致的时候的冲突
//当两个或者多个hash一致的时候,那么就将这两个或者多个元素存储在一个位置,用next来保存对下个元素的引用
Entry<K,V> next;
int hash;

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;
}

public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e
= (Map.Entry)o;
Object k1
= getKey();
Object k2
= e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1
= getValue();
Object v2
= e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}

public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}

public final String toString() {
return getKey() + "=" + getValue();
}


void recordAccess(HashMap<K,V> m) {
}


void recordRemoval(HashMap<K,V> m) {
}
}
//以上是内部类Entry

//构造方法, 设置HashMap的loadFactor 和 threshold, 方法极其简单,不多说
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: " +
JavaScript垃圾回收(二)――垃圾回收算法 - pwstrick  阅读原文»

【摘要】一、引用计数(Reference Counting)算法 Internet Explorer 8以下的DOM和BOM使用COM组件所以是引用计数来为DOM对象处理内存,引用计数的含义是跟踪记录每个值被引用的次数。形象点说: 1)房子里有很多便签纸,这些纸就好比是内存。如下图: 2)使用内存... 阅读全文

阅读更多内容

没有评论:

发表评论