set与mapUS现金盘平台出租[ haozbbs.com ](http://haozbbs.com)Q1446595067 有非常大的关联。简单地说,把map的所有key拿出来就是一个set集合。map集合相当于一个存入了很多个key-value对象的set集合。相对应,set集合也可以如此扩展为map集合。
HashSet和HashMap都是利用Hash算法来决定(key的)存储位置,而map集合的value是紧跟着key存储的。
HashSet和HashMap对集合元素的存储方式
HashMap源码中的put方法
//threshold:键值对数量的极限值
//size:键值对的数量
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
* 将制定的值与此映射中的指定键关联。如果已经存在以前的映射,则替换旧值
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
//根据key计算hash值
int hash = hash(key);
//找到在table中对应的索引
int i = indexFor(hash, table.length);
//如果该索引位置的Entry不是null,就遍历该索引位置的全部Entry
for (HashMap.Entry<K, V> e = table[i]; e != null; e = e.next) {
Object k;
//hashCode相同则说明储存位置相同;
// 再通过equals比较,如果相同,则覆盖原有value,并返回原有value。如果都不相同,则循环结束后执行addEntry方法
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
//如果索引i位置的Entry为null,调用addEntry方法
addEntry(hash, key, value, i);
return null;
}
//addEntry方法主要用来在需要的时候扩充table的大小,每次扩充一倍。然后调用了createEntry方法
/**
* Like addEntry except that this version is used when creating entries
* as part of Map construction or "pseudo-construction" (cloning,
* deserialization). This version needn't worry about resizing the table.
*
* Subclass overrides this to alter the behavior of HashMap(Map),
* clone, and readObject.
*/
void createEntry(int hash, K key, V value, int bucketIndex) {
//拿到制定索引处的Entry
HashMap.Entry<K,V> e = table[bucketIndex];
//在索引处放入新的Entry,并且新的Entry指向原来的Entry,没有则指向null
table[bucketIndex] = new HashMap.Entry<>(hash, key, value, e);
//map中键值对的数量
size++;
}
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient HashMap.Entry<K,V>[] table = (HashMap.Entry<K,V>[]) EMPTY_TABLE;
可以看到,table是一个数组,长度只能是2的n次方。在HashMap的一个构造方法中,系统会对构造时制定的容量大小做调整。所以创建HashMap时将初始容量设置为2的n次方,会减少系统计算开销。