目錄
1、add / addAll / addRange / complement
2、 remove / removeAll / clear / retainAll
3、size / contains / containsAll / iterator
1、add / addAll / addRange / complement
2、 remove / removeAll / clear / retainAll
3、size / contains / containsAll / iterator
EnumMap和EnumSet 都是爲key類型爲枚舉的定製集合類,相比直接使用HashMap或者HashSet效率更高,更節省內存佔用,本篇博客就詳細探討其實現細節。HashSet的實現是基於HashMap,HashMap的實現可以參考《java8 HashMap接口實現源碼解析》。
一、EnumMap
1、定義
EnumMap的類繼承關係如下:
其包含的屬性如下:
/**
* K的類型
*/
private final Class<K> keyType;
/**
* 保存K值的數組,根據枚舉類型來初始化,初始完成後不會改變,刪除某個key時只刪除對應的value,key值對應的數組元素不變
*/
private transient K[] keyUniverse;
/**
* 保存V值的數組,與保存K值的數組是一一對應的,可以通過枚舉值的索引即ordinal屬性來訪問,該屬性從0開始
*/
private transient Object[] vals;
/**
* Map的元素個數
*/
private transient int size = 0;
/**
* 表示值爲null的value
*/
private static final Object NULL = new Object() {
public int hashCode() {
return 0;
}
public String toString() {
return "java.util.EnumMap.NULL";
}
};
要求K必須擴展自Enum,即必須是枚舉類型,參考EnumMap的定義,如下:
其構造方法的實現如下:
public EnumMap(Class<K> keyType) {
this.keyType = keyType;
//根據枚舉類型獲取所有的枚舉值
keyUniverse = getKeyUniverse(keyType);
//創建一個跟枚舉值數組長度一樣的value數組
vals = new Object[keyUniverse.length];
}
public EnumMap(EnumMap<K, ? extends V> m) {
//直接賦值
keyType = m.keyType;
keyUniverse = m.keyUniverse;
vals = m.vals.clone();
size = m.size;
}
public EnumMap(Map<K, ? extends V> m) {
if (m instanceof EnumMap) {
//直接賦值
EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
keyType = em.keyType;
keyUniverse = em.keyUniverse;
vals = em.vals.clone();
size = em.size;
} else {
if (m.isEmpty())
throw new IllegalArgumentException("Specified map is empty");
//獲取key值的類型
keyType = m.keySet().iterator().next().getDeclaringClass();
//根據枚舉類型獲取所有的枚舉值
keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];
putAll(m);
}
}
//返回某個枚舉類的所有枚舉值,相當於調用對應枚舉類的values方法
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(keyType);
}
2、put / putAll / get
public V put(K key, V value) {
//檢查key的類型是否指定的枚舉類型keyType
typeCheck(key);
//獲取枚舉值的索引
int index = key.ordinal();
//獲取該索引對應的V
Object oldValue = vals[index];
//賦值
vals[index] = maskNull(value);
if (oldValue == null) //等於null,說明沒有這個key值,size加1
size++;
return unmaskNull(oldValue); //返回原來的值
}
public void putAll(Map<? extends K, ? extends V> m) {
if (m instanceof EnumMap) {
//如果是EnumMap
EnumMap<?, ?> em = (EnumMap<?, ?>)m;
if (em.keyType != keyType) {
if (em.isEmpty())
return;
//key類型不一致,拋出異常
throw new ClassCastException(em.keyType + " != " + keyType);
}
//遍歷所有的key值
for (int i = 0; i < keyUniverse.length; i++) {
//獲取m中對應key的value
Object emValue = em.vals[i];
if (emValue != null) {
if (vals[i] == null) //等於null,說明沒有這個key值,size加1
size++;
vals[i] = emValue; //賦值
}
}
} else {
//m是普通的HashMap,遍歷鍵值對,調用put方法
super.putAll(m);
}
}
public V get(Object key) {
//如果是有效的key值,則獲取對應key值的索引對應的value
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
private void typeCheck(K key) {
Class<?> keyClass = key.getClass();
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
throw new ClassCastException(keyClass + " != " + keyType);
}
private Object maskNull(Object value) {
return (value == null ? NULL : value);
}
@SuppressWarnings("unchecked")
private V unmaskNull(Object value) {
return (V)(value == NULL ? null : value);
}
//是否有效key值
private boolean isValidKey(Object key) {
if (key == null) //key不能爲null
return false;
//判斷key值的類型是否是keyType
Class<?> keyClass = key.getClass();
return keyClass == keyType || keyClass.getSuperclass() == keyType;
}
3、remove / clear
public V remove(Object key) {
if (!isValidKey(key)) //不是有效key,返回null
return null;
//獲取key值索引對應的value
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null; //置爲null
if (oldValue != null) //原來不爲null,說明原來有這個key,則將size減1
size--;
return unmaskNull(oldValue);
}
public void clear() {
//將vals置爲null,注意保存key值的數組keyUniverse沒有變更
Arrays.fill(vals, null);
size = 0;
}
二、EnumSet
1、定義
EnumSet的類繼承關係如下:
注意EnumSet是一個抽象類,不能直接使用,該類有兩個子類,如下:
這兩個子類都是非public的,只能包內訪問。EnumSet.noneOf 方法創建EnumSet實例時會使用這兩個子類,其實現如下:
即枚舉值的個數小於等於64時使用RegularEnumSet,大於64時使用JumboEnumSet。該類包含的屬性如下:
/**
* 枚舉的類型
*/
final Class<E> elementType;
/**
* 枚舉類E的所有枚舉值
*/
final Enum<?>[] universe;
EnumSet定義了多個靜態的工具類方法,其中核心方法如add的實現都留給了子類,下面逐一說明想法方法的實現。
2、noneOf / allOf / of / range
這些方法都是用來創建EnumSet的,noneOf返回一個空的EnumSet,allOf返回一個包含指定枚舉類所有枚舉值的EnumSet,of方法返回一個包含一個或者多個的指定枚舉值的EnumSet,range返回一個包含指定範圍的枚舉值的EnumSet。
//返回一個空的EnumSet
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
//返回一個包含了所有枚舉值的EnumSet
public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
EnumSet<E> result = noneOf(elementType);
//子類實現
result.addAll();
return result;
}
//創建只包含一個指定枚舉值的EnumSet,有多個重載版本,枚舉值從1個到5個
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
//子類實現
result.add(e);
return result;
}
@SafeVarargs
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
EnumSet<E> result = noneOf(first.getDeclaringClass());
result.add(first);
//rest是不定數量的數組,將其中的元素都添加到Set中
for (E e : rest)
result.add(e);
return result;
}
//創建包含指定範圍內的枚舉值的EnumSet
public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
if (from.compareTo(to) > 0)
throw new IllegalArgumentException(from + " > " + to);
EnumSet<E> result = noneOf(from.getDeclaringClass());
//子類實現
result.addRange(from, to);
return result;
}
//返回指定枚舉類的所有枚舉值
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(elementType);
}
測試用例如下:
enum Name{
SHL,
ABC,
DEF,
AVC,
DNG
}
@Test
public void test2() throws Exception {
//返回一個空的EnumSet
EnumSet<Name> names=EnumSet.noneOf(Name.class);
System.out.println(names);
//返回一個包含了所有枚舉值的EnumSet
names=EnumSet.allOf(Name.class);
System.out.println(names);
//返回一個包含了指定枚舉值的EnumSet
names=EnumSet.of(Name.ABC,Name.DEF);
System.out.println(names);
//返回一個包含了指定範圍的枚舉值的EnumSet,起始值都包含
names=EnumSet.range(Name.ABC,Name.AVC);
System.out.println(names);
}
}
輸出如下:
3、copyOf / complementOf
copyOf用於複製指定的EnumSet,complementOf返回原EnumSet中不包含的枚舉值。
public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
return s.clone();
}
public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
if (c instanceof EnumSet) {
//如果是EnumSet
return ((EnumSet<E>)c).clone();
} else {
if (c.isEmpty())
throw new IllegalArgumentException("Collection is empty");
//如果不是EnumSet,則遍歷其中的元素,逐一添加到EnumSet中
Iterator<E> i = c.iterator();
E first = i.next();
EnumSet<E> result = EnumSet.of(first);
while (i.hasNext())
result.add(i.next());
return result;
}
}
//返回的EnumSet中包含了所有的枚舉值
public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
EnumSet<E> result = copyOf(s);
//complement會補齊所有s中不包含的枚舉值,由子類實現
result.complement();
return result;
}
public EnumSet<E> clone() {
try {
//調用Object的clone方法
return (EnumSet<E>) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
測試用例如下:
@Test
public void test3() throws Exception {
EnumSet<Name> names=EnumSet.allOf(Name.class);
System.out.println(names);
EnumSet<Name> names2=EnumSet.copyOf(names);
System.out.println(names2);
names.remove(Name.SHL);
names2.remove(Name.DNG);
System.out.println(names);
System.out.println(names2);
EnumSet<Name> names3=EnumSet.complementOf(names);
System.out.println(names3);
}
其輸出如下:
三、RegularEnumSet
RegularEnumSet適用於枚舉值個數小於等於64的EnumSet,RegularEnumSet定義了一個私有的long類型變量elements,long類型一共64位,如果某一位爲1則表示該位對應的值對應的枚舉值已經添加到RegularEnumSet中了,具體細節參考下面的源碼分析。
1、add / addAll / addRange / complement
RegularEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
}
public boolean add(E e) {
//檢查e的枚舉類型是否指定的類型
typeCheck(e);
//獲取原來的elements值
long oldElements = elements;
//將ordinal對應的位標識爲1,表示添加了對應元素
elements |= (1L << ((Enum<?>)e).ordinal());
//如果不等說明原來不存在e,返回true
return elements != oldElements;
}
void addAll() {
if (universe.length != 0) //將所有枚舉值對應的位都標識爲1
//-1實際就是64個1,注意此處是右移一個負值,實際是右移該負值的補碼的後6位對應的位數,因爲超過6位就大於64了
//以universe.length爲8爲例,-8的補碼的後6位是111000,該值爲56,64個1右移56位的結果就是8個1
elements = -1L >>> -universe.length;
}
public boolean addAll(Collection<? extends E> c) {
if (!(c instanceof RegularEnumSet))
//如果不是RegularEnumSet類型,則通過父類的addAll方法添加,底層是遍歷c中的元素,循環調用add方法
return super.addAll(c);
//如果是RegularEnumSet類型
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType) {
if (es.isEmpty())
return false;
else
//枚舉類型不符,拋出異常
throw new ClassCastException(
es.elementType + " != " + elementType);
}
long oldElements = elements;
//直接或運算,有一個爲1則結果爲1
elements |= es.elements;
//兩者不等說明有添加新的元素了
return elements != oldElements;
}
void addRange(E from, E to) {
//將指定範圍內的位標記爲1,注意此處from.ordinal() - to.ordinal()是一個負值,再減1是爲了將to也包含進來
elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
}
void complement() {
if (universe.length != 0) {
//取非,原來爲1的變成0了,原來爲0的變成1了
elements = ~elements;
//將universe範圍以外的1都置爲0
elements &= -1L >>> -universe.length; // Mask unused bits
}
}
2、 remove / removeAll / clear / retainAll
public boolean remove(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
//不是指定枚舉類,返回false
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
long oldElements = elements;
//將ordinal對應的位置爲0
elements &= ~(1L << ((Enum<?>)e).ordinal());
//如果不等於說明該元素原來是存在的,返回true
return elements != oldElements;
}
public boolean removeAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
//調用父類removeAll,底層遍歷c,循環調用remove方法
return super.removeAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType)
return false; //枚舉類型不符
long oldElements = elements;
//先對es.elements求非,原來的1變成0,再求且,就會將elements中同樣是1的位置爲0了
elements &= ~es.elements;
//如果不等於說明有元素被刪除了
return elements != oldElements;
}
public void clear() {
//置爲0,所有爲1的位都置爲0了
elements = 0;
}
//retainAll求兩者的交集,將不在c中的元素移除,返回true表示有元素被移除了
public boolean retainAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
//調用父類retainAll,遍歷當前集合Set,如果不在c中則移除
return super.retainAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType) {
//枚舉類型不符,將當前元素全部清空
//不等於0說明原來的RegularEnumSet非空,此處清除了,發生修改了,返回true
boolean changed = (elements != 0);
elements = 0;
return changed;
}
//枚舉類型一致
long oldElements = elements;
//兩者求且,如果某個元素在elements存在而在es.elements中不存在則將elements中對應位置爲0,實現刪除的效果
elements &= es.elements;
return elements != oldElements;
}
3、size / contains / containsAll / iterator
public int size() {
//統計位爲1的位的總數,比如bitCount(8)返回1,bitCount(3)返回2
return Long.bitCount(elements);
}
public boolean contains(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false; //枚舉類型不符,返回false
//判斷ordinal對應的位是否爲0,爲0表示不存在
return (elements & (1L << ((Enum<?>)e).ordinal())) != 0;
}
public boolean containsAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
//調用父類的containsAll,遍歷c中的元素,如果有一個在當前Set中不存在則返回false
return super.containsAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType) //枚舉類型不符,如果c是空的則返回true
return es.isEmpty();
//elements求反後跟 es.elements 求且,如果結果爲0,說明c中的元素都在當前Set中,返回true
return (es.elements & ~elements) == 0;
}
public Iterator<E> iterator() {
return new EnumSetIterator<>();
}
private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
/**
* 當前elements
*/
long unseen;
/**
* 上一次返回的枚舉值對應位爲1的值,比如上一次返回的枚舉值的ordinal爲4,則lastReturned的後8位爲00010000
*/
long lastReturned = 0;
EnumSetIterator() {
unseen = elements;
}
public boolean hasNext() {
return unseen != 0;
}
@SuppressWarnings("unchecked")
public E next() {
if (unseen == 0)
throw new NoSuchElementException();
//unseen是奇數時,求且爲1,是偶數時,求且是一個2的整數次冪
lastReturned = unseen & -unseen;
//遍歷一個位對應的枚舉值,就通過減法,將對應位置爲0
unseen -= lastReturned;
return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
}
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
//將對應的位置爲0
elements &= ~lastReturned;
lastReturned = 0;
}
}
四、JumboEnumSet
JumboEnumSet適用於枚舉值個數大於64個的枚舉類,其底層實現跟RegularEnumSet一樣都是根據位是否爲1來判斷該枚舉值是否添加到了Set中,不過因爲枚舉值個數大於64個,無法用64位的long類型來記錄所有的枚舉值,所以將RegularEnumSet中long類型的elements改成了一個long類型數組,添加某個枚舉值時,先將某個枚舉值的ordinal屬性除以64,算出該枚舉值所屬的elements數組索引,再用ordinal屬性對64求餘,將對應的位標識位1,詳情參考下面的源碼分析。
1、add / addAll / addRange / complement
JumboEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
//加上63的目的是爲了對64整除後算出來的值能包含原來的
//以70爲例,64整除的結果是1,1*64 小於原來的70,如果加上63,則整除的結果是2,大於原來的70
elements = new long[(universe.length + 63) >>> 6];
}
public boolean add(E e) {
//檢查e的枚舉類型是否合法
typeCheck(e);
int eOrdinal = e.ordinal();
//左移6位就是除以64,算出該枚舉所屬的elements數組索引
int eWordNum = eOrdinal >>> 6;
//獲取原來的值
long oldElements = elements[eWordNum];
//eOrdinal的值是大於64的,此處右移,實際移動的位數是eOrdinal對64求餘的結果
//比如eOrdinal的值是68,1L<<68的結果就是1<<4,10000
elements[eWordNum] |= (1L << eOrdinal);
//判斷原elements數組索引的元素是否發生改變,如果改變則說明添加的枚舉值原來不存在
boolean result = (elements[eWordNum] != oldElements);
if (result) //爲true說明添加了一個新元素,size加1
size++;
return result;
}
void addAll() {
//遍歷所有的數組元素,將值置爲-1,-1時所有位都是1
for (int i = 0; i < elements.length; i++)
elements[i] = -1;
//最後一個數組元素不是所有位都是1的,只有universe.length對64求餘的結果對應的位置爲1,所以需要右移將其他的位置爲0
//以70爲例,對64求餘的結果就是6,-70的補碼的後6位是111010,即58,64個1右移58後還剩6個1
elements[elements.length - 1] >>>= -universe.length;
size = universe.length;
}
void addRange(E from, E to) {
int fromIndex = from.ordinal() >>> 6;
int toIndex = to.ordinal() >>> 6;
//如果起始枚舉值位於同一個數組元素中
if (fromIndex == toIndex) {
elements[fromIndex] = (-1L >>> (from.ordinal() - to.ordinal() - 1))
<< from.ordinal();
} else {
//起始枚舉值不在同一個數組元素中
//此處是左移,將低於from的位都置爲0
elements[fromIndex] = (-1L << from.ordinal());
//將fromIndex + 1到toIndex-1之間的數組元素都置爲-1,所有位變成1
for (int i = fromIndex + 1; i < toIndex; i++)
elements[i] = -1;
//將to之前的低位都置爲1
elements[toIndex] = -1L >>> (63 - to.ordinal());
}
//注意調用addRange時,JumboEnumSet是空的,所以此處直接賦值size
size = to.ordinal() - from.ordinal() + 1;
}
void complement() {
//遍歷所有數組元素,取非,原來爲0的位變成1,原來爲1的位變成0
for (int i = 0; i < elements.length; i++)
elements[i] = ~elements[i];
//處理最後一個數組元素,將多餘的位都置爲0
elements[elements.length - 1] &= (-1L >>> -universe.length);
//總長度減去原來的長度
size = universe.length - size;
}
2、 remove / removeAll / clear / retainAll
public boolean remove(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false; //元素類型不符,返回false
//對64整除,算出所屬的數組索引
int eOrdinal = ((Enum<?>)e).ordinal();
int eWordNum = eOrdinal >>> 6;
//將對應的數組元素的對應位置爲0
long oldElements = elements[eWordNum];
elements[eWordNum] &= ~(1L << eOrdinal);
boolean result = (elements[eWordNum] != oldElements);
if (result) //如果改變說明原來是有這個枚舉值的,size減1
size--;
return result;
}
public boolean removeAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
//調用父類removeAll,底層是遍歷c,調用remove方法
return super.removeAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType)
return false; //元素類型不符,返回false
//遍歷當前Set,先對es.elements[i]求非,將原來爲1的位變成0,再和elements[i]求且,
//實現將位於es.elements[i]中的元素都從elements[i]中移除了
for (int i = 0; i < elements.length; i++)
elements[i] &= ~es.elements[i];
//重新計算size,返回size是否改變
return recalculateSize();
}
public boolean retainAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
//調用父類retainAll,底層是遍歷當前Set,如果不在c中則將其移除
return super.retainAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType) {
//元素類型不一致,將當前Set清空
boolean changed = (size != 0);
clear();
return changed;
}
//遍歷當前Set,兩者的數組元素求且,不在es.elements[i]中的位就會被置爲0,實現元素移除的效果
for (int i = 0; i < elements.length; i++)
elements[i] &= es.elements[i];
//重新計算size,返回size是否改變
return recalculateSize();
}
public void clear() {
//所有元素都置爲0
Arrays.fill(elements, 0);
size = 0;
}
//重新計算size,並返回size是否發生改變
private boolean recalculateSize() {
int oldSize = size;
size = 0;
for (long elt : elements)
//遍歷elements,累加位爲1的總數
size += Long.bitCount(elt);
//如果size發生改變,說明有刪除元素了,返回true
return size != oldSize;
}
3、size / contains / containsAll / iterator
public int size() {
return size;
}
public boolean contains(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false; //枚舉類型不符,返回false
int eOrdinal = ((Enum<?>)e).ordinal();
//判斷對應數組元素的對應位是否爲0,如果是則說明不存在,返回false,否則返回true
return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0;
}
public boolean containsAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
//調用父類containsAll,遍歷c,如果有一個元素不在當前Set中,則返回false
return super.containsAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType) //元素類型不符
return es.isEmpty();
for (int i = 0; i < elements.length; i++)
//elements[i]先求非,原來爲1的位變成0,再求且,如果結果不爲0,說明某個元素在
//elements[i]中不存在,在es.elements[i]中存在,即c中某個元素不在當前Set中,返回false
if ((es.elements[i] & ~elements[i]) != 0)
return false;
return true;
}
public Iterator<E> iterator() {
return new EnumSetIterator<>();
}
private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
/**
* 當前遍歷的elements元素
*/
long unseen;
/**
當前遍歷的elements數組索引
*/
int unseenIndex = 0;
/**
* 上一次返回的爲1的位
*/
long lastReturned = 0;
/**
* The index corresponding to lastReturned in the elements array.
*/
int lastReturnedIndex = 0;
EnumSetIterator() {
unseen = elements[0];
}
@Override
public boolean hasNext() {
//遍歷找到下一個數組元素不爲0的數組元素
while (unseen == 0 && unseenIndex < elements.length - 1)
unseen = elements[++unseenIndex];
return unseen != 0;
}
@Override
@SuppressWarnings("unchecked")
public E next() {
if (!hasNext())
throw new NoSuchElementException();
//邏輯同RegularEnumSet
lastReturned = unseen & -unseen;
lastReturnedIndex = unseenIndex;
unseen -= lastReturned;
return (E) universe[(lastReturnedIndex << 6)
+ Long.numberOfTrailingZeros(lastReturned)];
}
@Override
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
final long oldElements = elements[lastReturnedIndex];
//對應的位置爲0
elements[lastReturnedIndex] &= ~lastReturned;
if (oldElements != elements[lastReturnedIndex]) {
size--;
}
lastReturned = 0;
}
}