17,序列化writeObject(ObjectOutputStream s)
18,反序列化readObject(ObjectInputStream s)
13,转换成 Set/CollectionkeySet()
keySet()
方法,获得 key Set 。代码如下:
public Set<K> keySet() {
Set<K> ks = keySet; // 获得 keySet 缓存
if (ks == null) { // 如果不存在,则进行创建
ks = new KeySet();
keySet = ks;
}
return ks;
}
14,获得 value 集合values()
values()
方法,获得 value 集合。代码如下:
public Collection<V> values() {
Collection<V> vs = values; // 获得 vs 缓存
if (vs == null) {
vs = new Values(); // 如果不存在,则进行创建
values = vs;
}
return vs;
}
15,获得 key-value Se entrySet()
entrySet()
方法,获得 key-value Set 。代码如下:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es; // 获得 entrySet 缓存
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es; // 如果不存在,则进行创建
}
16,清空clear()
clear()
方法,清空 HashMap 。代码如下:
public void clear() {
Node<K,V>[] tab;
modCount++; // 增加修改次数
if ((tab = table) != null && size > 0) {
size = 0; // 设置大小为 0
for (int i = 0; i < tab.length; ++i)
tab[i] = null; // 设置每个位置为 null
}
}
17,序列化writeObject(ObjectOutputStream s)
writeObject(ObjectOutputStream s)
方法,序列化 HashMap 对象。代码如下:
private void writeObject(java.io.ObjectOutputStream s)
throws IOException {
int buckets = capacity(); // 获得 HashMap table 数组大小
// Write out the threshold, loadfactor, and any hidden stuff
s.defaultWriteObject(); // 写入非静态属性、非 transient 属性
s.writeInt(buckets); // 写入 table 数组大小
s.writeInt(size); // 写入 key-value 键值对数量
internalWriteEntries(s); // 写入具体的 key-value 键值对
}
final int capacity() { // table 数组大小。封装方法的原因,需要考虑 table 未初始化的情况。
return (table != null) ? table.length :
(threshold > 0) ? threshold :
DEFAULT_INITIAL_CAPACITY;
}
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
Node<K,V>[] tab;
if (size > 0 && (tab = table) != null) {
for (int i = 0; i < tab.length; ++i) { // 遍历 table 数组
for (Node<K,V> e = tab[i]; e != null; e = e.next) { // 遍历链表或红黑树
s.writeObject(e.key);
s.writeObject(e.value);
}
}
}
}
18,反序列化readObject(ObjectInputStream s)
readObject(ObjectInputStream s)
方法,反序列化成 HashMap 对象。代码如下:
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read in the threshold (ignored), loadfactor, and any hidden stuff// 读取非静态属性、非 transient 属性
s.defaultReadObject();
reinitialize();
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new InvalidObjectException("Illegal load factor: " +
loadFactor);
s.readInt(); // Read and ignore number of buckets
int mappings = s.readInt(); // Read number of mappings (size)
if (mappings < 0)
throw new InvalidObjectException("Illegal mappings count: " +
mappings);
else if (mappings > 0) { // (if zero, use defaults)
// Size the table using given load factor only if within
// range of 0.25...4.0
float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
float fc = (float)mappings / lf + 1.0f;
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
DEFAULT_INITIAL_CAPACITY :
(fc >= MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY :
tableSizeFor((int)fc));
float ft = (float)cap * lf;
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);
// Check Map.Entry[].class since it's the nearest public type to
// what we're actually creating.
SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, cap);
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
table = tab;
// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < mappings; i++) {
@SuppressWarnings("unchecked")
K key = (K) s.readObject();
@SuppressWarnings("unchecked")
V value = (V) s.readObject();
putVal(hash(key), key, value, false, false);
}
}
}
void reinitialize() {
table = null;
entrySet = null;
keySet = null;
values = null;
modCount = 0;
threshold = 0;
size = 0;
}
19,克隆clone()
clone()
方法,克隆 HashMap 对象。代码如下:
@SuppressWarnings("unchecked")
@Override
public Object clone() {
HashMap<K,V> result; // 克隆 HashMap 对象
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
result.reinitialize(); // 重新初始化
result.putMapEntries(this, false); // 批量添加 key-value 键值对到其中
return result; // 返回 result
}