1、EnuMap介紹
鍵的值爲枚舉類型
主要因爲枚舉類型有兩個特徵:一個是他的值是有限的且預先定義的;而是枚舉值都有一個順序,這兩個特徵使得可以更高效的實現Map接口
內部基於數組實現
2、實現原理
內部有以下實例變量:
//表示類型信息
private final Class<K> keyType;
//表示鍵,是所有可能的枚舉值
private transient K[] keyUniverse;
//表示對應的值,對應Enum的順序所對應的值
private transient Object[] vals;
//表示鍵值對的個數
private transient int size = 0;
//EnumMap中可以存放NUll值
private static final Object NULL = new Object() {
public int hashCode() {
return 0;
}
public String toString() {
return "java.util.EnumMap.NULL";
}
};
3、構造方法
public EnumMap(Class<K> keyType) {
this.keyType = keyType;
//以初始化鍵數組
//原理是最終調用枚舉類型的values方法,
// 返回所有可能的枚舉值
keyUniverse = getKeyUniverse(keyType);
//vals爲鍵對應的值存儲的數組;根據鍵的個數確定其所對應數組的大小
vals = new Object[keyUniverse.length];
}
4、put方法
public V put(K key, V value) {
//檢查鍵的類型
typeCheck(key);
//如果類型正確,調用ordinal獲取索引index
int index = key.ordinal();
//並將值value放入數組vals[index]中
Object oldValue = vals[index];
//EnuMap允許值爲null,爲了區別null值與沒有null值,
//EnuMap將null值包裝成一個特殊的對象
//有兩個輔助放大用於null的打包和解包
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}
//如果鍵類型不對,則會拋出異常
private void typeCheck(K key) {
Class<?> keyClass = key.getClass();
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
throw new ClassCastException(keyClass + " != " + keyType);
}
/* @return the ordinal of this enumeration constant
返回鍵在枚舉類中的順序
*/
public final int ordinal() {
return ordinal;
}
5、get方法
public V get(Object key) {
//如果鍵有效,通過ordinal方法獲取索引
//然後直接在值數組vals裏找
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
6、containsValue
public boolean containsValue(Object value) {
//打包
value = maskNull(value);
//遍歷數組進行比較
for (Object val : vals)
if (value.equals(val))
return true;
return false;
}
7、remove方法
public V remove(Object key) {
//對鍵進行檢查:類型檢查
if (!isValidKey(key))
return null;
//獲取待刪除鍵的索引
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null;
if (oldValue != null)
size--;
return unmaskNull(oldValue);
}