NXHashTable -> _NXHashRehash 方法解读心得

数据结构都可以从 苹果开源代码 里 ,objc4 源码 适配mac系统  macOS Big Sur 11.5 ~ 11.6.2

具体数据结构在 hashtable2.h 里面都有定义,嫌麻烦的可以直接看 这个github 。 这里只解读关键函数,其他的基本都比较容易看明白


调用顺序:  NXHashInsert -> _NXHashRehash -> _NXHashRehashToCapacity 

    /* private data structure; may change */

        _NXHashRehashToCapacity (table, MORE_CAPACITY(table->nbBuckets)); //扩容2倍 + 1

    }

//newCapacity 扩容大小是原先2倍 + 1

void_NXHashRehashToCapacity(NXHashTable *table,unsigned newCapacity) {

    /* Rehash: we create a pseudo table pointing really to the old guys,

    extend self, copy the old pairs, and free the pseudo table */

    NXHashTable *old;

    NXHashState state;

    void *aux;

    __unusedvoid*z =ZONE_FROM_PTR(table);


    old =ALLOCTABLE(z);

    old->prototype= table->prototype; old->count= table->count; 

    old->nbBuckets= table->nbBuckets; old->buckets= table->buckets;

    table->nbBuckets= newCapacity;

    table->count=0; table->buckets=ALLOCBUCKETS(z, table->nbBuckets);

    state = NXInitHashState(old); //这里面

    //newCapacity 扩容之后,同一个buckets里面取出来的数据 hash表计算出来的hash值索引和原来就不一定一致,这样同一个aux 在进行insert 就会开新的bucket来存放数据。所以不是无限循环操作,这个琢磨好久才明白,否则就是无限循环插入了。

    while(NXNextHashState(old, &state, &aux))  //循环插入

        (void)NXHashInsert(table, aux);

    freeBuckets(old,NO);

    if(old->count!= table->count)

_objc_inform("*** hashtable: count differs after rehashing; probably indicates a broken invariant: there are x and y such as isEqual(x, y) is TRUE but hash(x) != hash (y)\n");

    free(old->buckets); 

    free(old);

    }

//这就是二维数组, i 表示 buckets 数量即: hash 表开的数组数量, j 表示 每一个buckets 里面的元素数量
NXHashState NXInitHashState (NXHashTable *table) {

    NXHashState state;

    state.i= table->nbBuckets;

    state.j=0;

    returnstate;

    };

    //从table.buckets表里面逆序查找hash非空bucket,返回当前bucket 链表最末端的数据,写入到 *data

int NXNextHashState(NXHashTable *table , NXHashState *state, void **data) {

    HashBucket *buckets = (HashBucket*) table->buckets;

   // j == 0 表示当前bucket 数据是空的, state -> i -- ,逆序向上在找一个bucket

    while(state->j==0) {

        if (state->i==0) return NO;

        state->i--; state->j= buckets[state->i].count;

}

    state-> j--; // j 数组数据的数量,j -- 表示数据在当前bucket 的真正下标

    buckets += state->i;//移动数组指针!!!。逆序的从hash 表里面提取buckets

    *data = (void*) ((buckets->count==1) ?  buckets->elements.one : buckets->elements.many[state->j]);

    return YES;

    };

你可能感兴趣的:(NXHashTable -> _NXHashRehash 方法解读心得)