intset(整數(shù)集合)是集合鍵的底層實現(xiàn)之一,當(dāng)一個集合只包含整數(shù),并且數(shù)量不多的時候,Redis就會使用整數(shù)集合作為集合鍵的底層實現(xiàn)
整數(shù)集合的實現(xiàn)
intset是Redis中用來保存整數(shù)值的集合抽象數(shù)據(jù)結(jié)構(gòu),可以保存int16_t,int32_t,int64_t的整數(shù)值,并且保證集合中不會出現(xiàn)重復(fù)的,從小到大有序排序
typedef struct intset{
//編碼方式
uint32_t encoding;
//集合包含的元素數(shù)量
uint32_t length;
//保存元素的數(shù)組
int8_t contents[];
}intset;
contents數(shù)組的真正類型取決于encoding屬性的值:
encoding:INTSET_ENC_INT16,那么contents就是一個int16_t類型的數(shù)組(-32768到32767)
encoding:INTSET_ENC_INT32,那么contents就是一個int32_t類型的數(shù)組(-2147483648到2147483647)
encoding:INTSET_ENC_INT64,那么contents就是一個int64_t類型的數(shù)組(-9223372036854775808到9223372036854775807)

contents數(shù)組的大小等于sizeof(int16_t)*5=16*5=80位
升級
當(dāng)我們要將一個新元素添加到整數(shù)集合中,并且新元素的類型比整數(shù)集合現(xiàn)有的所有元素類型都要長的時候,整數(shù)集合需要先進(jìn)行升級,然后才能將新元素添加到整數(shù)集合中
升級步驟:
根據(jù)新元素的類型,擴(kuò)展整數(shù)集合底層數(shù)組的空間大小,并為新元素分配空間
把底層數(shù)組現(xiàn)有的所有元素都轉(zhuǎn)換為與新元素相同的類型,并將類型轉(zhuǎn)換后的元素放到正確的位上,而且在防止元素的過程中,需要維持底層數(shù)組的有序性不變
將新元素添加到底層數(shù)組中
舉例:
包含3個int16_t類型的整數(shù)
contents底層數(shù)組大小3*16=48,下面是3個元素在48位中的位置
| 位 | 0-15位 | 16到31位 | 32到47位 |
|---|---|---|---|
| 元素 | 1 | 2 | 3 |
將65535添加進(jìn)去,這個是int32_t類型的,所以要對contents進(jìn)行升級
對底層數(shù)組做空間重分配,32*4=128位
| 位 | 0-15位 | 16到31位 | 32到47位 | 48到127位 |
|---|---|---|---|---|
| 元素 | 1 | 2 | 3 | 新分配空間 |
| 位 | 0-15位 | 16到31位 | 32到47位 | 48到63位 | 64到95位 | 96到127位 |
|---|---|---|---|---|---|---|
| 元素 | 1 | 2 | 3 | 新分配空間 | 3 | 新分配空間 |
| 位 | 0-15位 | 16到31位 | 32到63位 | 64到95位 | 96到127位 |
|---|---|---|---|---|---|
| 元素 | 1 | 2 | 2 | 3 | 新分配空間 |
| 位 | 0-31位 | 32到63位 | 64到95位 | 96到127位 |
|---|---|---|---|---|
| 元素 | 1 | 2 | 3 | 新分配空間 |
| 位 | 0-31位 | 32到63位 | 64到95位 | 96到127位 |
|---|---|---|---|---|
| 元素 | 1 | 2 | 3 | 65535 |
升級的好處
- 提升整數(shù)集合的靈活性
c語言是靜態(tài)類型語言,為了避免類型錯誤,通常不會將兩種不同類型的值放到一個數(shù)據(jù)結(jié)構(gòu)中,但是通過自動升級底層數(shù)組來適應(yīng)新元素,可以隨意將int16_t,int32_t,int64_t類型的整數(shù)添加到集合中,不必?fù)?dān)心類型錯誤
- 盡可能的節(jié)約內(nèi)存
如果直接使用int64_t作為底層數(shù)組的實現(xiàn),當(dāng)然可以同時保持所有了,但是如果存的都是int16_t,或者都是int32_t類型的值,就會浪費(fèi)內(nèi)存了,而升級只會讓他在需要的時候進(jìn)行升級,這樣可以盡量節(jié)省內(nèi)存
降級
intset不支持降級操作,一旦對數(shù)組做了升級,編碼就會一直保持升級后的狀態(tài),即使將int64_t類型的數(shù)刪除了,編碼仍然是int64_t
整數(shù)集合API
| 函數(shù) | 作用 | 時間復(fù)雜度 |
|---|---|---|
| intsetNew | 創(chuàng)建一個新的壓縮列表 | O(1) |
| intsetAdd | 將給定元素添加到整數(shù)集合中 | O(N) |
| intsetRemove | 從整數(shù)集合中移除給定元素 | O(N) |
| intsetFind | 檢查給定值是否存在于集合中 | 有序,可以通過二分查找O(logN) |
| intsetRandom | 從整數(shù)集合中隨機(jī)返回一個元素 | O(1) |
| intsetGet | 取出底層數(shù)組在給定索引上的元素 | O(1) |
| intestLen | 返回整數(shù)集合中包含元素的個數(shù) | O(1) |
| intsetBlobLen | 返回整數(shù)集合占用的內(nèi)存字節(jié)數(shù) | O(1) |
