1. 程式人生 > >枚舉類的學習

枚舉類的學習

mbo class 集合類 except 記錄 一句話 它的 深入 ati

  我一直不知道枚舉有數量的差別,64個以下(包括)的的枚舉是使用了RegularEnumSet,64個以上的使用了JumboEnumSet。最近看編寫高質量代碼這本書才發現枚舉是有數量的限制,不過其實一般的項目還真用不到一個枚舉類裏面放這麽多的枚舉數量,不過既然學習了我就隨便把它的源碼拿出來看看吧,也彌補一下自己確實在枚舉這一塊的不足。

  原諒我見識少,我竟然不知道有EnumMap和EnumSet枚舉類的集合,這種時候就是學習的機會了。先看一下這個2個集合類的定義:

public class EnumMap<K extends Enum<K>, V> extends
AbstractMap<K, V> implements java.io.Serializable, Cloneable

  我擦,泛型,繼承,實現全都有了,不過也就是一句話,key是枚舉類的Map,666.

public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable

  兩兄弟或兩姐妹(也有可能是兩兄妹,不過這個不重要)一樣是泛型,繼承,實現都有了,這個就是值是泛型的set。感覺好像差不多啊,一看就是一個模子造出來的。。。。。。。

  滾犢子,不要扯那麽多,我們是來學習的。對對對,學習學習。我們主要看一下EnumSet的allOf和noneOf方法,allOf方法:

    public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
        EnumSet<E> result = noneOf(elementType);
        result.addAll();
        return result;
    }

  沒有發現什麽詭異的地方呀,你丫的又在扯犢子吧。一看你就不懂Java代碼的主,我給你解釋一下,這個方法是傳入一個枚舉類,none方法把枚舉類轉換為一個EnumSet<E>,然後在addAll(),然後在返回結果出去。我們看一下allOf方法:

    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);
    }

  當當當,出現了64了,把枚舉枚舉類轉換為數組,然後判斷數組的大小是否小於等於64,如果是的話就使用RegularEnumSet類,大於的話就使用JumboEnumSet。這2個有什麽不同呢,這就有點懵逼的感覺,只能在深入去看看了。先看JumboEnumSet的addAll()方法:

private long elements[];

JumboEnumSet(Class<E>elementType, Enum<?>[] universe) {
    super(elementType, universe);
    elements = new long[(universe.length + 63) >>> 6];
}
void addAll() {
        for (int i = 0; i < elements.length; i++)
            elements[i] = -1;
        elements[elements.length - 1] >>>= -universe.length;
        size = universe.length;
}
 Java把多於64的枚舉一組扯分成了多組,每一組都映射到一個long類型的數字上,然後該數組再放置到elements數組中。long數組可以容納更多的枚舉。
RegularEnumSet的addAll():
private long elements = 0L;// 記錄所有枚舉排序號,註意是long型

RegularEnumSet(Class<E>elementType, Enum<?>[] universe) {//構造
        super(elementType, universe);
}
void addAll() {//加入所有類型
      if (universe.length != 0)
          elements = -1L >>> -universe.length;
}

小於等於64個的Java利用了枚舉的排序值沒有重號和跳號的特點,把每個枚舉的排序號映射到一個long類型的每個位上,把枚舉類映射到一個long類型的變量上。兩者一對比就知道就知道那個性能優了,一個數組一個long類型。所以建議不要使用超過64個枚舉的枚舉類。

枚舉類的學習