整数集合(intset)是集合键的底层实现之一。

它可以保存类型为int16_t,int32_t,int64_t的整数值,当一个集合只包含整数值元素,并且这个集合元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。

【redis设计与实现】数据结构:整数集合(intset)_数据结构

 

length:整数集合包含的元素数量。

encoding:编码方式。

contents数组:整数集合的每个元素都是contents数组的一个数组项(item),各个项在数组中按权的大小从小到大有序排列,并且不重复。

整数集合的升级:

当我们将一个新元素添加到整数集合里面,并且新元素的类型比整数集合现有所有类型都长时,整数集合需要先进行升级,才能将新元素添加到整数集合中。

步骤:

(1)根据新元素的类型,拓展整数集合底层数组的空间大小,并为新元素分配空间

(2)将底层数组现有的所有元素都转换成新元素相同的类型,并将类型装换后的元素放置到正确的位上,而且在放置元素的过程中,需要继续维持底层数组的有序性质不变。

(3)将新元素添加到底层数组里面。

示例:

【redis设计与实现】数据结构:整数集合(intset)_类型转换_02

整数集合中包含3个int_16的元素,共48位。

【redis设计与实现】数据结构:整数集合(intset)_数据结构_03

 

 

将int_32类型的元素65535添加到整数集合里面,因为int_32比整数集合int_32类型要长,所以在将65535添加到整数集合之前,需要先对整数集合进行升级。

一:重新分配空间

【redis设计与实现】数据结构:整数集合(intset)_数组_04

 一共需要32*4的空间。1,2,3类型不变,在前48位。

二:类型转换,重新放置元素,并且保持相对有序

【redis设计与实现】数据结构:整数集合(intset)_时间复杂度_05

 三:添加添加新元素 

【redis设计与实现】数据结构:整数集合(intset)_数组_06

最后,将整数集合encoding属性从int_16改为int_32,将length从3改到4

【redis设计与实现】数据结构:整数集合(intset)_时间复杂度_07

 

时间复杂度分析:

因为每次向整数集合添加元素都可能会引起升级,而每次升级都需要对底层数组中所有的元素进行类型转换,所以向整数集合中添加新元素的时间复杂度为O(N)

升级的好处:

一:提升整数的灵活性

因为c语言是静态类型语言,为了避免类型错误,通常不会将两种不同类型的值放在同一个数据结构中。但是整数集合可以通过自动升级底层数组来适应新元素,所以可以随意地将int16_t,int32_t,int64_t类型的整数添加到集合中。

二:尽可能节约内存

可以直接使用int64_t类型的数组来保存元素,但是即使添加到数组中的元素都是int16_t或者int32_t,数组都需要使用int64_t类型的空间去保存,从而出现浪费内存的情况。

整数集合可以同时保存三种不同类型的值,又可以确保升级操作只会在有需要的时候进行,节省内存。

整数集合不支持降级,一旦升级,编码就会一直保持升级后的状态。