整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的数量不多时,Redis就会使用整数集合作为集合键的底层实现。
整数集合的实现:
整数集合(intset)是用于保存整数值的集合抽象数据结构,它可以保存类型int16_t、int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素。
每个intset.h/intset结构表示一个整数集合:
typedef struct intset{ //编码方式 unit32_t encoding; //集合包含的元素数量,contents数组的长度。 unit32_t length; //保存元素的数组 int8_t contents[]; }intset;
虽然intset结构将contents属性声明为int8_t类型的数组,但实际上contents数组并不保存任何int8_t类型的值,contents数组的真正类型取决于encoding属性的值,contents数组按从小到大的排序保存数组中的元素。
备注:数组的大小和数组的长度并不一样。
升级与降级:
每当将一个新元素添加到整数集合中,并且新元素的类型比整数集合现有的元素的类型都要长是,整数集合需要先进行升级(upgrade),然后才能将新元素添加到整数集合中。
升级整数集合并添加新元素分三步进行:
1.根据新元素的类型,扩展整数集合底层数组的空间大小,并且为新元素分配空间。
2.将底层数组现有的新元素都转换成与新元素相同的类型,并将类型转换后的元素都放置到正确的位置上,而且在放置的过程中,需要维持底层数组的有序性质不变。
3.将新元素添加到底层数组里面。
因为每次新添加元素都可能会升级,且每次升级需要对底层所有的元素进行类型转换,所以想整数集合添加新元素的时间复杂度为O(N);
升级之后新元素的摆放位置:
因为引发升级的新元素的长度总是比整数集合现有所有元素的长度都大,所以新元素的值要么大于现有元素,要么就小于所有现有元素。
1.在新元素小于所有现有元素的情况下,新元素会被放置在底层数组的最开始(索引0)。
2.在新元素大于所有现有元素的情况下,新元素会被放置在底层数组的最大化(索引:length-1)
升级的好处:
1.提升整数集合的灵活性;
3.尽可能节约内存。
降级:整数集合不支持降级操作,一旦升级,编码就会一直保持着升级后的状态。