Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 314|回复: 0

[集合学习]实现HashMap的例子

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-2 23:56:37 | 显示全部楼层 |阅读模式
    实现HashMap的例子,关键字为long类型,来自jive2.5
       
    1. package com.cache;
    2. public final class LongHashMap {   
    3.     protected long table[];
    4.     protected Object values[];
    5.     protected byte state[];   
    6.     protected int freeEntries;
    7.     //The number of distinct associations in the map; its "size()".
    8.     protected int distinct;   
    9.     protected int lowWaterMark;
    10.     protected int highWaterMark;
    11.     //The minimum load factor for the hashtable.
    12.     protected double minLoadFactor;
    13.     //The maximum load factor for the hashtable.
    14.     protected double maxLoadFactor;
    15.     protected static final int DEFAULT_CAPACITY = 277;
    16.     protected static final double DEFAULT_MIN_LOAD_FACTOR = 0.2;
    17.     protected static final double DEFAULT_MAX_LOAD_FACTOR = 0.6;
    复制代码

       
      
    1.     protected static final byte FREE = 0;
    2.     protected static final byte FULL = 1;
    3.     protected static final byte REMOVED = 2;

    4.     /**
    5.      * Constructs an empty map with default capacity and default load factors.
    6.      */
    7.     public LongHashMap() {
    8.         this(DEFAULT_CAPACITY);
    9.     }
    10.     /**
    11.      * Constructs an empty map with the specified initial capacity and default
    12.      * load factors.
    13.      *
    14.      * @param      initialCapacity   the initial capacity of the map.
    15.      * @throws     IllegalArgumentException if the initial capacity is less
    16.      *             than zero.
    17.      */
    18.     public LongHashMap(int initialCapacity) {
    19.         this(initialCapacity, DEFAULT_MIN_LOAD_FACTOR, DEFAULT_MAX_LOAD_FACTOR);
    20.     }

    21.     public LongHashMap(int initialCapacity, double minLoadFactor, double maxLoadFactor) {
    22.         setUp(initialCapacity,minLoadFactor,maxLoadFactor);
    23.     }
    24.    
    25.     public void clear() {
    26.         for (int i=0; i< state.length; i++) {
    27.             state[i] = FREE;
    28.         }
    29.         for (int i=0; i< values.length-1; i++) {
    30.             values[i] = null;
    31.         }
    32.         this.distinct = 0;
    33.         this.freeEntries = table.length; // delta
    34.         trimToSize();
    35.     }
    36.     public boolean containsKey(long key) {
    37.         return indexOfKey(key) >= 0;
    38.     }
    39.    
    40.     public boolean containsValue(Object value) {
    41.         return indexOfValue(value) >= 0;
    42.     }
    43.   
    44.     public void ensureCapacity(int minCapacity) {
    45.         if (table.length < minCapacity) {
    46.             int newCapacity = nextPrime(minCapacity);
    47.             rehash(newCapacity);
    48.         }
    49.     }
    50.    
    51.     public final Object get(long key) {
    52.         int i = indexOfKey(key);
    53.         //If not in the map return null
    54.         if (i<0) {
    55.             return null;
    56.         }
    57.         else {
    58.             return values[i];
    59.         }
    60.     }
    61.   
    62.     private final int indexOfInsertion(long key) {
    63.         final long tab[] = table;
    64.         final byte stat[] = state;
    65.         final int length = tab.length;
    66.         final int hash = ((int)(key ^ (key >> 32))) & 0x7FFFFFFF;
    67.         int i = hash % length;
    68.         // double hashing, see http://www.eece.unm.edu/faculty/heileman/hash/node4.html
    69.         int decrement = (hash) % (length-2);
    70.         //OLD CODE: int decrement = (hash / length) % length;
    71.         if (decrement == 0) decrement = 1;
    72.         // stop if we find a removed or free slot, or if we find the key itself
    73.         // do NOT skip over removed slots (yes, open addressing is like that...)
    74.         while (stat[i] == FULL && tab[i] != key) {
    75.         i -= decrement;
    76.             //hashCollisions++;
    77.             if (i<0) i+=length;
    78.         }
    79.         if (stat[i] == REMOVED) {
    80.             // stop if we find a free slot, or if we find the key itself.
    81.             // do skip over removed slots (yes, open addressing is like that...)
    82.             // assertion: there is at least one FREE slot.
    83.             int j = i;
    84.             while (stat[i] != FREE && (stat[i] == REMOVED || tab[i] != key)) {
    85.                 i -= decrement;
    86.                 //hashCollisions++;
    87.                 if (i< 0) i+=length;
    88.             }
    89.             if (stat[i] == FREE) i = j;
    90.         }
    91.         if (stat[i] == FULL) {
    92.             // key already contained at slot i.
    93.             // return a negative number identifying the slot.
    94.             return -i-1;
    95.         }
    96.         // not already contained, should be inserted at slot i.
    97.         // return a number >= 0 identifying the slot.
    98.         return i;
    99.     }
    100.    
    101.     private final int indexOfKey(long key) {
    102.         final long tab[] = table;
    103.         final byte stat[] = state;
    104.         final int length = tab.length;
    105.         final int hash = ((int)(key ^ (key >> 32))) & 0x7FFFFFFF;
    106.         int i = hash % length;
    107.         // double hashing, see http://www.eece.unm.edu/faculty/heileman/hash/node4.html
    108.         int decrement = (hash) % (length-2);
    109.         //OLD CODE: int decrement = (hash / length) % length;
    110.         if (decrement == 0) decrement = 1;
    111.         // stop if we find a free slot, or if we find the key itself.
    112.         // do skip over removed slots (yes, open addressing is like that...)
    113.         while (stat[i] != FREE && (stat[i] == REMOVED || tab[i] != key)) {
    114.             i -= decrement;
    115.             //hashCollisions++;
    116.             if (i<0) i+=length;
    117.         }
    118.         if (stat[i] == FREE) return -1; // not found
    119.         return i; //found, return index where key is contained
    120.     }
    121.     /**
    122.      * @param value the value to be searched in the receiver.
    123.      * @return the index where the value is contained in the receiver,
    124.      *      returns -1 if the value was not found.
    125.      */
    126.     protected int indexOfValue(Object value) {
    127.         final Object val[] = values;
    128.         final byte stat[] = state;
    129.         for (int i=stat.length; --i >= 0;) {
    130.             if (stat[i]==FULL && val[i]==value) return i;
    131.         }
    132.         return -1; // not found
    133.     }
    134.     /**
    135.      * Returns the first key the given value is associated with.
    136.      *
    137.      * @param value the value to search for.
    138.      * @return the first key for which holds get(key) == value;
    139.      *                   returns Long.MIN_VALUE if no such key exists.
    140.      */
    141.     public long keyOf(Object value) {
    142.         //returns the first key found; there may be more matching keys, however.
    143.         int i = indexOfValue(value);
    144.         if (i<0) return Long.MIN_VALUE;
    145.         return table[i];
    146.     }
    147.     /**
    148.      * Returns all the keys in the map.
    149.      */
    150.     public long[] keys() {
    151.         long[] elements = new long[distinct];
    152.         long[] tab = table;
    153.         byte[] stat = state;
    154.         int j=0;
    155.         for (int i = tab.length ; i-- > 0 ;) {
    156.             if (stat[i]==FULL) {
    157.                 elements[j++]=tab[i];
    158.             }
    159.         }
    160.         return elements;
    161.     }
    162.   
    163.     public boolean put(long key, Object value) {
    164.         int i = indexOfInsertion(key);
    165.         if (i<0) { //already contained
    166.             i = -i -1;
    167.             this.values[i]=value;
    168.             return false;
    169.         }
    170.         if (this.distinct > this.highWaterMark) {
    171.             int newCapacity = chooseGrowCapacity(
    172.                     this.distinct+1,
    173.                     this.minLoadFactor,
    174.                     this.maxLoadFactor
    175.                 );
    176.             rehash(newCapacity);
    177.             return put(key, value);
    178.         }
    179.         this.table[i]=key;
    180.         this.values[i]=value;
    181.         if (this.state[i]==FREE) this.freeEntries--;
    182.         this.state[i]=FULL;
    183.         this.distinct++;
    184.         if (this.freeEntries < 1) { //delta
    185.             int newCapacity = chooseGrowCapacity(
    186.                     this.distinct+1,
    187.                     this.minLoadFactor,
    188.                     this.maxLoadFactor
    189.                 );
    190.             rehash(newCapacity);
    191.         }
    192.         return true;
    193.     }
    194.     /**
    195.      * Returns the number of (key,value) associations currently contained.
    196.      *
    197.      * @return the number of (key,value) associations currently contained.
    198.      */
    199.     public int size() {
    200.         return distinct;
    201.     }
    202.     /**
    203.      * Returns true if the receiver contains no (key,value) associations.
    204.      *
    205.      * @return true if the receiver contains no (key,value) associations.
    206.      */
    207.     public boolean isEmpty() {
    208.         return distinct == 0;
    209.     }
    210.    
    211.     protected void rehash(int newCapacity) {
    212.         int oldCapacity = table.length;
    213.         //if (oldCapacity == newCapacity) return;
    214.         long oldTable[] = table;
    215.         Object oldValues[] = values;
    216.         byte oldState[] = state;
    217.         long newTable[] = new long[newCapacity];
    218.         Object newValues[] = new Object[newCapacity];
    219.         byte newState[] = new byte[newCapacity];
    220.         this.lowWaterMark  = chooseLowWaterMark(newCapacity,this.minLoadFactor);
    221.         this.highWaterMark = chooseHighWaterMark(newCapacity,this.maxLoadFactor);
    222.         this.table = newTable;
    223.         this.values = newValues;
    224.         this.state = newState;
    225.         this.freeEntries = newCapacity-this.distinct; // delta
    226.         for (int i = oldCapacity ; i-- > 0 ;) {
    227.             if (oldState[i]==FULL) {
    228.                 long element = oldTable[i];
    229.                 int index = indexOfInsertion(element);
    230.                 newTable[index]=element;
    231.                 newValues[index]=oldValues[i];
    232.                 newState[index]=FULL;
    233.             }
    234.         }
    235.     }
    236.    
    237.     public boolean removeKey(long key) {
    238.         int i = indexOfKey(key);
    239.         if (i<0) return false; // key not contained
    240.         this.state[i]=REMOVED;
    241.         this.values[i]=null; // delta
    242.         this.distinct--;
    243.         if (this.distinct < this.lowWaterMark) {
    244.                 int newCapacity = chooseShrinkCapacity(
    245.                         this.distinct,
    246.                         this.minLoadFactor,
    247.                         this.maxLoadFactor
    248.                     );
    249.                 rehash(newCapacity);
    250.         }
    251.         return true;
    252.     }
    253.   
    254.     protected void setUp(int initialCapacity, double minLoadFactor, double maxLoadFactor) {
    255.         if (initialCapacity < 0) {
    256.             throw new IllegalArgumentException(
    257.                 "Initial Capacity must not be less than zero: "+ initialCapacity
    258.             );
    259.         }
    260.         if (minLoadFactor < 0.0 || minLoadFactor >= 1.0) {
    261.                 throw new IllegalArgumentException(
    262.                     "Illegal minLoadFactor: "+ minLoadFactor
    263.                 );
    264.         }
    265.         if (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) {
    266.                 throw new IllegalArgumentException(
    267.                     "Illegal maxLoadFactor: "+ maxLoadFactor
    268.                 );
    269.         }
    270.         if (minLoadFactor >= maxLoadFactor) {
    271.                 throw new IllegalArgumentException(
    272.                     "Illegal minLoadFactor: " + minLoadFactor +
    273.                     " and maxLoadFactor: " + maxLoadFactor
    274.                 );
    275.         }
    276.         int capacity = initialCapacity;
    277.         capacity = nextPrime(capacity);
    278.         // open addressing needs at least one FREE slot at any time.
    279.         if (capacity==0) {
    280.             capacity=1;
    281.         }
    282.         this.table = new long[capacity];
    283.         this.values = new Object[capacity];
    284.         this.state = new byte[capacity];
    285.         //memory will be exhausted long before this pathological case happens, anyway.
    286.         this.minLoadFactor = minLoadFactor;
    287.         if (capacity == LARGEST_PRIME) this.maxLoadFactor = 1.0;
    288.         else this.maxLoadFactor = maxLoadFactor;
    289.         this.distinct = 0;
    290.         this.freeEntries = capacity; // delta
    291.         /**
    292.          * lowWaterMark will be established upon first expansion. Establishing
    293.          * it now (upon instance construction) would immediately make the table
    294.          * shrink upon first put(...). After all the idea of an
    295.          * "initialCapacity" implies violating lowWaterMarks when an object is
    296.          * young. See ensureCapacity(...)
    297.          */
    298.         this.lowWaterMark = 0;
    299.         this.highWaterMark = chooseHighWaterMark(capacity, this.maxLoadFactor);
    300.     }
    301.     /**
    302.      * Trims the capacity of the receiver to be the receiver"s current size.
    303.      * Releases any superfluous internal memory. An application can use this
    304.      * operation to minimize the storage of the receiver.
    305.      */
    306.     public void trimToSize() {
    307.         //*1.2 because open addressing"s performance exponentially degrades
    308.         //beyond that point so that even rehashing the table can take very long
    309.         int newCapacity = nextPrime((int)(1 + 1.2*size()));
    310.         if (table.length > newCapacity) {
    311.             rehash(newCapacity);
    312.         }
    313.     }
    314.     /**
    315.      * Returns an array of all the values in the Map.
    316.      */
    317.     public Object[] values() {
    318.         Object[] elements = new Object[distinct];
    319.         Object[] val = values;
    320.         byte[] stat = state;
    321.         int j=0;
    322.         for (int i = stat.length ; i-- > 0 ;) {
    323.             if (stat[i]==FULL) {
    324.                 elements[j++]=val[i];
    325.             }
    326.         }
    327.         return elements;
    328.     }
    329.     /**
    330.      * Chooses a new prime table capacity optimized for growing that
    331.      * (approximately) satisfies the invariant
    332.      * c * minLoadFactor <= size <= c * maxLoadFactor
    333.      * and has at least one FREE slot for the given size.
    334.      */
    335.     private int chooseGrowCapacity(int size, double minLoad, double maxLoad) {
    336.         return nextPrime(Math.max(size+1, (int) ((4*size / (3*minLoad+maxLoad)))));
    337.     }
    338.     /**
    339.      * Returns new high water mark threshold based on current capacity and
    340.      * maxLoadFactor.
    341.      *
    342.      * @return int the new threshold.
    343.      */
    344.     private int chooseHighWaterMark(int capacity, double maxLoad) {
    345.         //makes sure there is always at least one FREE slot
    346.         return Math.min(capacity-2, (int) (capacity * maxLoad));
    347.     }
    348.     /**
    349.      * Returns new low water mark threshold based on current capacity and minLoadFactor.
    350.      * @return int the new threshold.
    351.      */
    352.     protected int chooseLowWaterMark(int capacity, double minLoad) {
    353.         return (int) (capacity * minLoad);
    354.     }
    355.     /**
    356.      * Chooses a new prime table capacity neither favoring shrinking nor growing,
    357.      * that (approximately) satisfies the invariant
    358.      * c * minLoadFactor <= size <= c * maxLoadFactor
    359.      * and has at least one FREE slot for the given size.
    360.      */
    361.     protected int chooseMeanCapacity(int size, double minLoad, double maxLoad) {
    362.         return nextPrime(Math.max(size+1, (int) ((2*size / (minLoad+maxLoad)))));
    363.     }

    364.     protected int chooseShrinkCapacity(int size, double minLoad, double maxLoad) {
    365.         return nextPrime(Math.max(size+1, (int) ((4*size / (minLoad+3*maxLoad)))));
    366.     }
    367.   
    368.     protected int nextPrime(int desiredCapacity) {
    369.         int i = java.util.Arrays.binarySearch(primeCapacities, desiredCapacity);
    370.         if (i<0) {
    371.             //desired capacity not found, choose next prime greater than desired
    372.             //capacity
    373.             i = -i -1; // remember the semantics of binarySearch...
    374.         }
    375.         return primeCapacities[i];
    376.     }
    377.     /**
    378.      * The largest prime this class can generate; currently equal to Integer.MAX_VALUE.
    379.      */
    380.     public static final int LARGEST_PRIME = Integer.MAX_VALUE; //yes, it is prime.
    381.    
    382.     private static final int[] primeCapacities = {
    383.         //chunk #0
    384.         LARGEST_PRIME,
    385.         //chunk #1
    386.         5,11,23,47,97,197,397,797,1597,3203,6421,12853,25717,51437,102877,205759,
    387.         411527,823117,1646237,3292489,6584983,13169977,26339969,52679969,105359939,
    388.         210719881,421439783,842879579,1685759167,
    389.         //chunk #2
    390.         433,877,1759,3527,7057,14143,28289,56591,113189,226379,452759,905551,1811107,
    391.         3622219,7244441,14488931,28977863,57955739,115911563,231823147,463646329,927292699,
    392.         1854585413,
    393.         //chunk #3
    394.         953,1907,3821,7643,15287,30577,61169,122347,244703,489407,978821,1957651,3915341,
    395.         7830701,15661423,31322867,62645741,125291483,250582987,501165979,1002331963,
    396.         2004663929,
    397.         //chunk #4
    398.         1039,2081,4177,8363,16729,33461,66923,133853,267713,535481,1070981,2141977,4283963,
    399.         8567929,17135863,34271747,68543509,137087021,274174111,548348231,1096696463,
    400.         //chunk #5
    401.         31,67,137,277,557,1117,2237,4481,8963,17929,35863,71741,143483,286973,573953,
    402.         1147921,2295859,4591721,9183457,18366923,36733847,73467739,146935499,293871013,
    403.         587742049,1175484103,
    404.         //chunk #6
    405.         599,1201,2411,4831,9677,19373,38747,77509,155027,310081,620171,1240361,2480729,
    406.         4961459,9922933,19845871,39691759,79383533,158767069,317534141,635068283,1270136683,
    407.         //chunk #7
    408.         311,631,1277,2557,5119,10243,20507,41017,82037,164089,328213,656429,1312867,
    409.         2625761,5251529,10503061,21006137,42012281,84024581,168049163,336098327,672196673,
    410.         1344393353,
    411.         //chunk #8
    412.         3,7,17,37,79,163,331,673,1361,2729,5471,10949,21911,43853,87719,175447,350899,
    413.         701819,1403641,2807303,5614657,11229331,22458671,44917381,89834777,179669557,
    414.         359339171,718678369,1437356741,
    415.         //chunk #9
    416.         43,89,179,359,719,1439,2879,5779,11579,23159,46327,92657,185323,370661,741337,
    417.         1482707,2965421,5930887,11861791,23723597,47447201,94894427,189788857,379577741,
    418.         759155483,1518310967,
    419.         //chunk #10
    420.         379,761,1523,3049,6101,12203,24407,48817,97649,195311,390647,781301,1562611,
    421.         3125257,6250537,12501169,25002389,50004791,100009607,200019221,400038451,800076929,
    422.         1600153859
    423.     };
    424.     static { //initializer
    425.         // The above prime numbers are formatted for human readability.
    426.         // To find numbers fast, we sort them once and for all.
    427.         java.util.Arrays.sort(primeCapacities);
    428.     }
    429. }
    复制代码

      

      
      
       
       

         
       

         
       
      
       
      

      










    源码下载:http://file.javaxxz.com/2014/11/2/235637093.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 16:09 , Processed in 0.340089 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表