原文出处:http://www.cnblogs.com/chenpi/p/5280304.html

以下内容基于jdk1.7.0_79源码;

什么是HashMap

基于哈希表的一个Map接口实现,存储的对象是一个键值对对象(Entry<K,V>);

HashMap补充说明

基于数组和链表实现,内部维护着一个数组table,该数组保存着每个链表的表头结点;查找时,先通过hash函数计算hash值,再根据hash值计算数组索引,然后根据索引找到链表表头结点,然后遍历查找该链表;

HashMap数据结构

画了个示意图,如下,左边的数组索引是根据hash值计算得到,不同hash值有可能产生一样的索引,即哈希冲突,此时采用链地址法处理哈希冲突,即将所有索引一致的节点构成一个单链表;

HashMap继承的类与实现的接口

Map接口,方法的含义很简单,基本上看个方法名就知道了,后面会在HashMap源码分析里详细说明

AbstractMap抽象类中定义的方法

HashMap源码分析,大部分都加了注释

package java.util;
import java.io.*; public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{ /**
* 默认初始容量,默认为2的4次方 = 16
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 /**
* 最大容量,默认为2的30次方
*/
static final int MAXIMUM_CAPACITY = 1 << 30; /**
* 默认负载因子,默认为0.75
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f; /**
*当数组表还没扩容的时候,一个共享的空表对象
*/
static final Entry<?,?>[] EMPTY_TABLE = {}; /**
* 数组表,大小可以改变,且大小必须为2的幂
*/
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE; /**
* 当前Map中key-value映射的个数
*/
transient int size; /**
* 下次扩容阈值,当size > capacity * load factor时,开始扩容
*/
int threshold; /**
* 负载因子
*/
final float loadFactor; /**
* Hash表结构性修改次数,用于实现迭代器快速失败行为
*/
transient int modCount; /**
* 容量阈值,默认大小为Integer.MAX_VALUE
*/
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE; /**
* 静态内部类Holder,存放一些只能在虚拟机启动后才能初始化的值
*/
private static class Holder { /**
* 容量阈值,初始化hashSeed的时候会用到该值
*/
static final int ALTERNATIVE_HASHING_THRESHOLD; static {
//获取系统变量jdk.map.althashing.threshold
String altThreshold = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"jdk.map.althashing.threshold")); int threshold;
try {
threshold = (null != altThreshold)
? Integer.parseInt(altThreshold)
: ALTERNATIVE_HASHING_THRESHOLD_DEFAULT; // jdk.map.althashing.threshold系统变量默认为-1,如果为-1,则将阈值设为Integer.MAX_VALUE
if (threshold == -1) {
threshold = Integer.MAX_VALUE;
}
//阈值需要为正数
if (threshold < 0) {
throw new IllegalArgumentException("value must be positive integer.");
}
} catch(IllegalArgumentException failed) {
throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
} ALTERNATIVE_HASHING_THRESHOLD = threshold;
}
} /**
* 计算hash值的时候需要用到
*/
transient int hashSeed = 0; /**
* 生成一个空的HashMap,并指定其容量大小和负载因子
*
*/
public HashMap(int initialCapacity, float loadFactor) {
//保证初始容量大于等于0
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
//保证初始容量不大于最大容量MAXIMUM_CAPACITY
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY; //loadFactor小于0或为无效数字
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
//负载因子
this.loadFactor = loadFactor;
//下次扩容大小
threshold = initialCapacity;
init();
} /**
* 生成一个空的HashMap,并指定其容量大小,负载因子使用默认的0.75
*
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
} /**
* 生成一个空的HashMap,容量大小使用默认值16,负载因子使用默认值0.75
*/
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
} /**
* 根据指定的map生成一个新的HashMap,负载因子使用默认值,初始容量大小为
* Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY)
*/
public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
inflateTable(threshold); putAllForCreate(m);
} //返回>=number的最小2的n次方值,如number=5,则返回8
private static int roundUpToPowerOf2(int number) {
// assert number >= 0 : "number must be non-negative";
return number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
} /**
* 对table扩容
*/
private void inflateTable(int toSize) {
// Find a power of 2 >= toSize
//找一个值(2的n次方,且>=toSize)
int capacity = roundUpToPowerOf2(toSize); //下次扩容阈值
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1); table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
} // internal utilities void init() {
} /**
* 初始化hashSeed
*/
final boolean initHashSeedAsNeeded(int capacity) {
boolean currentAltHashing = hashSeed != 0;
boolean useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean switching = currentAltHashing ^ useAltHashing;
if (switching) {
hashSeed = useAltHashing
? sun.misc.Hashing.randomHashSeed(this)
: 0;
}
return switching;
} /**
* 生成hash值
*/
final int hash(Object k) {
int h = hashSeed; //如果key是字符串,调用un.misc.Hashing.stringHash32生成hash值
//Oracle表示能生成更好的hash分布,不过这在jdk8中已删除
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
//一次散列,调用k的hashCode方法,与hashSeed做异或操作
h ^= k.hashCode(); // This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
//二次散列,
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
} /**
* 返回hash值的索引,采用除模取余法,h & (length-1)操作 等价于 hash % length操作, 但&操作性能更优
*/
static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
} /**
* 返回key-value映射个数
*/
public int size() {
return size;
} /**
* 判断map是否为空
*/
public boolean isEmpty() {
return size == 0;
} /**
* 返回指定key对应的value
*/
public V get(Object key) {
//key为null情况
if (key == null)
return getForNullKey(); //根据key查找节点
Entry<K,V> entry = getEntry(key); //返回key对应的值
return null == entry ? null : entry.getValue();
} /**
* 查找key为null的value,注意如果key为null,则其hash值为0,默认是放在table[0]里的
*/
private V getForNullKey() {
if (size == 0) {
return null;
}
//在table[0]的链表上查找key为null的键值对,因为null默认是存在table[0]的桶里
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null)
return e.value;
}
return null;
} /**
*判断是否包含指定的key
*/
public boolean containsKey(Object key) {
return getEntry(key) != null;
} /**
* 根据key查找键值对,找不到返回null
*/
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
//如果key为null,hash值为0,否则调用hash方法,对key生成hash值
int hash = (key == null) ? 0 : hash(key); //调用indexFor方法生成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;
} /**
* 向map存入一个键值对,如果key已存在,则覆盖
*/
public V put(K key, V value) {
//数组为空,对数组扩容
if (table == EMPTY_TABLE) {
inflateTable(threshold);
} //对key为null的键值对调用putForNullKey处理
if (key == null)
return putForNullKey(value); //生成hash值
int hash = hash(key); //生成hash值索引
int i = indexFor(hash, table.length); //查找是否有key“相等”的键值对,有的话覆盖
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++; //在指定hash值索引处的链表上增加该键值对
addEntry(hash, key, value, i);
return null;
} /**
* 存放key为null的键值对,存放在索引为0的链表上,已存在的话,替换
*/
private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
//已存在key为null,则替换
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
//操作次数加一,用于迭代器快速失败行为
modCount++;
//在指定hash值索引处的链表上增加该键值对
addEntry(0, null, value, 0);
return null;
} /**
* 添加键值对
*/
private void putForCreate(K key, V value) {
//生成hash值
int hash = null == key ? 0 : hash(key); //生成hash值索引,
int i = indexFor(hash, table.length); /**
* key“相等”,则替换
*/
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
e.value = value;
return;
}
}
//在指定索引处的链表上创建该键值对
createEntry(hash, key, value, i);
} //将制定map的键值对添加到map中
private void putAllForCreate(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
putForCreate(e.getKey(), e.getValue());
} /**
* 对数组扩容
*/
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, initHashSeedAsNeeded(newCapacity)); //table索引替换成新数组
table = newTable; //重新计算阈值
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
} /**
* 拷贝旧的键值对到新的哈希表中
*/
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
//遍历旧的数组
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
//根据新的数组长度,重新计算索引,
int i = indexFor(e.hash, newCapacity); //插入到链表表头
e.next = newTable[i]; //将e放到索引为i处
newTable[i] = e; //将e设置成下个节点
e = next;
}
}
} /**
* 将制定map的键值对put到本map,key“相等”的直接覆盖
*/
public void putAll(Map<? extends K, ? extends V> m) {
int numKeysToBeAdded = m.size();
if (numKeysToBeAdded == 0)
return; //空map,扩容
if (table == EMPTY_TABLE) {
inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
} /*
* 判断是否需要扩容
*/
if (numKeysToBeAdded > threshold) {
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
if (targetCapacity > MAXIMUM_CAPACITY)
targetCapacity = MAXIMUM_CAPACITY;
int newCapacity = table.length;
while (newCapacity < targetCapacity)
newCapacity <<= 1;
if (newCapacity > table.length)
resize(newCapacity);
} //依次遍历键值对,并put
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
} /**
* 移除指定key的键值对
*/
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
} /**
* 移除指定key的键值对
*/
final Entry<K,V> removeEntryForKey(Object key) {
if (size == 0) {
return null;
}
//计算hash值及索引
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length); Entry<K,V> prev = table[i];
Entry<K,V> e = prev; //头节点为table[i]的单链表上执行删除节点操作
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;
} /**
* 删除指定键值对对象(Entry对象)
*/
final Entry<K,V> removeMapping(Object o) {
if (size == 0 || !(o instanceof Map.Entry))
return null; Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
Object key = entry.getKey();
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;
//找到节点
if (e.hash == hash && e.equals(entry)) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
} return e;
} /**
* 清空map,将table数组所有元素设为null
*/
public void clear() {
modCount++;
Arrays.fill(table, null);
size = 0;
} /**
* 判断是否含有指定value的键值对
*/
public boolean containsValue(Object value) {
if (value == null)
return containsNullValue(); Entry[] tab = table;
//遍历table数组
for (int i = 0; i < tab.length ; i++)
//遍历每条单链表
for (Entry e = tab[i] ; e != null ; e = e.next)
if (value.equals(e.value))
return true;
return false;
} /**
* 判断是否含有value为null的键值对
*/
private boolean containsNullValue() {
Entry[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (e.value == null)
return true;
return false;
} /**
* 浅拷贝,键值对不复制
*/
public Object clone() {
HashMap<K,V> result = null;
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// assert false;
}
if (result.table != EMPTY_TABLE) {
result.inflateTable(Math.min(
(int) Math.min(
size * Math.min(1 / loadFactor, 4.0f),
// we have limits...
HashMap.MAXIMUM_CAPACITY),
table.length));
}
result.entrySet = null;
result.modCount = 0;
result.size = 0;
result.init();
result.putAllForCreate(this); return result;
} //内部类,节点对象,每个节点包含下个节点的引用
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
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;
}
//获取节点的key
public final K getKey() {
return key;
}
//获取节点的value
public final V getValue() {
return value;
} //设置新value,并返回旧的value
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
} //判断key和value是否相同,两个都“相等”,返回true
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();
} /**
* This method is invoked whenever the value in an entry is
* overwritten by an invocation of put(k,v) for a key k that's already
* in the HashMap.
*/
void recordAccess(HashMap<K,V> m) {
} /**
* This method is invoked whenever the entry is
* removed from the table.
*/
void recordRemoval(HashMap<K,V> m) {
}
} /**
* 添加新节点,如有必要,执行扩容操作
*/
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);
} /**
* 插入单链表表头
*/
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++;
} //hashmap迭代器
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; // 下个键值对索引
int expectedModCount; // 用于判断快速失败行为
int index; // current slot
Entry<K,V> current; // current entry HashIterator() {
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
} public final boolean hasNext() {
return next != null;
} final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException(); if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
} public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount;
}
} //ValueIterator迭代器
private final class ValueIterator extends HashIterator<V> {
public V next() {
return nextEntry().value;
}
}
//KeyIterator迭代器
private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}
////KeyIterator迭代器
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
} // 返回迭代器方法
Iterator<K> newKeyIterator() {
return new KeyIterator();
}
Iterator<V> newValueIterator() {
return new ValueIterator();
}
Iterator<Map.Entry<K,V>> newEntryIterator() {
return new EntryIterator();
} // Views private transient Set<Map.Entry<K,V>> entrySet = null; /**
* 返回一个set集合,包含key
*/
public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet()));
} private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
} /**
* 返回一个value集合,包含value
*/
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
} private final class Values extends AbstractCollection<V> {
public Iterator<V> iterator() {
return newValueIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsValue(o);
}
public void clear() {
HashMap.this.clear();
}
} /**
* 返回一个键值对集合
*/
public Set<Map.Entry<K,V>> entrySet() {
return entrySet0();
} private Set<Map.Entry<K,V>> entrySet0() {
Set<Map.Entry<K,V>> es = entrySet;
return es != null ? es : (entrySet = new EntrySet());
} private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return newEntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<K,V> e = (Map.Entry<K,V>) o;
Entry<K,V> candidate = getEntry(e.getKey());
return candidate != null && candidate.equals(e);
}
public boolean remove(Object o) {
return removeMapping(o) != null;
}
public int size() {
return size;
}
public void clear() {
HashMap.this.clear();
}
} /**
* map序列化,可实现深拷贝
*/
private void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
// Write out the threshold, loadfactor, and any hidden stuff
s.defaultWriteObject(); // Write out number of buckets
if (table==EMPTY_TABLE) {
s.writeInt(roundUpToPowerOf2(threshold));
} else {
s.writeInt(table.length);
} // Write out size (number of Mappings)
s.writeInt(size); // Write out keys and values (alternating)
if (size > 0) {
for(Map.Entry<K,V> e : entrySet0()) {
s.writeObject(e.getKey());
s.writeObject(e.getValue());
}
}
} private static final long serialVersionUID = 362498820763181265L; /**
* 反序列化,读取字节码转为对象
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read in the threshold (ignored), loadfactor, and any hidden stuff
s.defaultReadObject();
if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
throw new InvalidObjectException("Illegal load factor: " +
loadFactor);
} // set other fields that need values
table = (Entry<K,V>[]) EMPTY_TABLE; // Read in number of buckets
s.readInt(); // ignored. // Read number of mappings
int mappings = s.readInt();
if (mappings < 0)
throw new InvalidObjectException("Illegal mappings count: " +
mappings); // capacity chosen by number of mappings and desired load (if >= 0.25)
int capacity = (int) Math.min(
mappings * Math.min(1 / loadFactor, 4.0f),
// we have limits...
HashMap.MAXIMUM_CAPACITY); // allocate the bucket array;
if (mappings > 0) {
inflateTable(capacity);
} else {
threshold = capacity;
} init(); // Give subclass a chance to do its thing. // Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < mappings; i++) {
K key = (K) s.readObject();
V value = (V) s.readObject();
putForCreate(key, value);
}
} // These methods are used when serializing HashSets
int capacity() { return table.length; }
float loadFactor() { return loadFactor; }
}
}

【JAVA集合】HashMap源码分析(转载)的更多相关文章

  1. 【Java】HashMap源码分析——常用方法详解

    上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...

  2. 【Java】HashMap源码分析——基本概念

    在JDK1.8后,对HashMap源码进行了更改,引入了红黑树.在这之前,HashMap实际上就是就是数组+链表的结构,由于HashMap是一张哈希表,其会产生哈希冲突,为了解决哈希冲突,HashMa ...

  3. [转载] Java集合---HashMap源码剖析

    转载自http://www.cnblogs.com/ITtangtang/p/3948406.html 一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射 ...

  4. Java集合---HashMap源码剖析

    一.HashMap概述二.HashMap的数据结构三.HashMap源码分析     1.关键属性     2.构造方法     3.存储数据     4.调整大小 5.数据读取           ...

  5. Java中HashMap源码分析

    一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...

  6. Java入门系列之集合HashMap源码分析(十四)

    前言 我们知道在Java 8中对于HashMap引入了红黑树从而提高操作性能,由于在上一节我们已经通过图解方式分析了红黑树原理,所以在接下来我们将更多精力投入到解析原理而不是算法本身,HashMap在 ...

  7. java.util.HashMap源码分析

    在java jdk8中对HashMap的源码进行了优化,在jdk7中,HashMap处理“碰撞”的时候,都是采用链表来存储,当碰撞的结点很多时,查询时间是O(n). 在jdk8中,HashMap处理“ ...

  8. java集合-HashMap源码解析

    HashMap 键值对集合 实现原理: HashMap 是基于数组 + 链表实现的. 通过hash值计算 数组索引,将键值对存到该数组中. 如果多个元素hash值相同,通过链表关联,再头部插入新添加的 ...

  9. Java集合框架源码分析(2)LinkedList

    链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...

  10. Java集合-LinkedList源码分析

    目录 1.数据结构-链表 2.ArrayList结构特性 3.构造方法 4.成员变量 5.常用的成员方法 6.Node节点 7.序列化原理 8.迭代器 9.总结 1.数据结构-链表 链表(Linked ...

随机推荐

  1. Oracle数据库sys和system用户的默认密码及如何修改密码

    新安装好的Oracle数据库sys用户默认密码为change_on_install,system用户默认密码为manager. 以管理员身份登录的话,在命令行中输入 sqlplus sys/chang ...

  2. 【Caffe 测试】Training LeNet on MNIST with Caffe

    Training LeNet on MNIST with Caffe We will assume that you have Caffe successfully compiled. If not, ...

  3. HDU 2298 Toxophily

    题目: Description The recreation center of WHU ACM Team has indoor billiards, Ping Pang, chess and bri ...

  4. 关于一个WCF调用的服务端和客户端的配置信息集合

    客户端的配置我知道. 但是: httpTransport maxReceivedMessageSize="2147483647" <dataContractSerialize ...

  5. 配置nginx如果获取不到图片 去另外一台服务器获取

    配置nginx服务器从一台服务器如果获取不到图片 从另外一台服务器中获取 location ^~ /uploads/ { root /data/weiwend/weiwang; try_files $ ...

  6. Yii 将对象转化成数组

    将从数据库查找的对象,转换成数组,并且以设定属性键名称,用到ArrayHelper::toArray $posts = Post::find()->limit(10)->all(); $d ...

  7. Java工作队列和线程池

    背景    最近的需要做一个与设备通信的web项目.当然,我们需要写好与设备之间的通信协议(socket).大致的时序逻辑时:当用户用浏览器点击页面某一控件后,它就向后台发送一个post请求,后台解析 ...

  8. java nio之Buffer(一)

    Buffer是一个包装了基本数据元素数组的对象,它以及它的子类定义了一系列API用于处理数据缓存. 一.属性 Buffer有四个基本属性: 1.capacity  容量,buffer能够容纳的最大元素 ...

  9. 【设计模式 - 22】之策略模式(Strategy)

    1      模式简介 在策略模式中,一个类的行为或其算法可以在运行时改变.策略模式定义了一系列算法,把它们一个个封装起来,并且使它们可以互相替换. 策略模式的优点: 1)        算法可以自由 ...

  10. STL algorithm算法merge(34)

    merge原型: std::merge default (1) template <class InputIterator1, class InputIterator2, class Outpu ...