zoukankan      html  css  js  c++  java
  • .net源码研究(1)HashTable

    HashTable构造函数源码如下:

    View Code
    public Hashtable(int capacity, float loadFactor)
    {
        if (capacity < 0)
        {
            throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
        }
        if ((loadFactor < 0.1f) || (loadFactor > 1f))
        {
            throw new ArgumentOutOfRangeException("loadFactor", Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", new object[] { 0.1, 1.0 }));
        }
        this.loadFactor = 0.72f * loadFactor;
        double num = ((float) capacity) / this.loadFactor;
        if (num > 2147483647.0)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
        }
        int num2 = (num > 3.0) ? HashHelpers.GetPrime((int) num) : 3;
        this.buckets = new bucket[num2];
        this.loadsize = (int) (this.loadFactor * num2);
        this.isWriterInProgress = false;
    }
    
     
    HashTable实质为一个一维数组,即上述源码中的buckets,其初始大小num2由初始指定容量capacity和装载因子loadFactor决定,其实际装载容量loadsize为装在因子*0.72f*初始大小num2。

    注:

    • capacity: System.Collections.Hashtable 对象最初可包含的元素的近似数目。
    • loadFactor: 0.1 到 1.0 范围内的数字,再乘以提供最佳性能的默认值。结果是元素与存储桶的最大比率。

    Insert方法源码如下:

    View Code
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    private void Insert(object key, object nvalue, bool add)
    {
        uint num;
        uint num2;
        if (key == null)
        {
            throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
        }
        if (this.count >= this.loadsize)
        {
            this.expand();
        }
        else if ((this.occupancy > this.loadsize) && (this.count > 100))
        {
            this.rehash();
        }
        uint num3 = this.InitHash(key, this.buckets.Length, out num, out num2);
        int num4 = 0;
        int index = -1;
        int num6 = (int) (num % this.buckets.Length);
    Label_0071:
        if (((index == -1) && (this.buckets[num6].key == this.buckets)) && (this.buckets[num6].hash_coll < 0))
        {
            index = num6;
        }
        if ((this.buckets[num6].key == null) || ((this.buckets[num6].key == this.buckets) && ((this.buckets[num6].hash_coll & 0x80000000L) == 0L)))
        {
            if (index != -1)
            {
                num6 = index;
            }
            Thread.BeginCriticalRegion();
            this.isWriterInProgress = true;
            this.buckets[num6].val = nvalue;
            this.buckets[num6].key = key;
            this.buckets[num6].hash_coll |= (int) num3;
            this.count++;
            this.UpdateVersion();
            this.isWriterInProgress = false;
            Thread.EndCriticalRegion();
        }
        else if (((this.buckets[num6].hash_coll & 0x7fffffff) == num3) && this.KeyEquals(this.buckets[num6].key, key))
        {
            if (add)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", new object[] { this.buckets[num6].key, key }));
            }
            Thread.BeginCriticalRegion();
            this.isWriterInProgress = true;
            this.buckets[num6].val = nvalue;
            this.UpdateVersion();
            this.isWriterInProgress = false;
            Thread.EndCriticalRegion();
        }
        else
        {
            if ((index == -1) && (this.buckets[num6].hash_coll >= 0))
            {
                this.buckets[num6].hash_coll |= -2147483648;
                this.occupancy++;
            }
            num6 = (int) ((num6 + num2) % ((ulong) this.buckets.Length));
            if (++num4 < this.buckets.Length)
            {
                goto Label_0071;
            }
            if (index == -1)
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HashInsertFailed"));
            }
            Thread.BeginCriticalRegion();
            this.isWriterInProgress = true;
            this.buckets[index].val = nvalue;
            this.buckets[index].key = key;
            this.buckets[index].hash_coll |= (int) num3;
            this.count++;
            this.UpdateVersion();
            this.isWriterInProgress = false;
            Thread.EndCriticalRegion();
        }
    }
    
     
    当HashTable也即buckets数组中实际添加元素数超过loadsize时,会调用expand方法使得buckets扩容一倍。
    根据要插入的key和buckets的length生成初次要插入的位置num6和发生哈希冲突后要增加的步进量num2,该计算由InitHash函数实现,源码如下:
    View Code
    private uint InitHash(object key, int hashsize, out uint seed, out uint incr)
    {
        uint num = (uint) (this.GetHash(key) & 0x7fffffff);
        seed = num;
        incr = 1 + ((uint) (((seed >> 5) + 1) % (hashsize - 1)));
        return num;
    }
    
     

     参见:http://www.cnblogs.com/xiaosuo/archive/2010/03/18/1632341.html

  • 相关阅读:
    泛型为什么不用装箱拆箱
    net 自带cache
    泛型与非泛型的区别。
    java 魔术
    栈帧
    yii使用CUploadedFile上传文件
    yii上传图片、yii上传文件、yii控件activeFileField使用
    yii 验证码的使用
    mysql 分库分表
    全国省市区三级联动js
  • 原文地址:https://www.cnblogs.com/Finding2013/p/2975766.html
Copyright © 2011-2022 走看看