I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0
          1.EnumSet示例及核心源碼分析

          package com.landon.mavs.example.collection;

          import java.util.EnumSet;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;

          import com.landon.mavs.example.collection.EnumMapExample.NBA;

          /**
           * 
           * EnumSet example
           * 
           * <pre>
           * 1.public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
           *     implements Cloneable, java.io.Serializable
           * 2.其內部元素為枚舉,另外可以看到其是一個抽象類abstract
           * 3.其在內部表示為位向量,足以用作傳統上基于 int 的“位標志”的替換形式.(即類似0x1000000,按bit存儲,用位運算進行相關操作)
           * 4. 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以內則返回RegularEnumSet,否則JumboEnumSet
           * 5.從其內部API方法看,全部是靜態方法static.
           * 6.以RegularEnumSet內部方法實現:
           * public boolean add(E e) {
           *         typeCheck(e);
           *         // elements默認為0
           *         long oldElements = elements;
           *         elements |= (1L << ((Enum)e).ordinal());
           *         return elements != oldElements;
           *     }
           *  從add源碼上看:1.取枚舉值的ordinal,初始為0. 2.1 << ordinal 3.與elements做|運算
           *  舉例:a.添加ordinal為0,則計算后elements為1
           *     b.添加ordinal為1,則計算后elements為(10 | 01) = 11
           *     c.添加ordinal為2,則計算后elements為(011 | 100) = 111
           *   ->所以從源碼上看,其就是用一個long來存儲枚舉.你懂得(long是64位).
           *   
           *   public boolean contains(Object e) {
           *         if (e == null)
           *             return false;
           *         Class eClass = e.getClass();
           *         if (eClass != elementType && eClass.getSuperclass() != elementType)
           *             return false;
           * 
           *         return (elements & (1L << ((Enum)e).ordinal())) != 0;
           *     }
           *     從contains源碼上看:最重要的是最好一句:(elements & (1L << ((Enum)e).ordinal())) != 0
           *         1.1L << ((Enum)e).ordinal()
           *         2.與elements做&運算
           *        舉例:如果ordinal為2,則通過第一步計算值為4(100) & 111(之前已經添加過ordinal為2的元素,高位至1)
           *        ->則高位肯定為1,則表示有這個元素
           *         總結:利用一個long和位運算實現EnumSet的快速存儲和判斷.
           *  7.至于JumboEnumSet的內部實現:則是用一個long elements[]實現,只是對long的擴展,其實現細節差不太多,這里不詳述了
           * </pre>
           * 
           * @author landon
           * 
           
          */

          public class EnumSetExample {
              
          private static final Logger LOGGER = LoggerFactory
                      .getLogger(EnumSetExample.class);

              
          public static void main(String[] args) {
                  
          // allOf:一個包含指定元素類型的所有元素的枚舉 set
                  EnumSet<NBA> allofEnumSet = EnumSet.allOf(NBA.class);
                  
          // [allofEnumSet:[MAVS, LAKERS, PACERS]]
                  LOGGER.debug("allofEnumSet:{}", allofEnumSet);

                  
          // noneOf:創建一個具有指定元素類型的空枚舉 set
                  EnumSet<NBA> noneofEnumSet = EnumSet.noneOf(NBA.class);
                  
          // 添加一個元素
                  noneofEnumSet.add(NBA.LAKERS);
                  
          // [noneofEnumSet:[LAKERS]]
                  LOGGER.debug("noneofEnumSet:{}", noneofEnumSet);

                  
          // complementOf:取補
                  EnumSet<NBA> complementOfEnumSet = EnumSet.complementOf(noneofEnumSet);
                  
          // [[complementOfEnumSet:[MAVS, PACERS]]
                  LOGGER.debug("complementOfEnumSet:{}", complementOfEnumSet);

                  
          // copyof:拷貝
                  EnumSet<NBA> copyofEnumSet = EnumSet.copyOf(complementOfEnumSet);
                  
          // [copyofEnumSet:[MAVS, PACERS]]
                  LOGGER.debug("copyofEnumSet:{}", copyofEnumSet);

                  
          // of(E e):最初包含指定元素的枚舉 set
                  EnumSet<NBA> ofEnumSet = EnumSet.of(NBA.PACERS);
                  LOGGER.debug("ofEnumSet:{}", ofEnumSet);

                  
          // of(E first,E rest)
                  NBA[] nbas = new NBA[] { NBA.LAKERS, NBA.MAVS, NBA.PACERS };
                  EnumSet<NBA> ofEnumSet2 = EnumSet.of(NBA.PACERS, nbas);
                  
          // 從輸出可以可以看到:是按照枚舉的ordinal順序輸出的
                  LOGGER.debug("ofEnumSet2:{}", ofEnumSet2);

                  
          // range(E from, E to) [from,to]
                  EnumSet<NBA> rangeEnumSet = EnumSet.range(NBA.MAVS, NBA.PACERS);
                  LOGGER.debug("rangeEnumSet:{}", rangeEnumSet);

                  
          // Exception in thread "main" java.lang.IllegalArgumentException: PACERS
                  
          // > LAKERS
                  
          // 拋出了異常,所以from和to的順序不能顛倒(按照枚舉的ordinal順序)
                  EnumSet<NBA> rangeEnumSet2 = EnumSet.range(NBA.PACERS, NBA.LAKERS);
                  LOGGER.debug("rangeEnumSet2:{}", rangeEnumSet2);
              }


          }



          2.EnumMap示例及核心源碼分析

          package com.landon.mavs.example.collection;

          import java.util.Collection;
          import java.util.EnumMap;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;

          /**
           * 
           * EnumMap example
           * 
           * <pre>
           * 1.public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
           *     implements java.io.Serializable, Cloneable
           * 2.可見EnumMap的key是一個枚舉
           * 3.枚舉映射在內部表示為數組 
           * 4. public V put(K key, V value) {
           *         typeCheck(key);
           * 
           *         int index = key.ordinal();
           *         Object oldValue = vals[index];
           *         vals[index] = maskNull(value);
           *         if (oldValue == null)
           *             size++;
           *         return unmaskNull(oldValue);
           *     }
           *     從put的源碼可以看到,是利用Enum的ordinal作為數組的索引.所以實現緊湊且高效
           * </pre>
           * 
           * @author landon
           * 
           
          */

          public class EnumMapExample {
              
          private static final Logger LOGGER = LoggerFactory
                      .getLogger(EnumMapExample.class);

              
          /**
               * 
               * Nba球隊枚舉,分別是小牛,湖人,步行者
               * 
               * @author landon
               * 
               
          */

              
          static enum NBA {
                  MAVS, LAKERS, PACERS,
              }


              
          public static void main(String[] args) {
                  
          // 構造函數public EnumMap(Class<K> keyType),參數表示key類型
                  
          // 泛型只是編譯起作用
                  EnumMap<NBA, String> em = new EnumMap<NBA, String>(NBA.class);

                  
          // put順序不是根據枚舉的ordinal順序
                  em.put(NBA.LAKERS, "kobe");
                  em.put(NBA.MAVS, "dirk");
                  em.put(NBA.PACERS, "miller");

                  
          // get方法會首先檢查參數的class是否valid(與keyTypeClass對比)
                  LOGGER.debug("mavs_player:{}", em.get(NBA.MAVS));
                  
          // 類型檢查失敗則返回null
                  LOGGER.debug("mavs_player:{}", em.get("mavs"));

                  Collection
          <String> values = em.values();
                  
          // 從輸出可以看到,視圖的內部順序是枚舉定義的順序.
                  
          // 輸出em.values:[dirk, kobe, miller]
                  LOGGER.debug("em.values:{}", values.toString());

                  
          // 拋出空指針異常Exception in thread "main" java.lang.NullPointerException
                  
          // 所以key不允許為null
                  em.put(null"tmac");
              }

          }


          posted on 2014-02-03 18:34 landon 閱讀(1650) 評論(0)  編輯  收藏 所屬分類: Program 、Sources
          主站蜘蛛池模板: 阿克苏市| 贡山| 泰和县| 武威市| 札达县| 上饶县| 都匀市| 阜康市| 濉溪县| 淮滨县| 崇左市| 弥勒县| 芒康县| 天全县| 丽江市| 竹山县| 信阳市| 宝清县| 满洲里市| 徐水县| 温宿县| 双柏县| 南昌市| 南涧| 河南省| 大同县| 长武县| 沛县| 铜川市| 定远县| 小金县| 阿克| 滨州市| 志丹县| 壶关县| 原平市| 淮阳县| 井冈山市| 六盘水市| 水城县| 东源县|