/**
* 一个空的entry数组,桶 的默认值
*/
static final Entry<?,?>[] EMPTY_TABLE = {};
/**
* 桶,按需调整大小,但必须是2的次幂
*/
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
/**
* 默认初始化容量,必须为2的次幂The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* 最大容量,如果通过构造函数参数中传递初始化容量大于该最大容量了,也会使用该容量为初始化容量 * 必须是2的次幂且小于等于2的30次方 */
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 默认的负载因子,可以通过构造函数指定
*/
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中键值对的数量,在每次新增或删除的时候都会对size进行+1或者-1操作.
*/
transient int size;
/**
* 负载值,需要调整大小的临界值,为:(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;
/**
* 负载因子,如果构造函数中没有指定,则采用默认的负载因子,
*
* @serial
*/
final float loadFactor;
/**
* HashMap结构修改次数,结构修改时改变HashMap中的映射数量或修改其内部结构(例如,* rehash方法,重建内部数据结构),此字段用于在 * HashMap的集合视图上生成的迭代器都处理成快速失败的
*/
transient int modCount;
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) { // 如果容量已达最大限制,则设置下负载值后直接返回
threshold = Integer.MAX_VALUE;
return;
}
// 创建新的table存储数据
Entry[] newTable = new Entry[newCapacity];
// 将旧table中的数据转存到新table中去,这一步会花费比较多的时间
transfer(newTable, initHashSeedAsNeeded(newCapacity));
table = newTable;
// 最后设置下下次调整大小的负载值
threshold = (int) Math.min(newCapacity * loadFactor,
MAXIMUM_CAPACITY + 1);
}
/**
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
* (16) and the default load factor (0.75).
*/
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity.
* @throws IllegalArgumentException if the initial capacity is negative.
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
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);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
/**
* 在此映射中关联指定值与指定建。如果该映射以前包含了一个该键的映射关系,则旧值被替换
*
* @param 指定将要关联的键
* @param 指定将要关联的值
* @return 与key关联的旧值,如果key没有任何映射关系,则返回null(返回null还可能表示该映射之前将null与key关联)
*/
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
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;
}
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++;
}
/**
* Entry构造方法,创建一个新的Entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
/**
* 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回null
* 返回null值并不一定表明该映射不包含该键的映射,也可能改映射将该键显示的映射为null,可使用containsKey操作来区分这两种情况
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
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;
}
class User {
// 身份证号码
protected int idNumber;
public User(int id){
idNumber = id;
}
}
public class TestUser{
public static void main(String[] args) {
Map<User, String> map = new HashMap<User, String>();
for (int i=0; i<5; i++) {
map.put(new User(i), "姓名: " + i);
}
System.out.println("User3 的姓名:" + map.get(new User(3)));
}
}
输出:
User3 的姓名:null
class User {
// 身份证号码
protected int idNumber;
public User(int id){
idNumber = id;
}
@Override
public int hashCode() {
return idNumber;
}
@Override
public boolean equals(Object obj) {
return obj instanceof User && (idNumber==((User)obj).idNumber);
}
}
public class TestUser{
public static void main(String[] args) {
Map<User, String> map = new HashMap<User, String>();
for (int i=0; i<5; i++) {
map.put(new User(i), "姓名: " + i);
}
System.out.println("User3 的姓名:" + map.get(new User(3)));
}
}
输出:
User3 的姓名:姓名: 3
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有