Redis整数集合

集合键的底层实现之一,当集合只包含整数值元素,且报价函的元素不多时,就会使用整数集合作为集合键的底层实现。

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类型的数组。

如上图,虽然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类型的。

posted @   新游  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示