集合键的底层实现之一,当集合只包含整数值元素,且报价函的元素不多时,就会使用整数集合作为集合键的底层实现。
intset实现
typedef struct intset {
uint32_t encoding; // 编码方式
uint32_t length; // 集合包含的元素数量
int8_t contents[]; // 保存元素的数组
} intset;
- contents[]: 是整数集合的底层实现,各元素在数组中按值从小到大排列,并且无重复项。
- length:contents数组包含的元素数量,即数组长度。
- encoding:决定contents数组包含的整数类型,虽然contents[] 明面上是声明为int8_t类型,但实际取决于encoding
- 如果encoding = INTSET_ENC_INT16, 那么contents就是int16_t类型的数组,如果是INTSET_ENC_INT32或INTSET_ENC_INT64,就分别是int32_t, int64_t类型的数组。
- 如果encoding = INTSET_ENC_INT16, 那么contents就是int16_t类型的数组,如果是INTSET_ENC_INT32或INTSET_ENC_INT64,就分别是int32_t, int64_t类型的数组。
如上图,虽然contents数组只有一个是真正需要64位保存的整数:contents[0],但其余四个都是int64_t类型的。所以当整数集合涉及到保存位数更多的整数的时候,就需要对数组进行升级。
升级
-
条件:有新元素加入整数集合,并且改新元素的类型大于整数集合现有的元素的类型,整数集合触发升级操作。然后才能将新元素加入整数集合。
-
步骤:
- 根据新元素的类型,扩展整数集合底层数组的空间大小,并为新元素分配空间。
- 底层数组所有的元素类型换成与新元素相同的类型,并将类型转换后的元素放到正确的位置上,并且元素的整体顺序不变。
- 将新元素添加到新数组里。
好处:
- 提升整数集合的灵活性
- 因为C语⾔是静态类型语⾔,为了避免类型错误,我们通常不会将两种不同类型的值放在同⼀个数据结构⾥⾯。例如,我们⼀般只使⽤int16_t类型的数组来保存int16_t类型的值,只使⽤int32_t类型的数组来保存int32_t类型的值,诸如此类。但是,因为整数集合可以通过⾃动升级底层数组来适应新元素,所以我们可以随意地将int16_t、int32_t或者int64_t类型的整数添加到集合中,⽽不必担⼼出现类型错误,这种做法⾮常灵活。
- 节约内存
- 要让⼀个数组可以同时保存int16_t、int32_t、int64_t三种类型的值,最简单的做法就是直接使⽤int64_t类型的数组作为整数集合的底层实现。不过这样⼀来,即使添加到整数集合⾥⾯的都是int16_t类型或者int32_t类型的值,数组都需要使⽤int64_t类型的空间去保存它们,从⽽出现浪费内存的情况。⽽整数集合现在的做法既可以让集合能同时保存三种不同类型的值,⼜可以确保升级操作只会在有需要的时候进⾏,这可以尽量节省内存。
整数集合不支持降级操作,即使将整数数组里的int64_t类型的整数全部删除,只留下int32_t或int16_t的整数,底层数组也不会降级,仍然是int64_t类型的。
标签:Redis,整数,类型,int64,数组,集合,contents From: https://www.cnblogs.com/wz-NO1/p/17237466.html