- 整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。
6.1整数集合的实现
- 整数集合可以保存的类型为int16_t , int32_t , int64_t的整数值,并且集合中不会出现重复的元素。
结构表示:
typedef struct inset{
//编码方式
uint32_t encoding;
//集合包含的元素数量
uint32_t length;
//保存元素的数组
int8_t contents[];
}intset;
![](https://img.haomeiwen.com/i8432968/30cde3d61882ad7d.jpeg)
- contents 数组是整数集合的底层实现;数组中按值的大小从小到大的有序排列,数组中不包含任何重复项。
- length 记录了整数集合中元素的数量
虽然intset结构将contents属性声明为int8_t类型的数组,实际上contents数组不保存任何int8_t类型的值,真正的类型取决于encoding属性的值:
- 如果encoding 值为 INTSET_ENC_INT16 那么contents就是一个int16_t类型的数组(-32768 ~ 32767)
- 如果encoding 值为 INTSET_ENC_INT32 那么contents就是一个int32_t类型的数组(-2147483648 ~ 2147483647)
- 如果encoding 值为 INTSET_ENC_INT64 那么contents就是一个int64_t类型的数组(-9223372036854775808 ~ 9223372036854775807 )
当向一个底层为int16_t数组的整数集合中添加一个int64_t类型的数值时,整数集合中所有的元素都会被转换为int64_t类型!
6.2升级
- 将一个新元素添加到整数集合里面,新元素类型比整数集合现有所有元素类型都要长时,整数集合需要先进行升级,才能将新元素添加到整数集合里面。
升级步骤:
- 根据新元素的类型,扩展整数集合底层数组的空间大小,并为新元素分配空间。
- 将底层数组现有的所有元素都转换成与新元素相同的类型,将类型转换后的元素放到正确的位置上,在放置元素过程中,继续维持底层数组的有序性质不变
- 将新元素添加到底层数组里面
每次向整数集合添加新元素都可能会引起升级,每次升级都需要对底层数组中已有的所有元素进行类型转换;时间复杂度为O(n)
6.3升级的好处
升级策略有两个好处:
- 提升整数的灵活性:整数集合通过自动升级底层数组来适应新的元素,随意的将int16_t, int32_t, 或者int64_t 的整数添加到集合中,不必担心出现类型错误,这种做法非常灵活。
- 尽可能的节约内存:可以让集合能同时保存三种不同类型的值,又可以确保升级操作只会在有需要的时候进行,这可以尽量节省内存。
6.4降级
- 整数集合不支持降级操作,一旦对数组进行了升级,编码就会一直保持升级后的状态。
整数集合API
函数: 作用 | 时间复杂度 |
---|---|
intsetNew:创建一个新的整数集合 | O(1) |
intsetAdd:将给定的元素添加到整数集合里面 | O(n) |
intsetRemove:从整数集合中移除给定元素 | O(n) |
intsetFind:检查给定值是否存在于集合 | O(logN) |
intsetRandom:从整数集合中随机返回一个元素 | O(1) |
intsetGet:取出底层数组在给定索引上的元素 | O(1) |
intsetLen:返回整数集合包含的元素个数 | O(1) |
intsetBlobLen:返回整数集合占用的内存字节数 | O(1) |
网友评论