整数集合的实现

最后更新于:2022-04-01 21:35:34

整数集合(intset)是 Redis 用于保存整数值的集合抽象数据结构, 它可以保存类型为 `int16_t` 、 `int32_t` 或者 `int64_t` 的整数值, 并且保证集合中不会出现重复元素。 每个 `intset.h/intset` 结构表示一个整数集合: ~~~ typedef struct intset { // 编码方式 uint32_t encoding; // 集合包含的元素数量 uint32_t length; // 保存元素的数组 int8_t contents[]; } intset; ~~~ `contents` 数组是整数集合的底层实现: 整数集合的每个元素都是 `contents` 数组的一个数组项(item), 各个项在数组中按值的大小从小到大有序地排列, 并且数组中不包含任何重复项。 `length` 属性记录了整数集合包含的元素数量, 也即是 `contents` 数组的长度。 虽然 `intset` 结构将 `contents` 属性声明为 `int8_t` 类型的数组, 但实际上 `contents` 数组并不保存任何 `int8_t` 类型的值 —— `contents` 数组的真正类型取决于 `encoding` 属性的值: * 如果 `encoding` 属性的值为 `INTSET_ENC_INT16` , 那么 `contents` 就是一个 `int16_t` 类型的数组, 数组里的每个项都是一个 `int16_t` 类型的整数值 (最小值为 `-32,768` ,最大值为 `32,767` )。 * 如果 `encoding` 属性的值为 `INTSET_ENC_INT32` , 那么 `contents` 就是一个 `int32_t` 类型的数组, 数组里的每个项都是一个 `int32_t` 类型的整数值 (最小值为 `-2,147,483,648` ,最大值为 `2,147,483,647` )。 * 如果 `encoding` 属性的值为 `INTSET_ENC_INT64` , 那么 `contents` 就是一个 `int64_t` 类型的数组, 数组里的每个项都是一个 `int64_t` 类型的整数值 (最小值为 `-9,223,372,036,854,775,808` ,最大值为 `9,223,372,036,854,775,807` )。 图 6-1 展示了一个整数集合示例: * `encoding` 属性的值为 `INTSET_ENC_INT16` , 表示整数集合的底层实现为 `int16_t` 类型的数组, 而集合保存的都是 `int16_t` 类型的整数值。 * `length` 属性的值为 `5` , 表示整数集合包含五个元素。 * `contents` 数组按从小到大的顺序保存着集合中的五个元素。 * 因为每个集合元素都是 `int16_t` 类型的整数值, 所以 `contents` 数组的大小等于 `sizeof(int16_t) * 5 = 16 * 5 = 80` 位。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-09-13_55f51a1132a4b.png) 图 6-2 展示了另一个整数集合示例: * `encoding` 属性的值为 `INTSET_ENC_INT64` , 表示整数集合的底层实现为 `int64_t` 类型的数组, 而数组中保存的都是 `int64_t` 类型的整数值。 * `length` 属性的值为 `4` , 表示整数集合包含四个元素。 * `contents` 数组按从小到大的顺序保存着集合中的四个元素。 * 因为每个集合元素都是 `int64_t` 类型的整数值, 所以 `contents` 数组的大小为 `sizeof(int64_t) * 4 = 64 * 4 = 256` 位。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-09-13_55f51a139a148.png) 虽然 `contents` 数组保存的四个整数值中, 只有 `-2675256175807981027` 是真正需要用 `int64_t` 类型来保存的, 而其他的 `1` 、 `3` 、 `5` 三个值都可以用 `int16_t` 类型来保存, 不过根据整数集合的升级规则, 当向一个底层为 `int16_t` 数组的整数集合添加一个 `int64_t` 类型的整数值时, 整数集合已有的所有元素都会被转换成 `int64_t` 类型, 所以 `contents` 数组保存的四个整数值都是 `int64_t` 类型的, 不仅仅是`-2675256175807981027` 。 接下来的一节将对整数集合的升级操作进行详细的介绍。
';