主要考慮3個問題
- 主要的操作
- 擴容的策略
- 數據遷移策略
其中,主要操作如下:
PS. 注意沒有插入操作,只有添加,刪除,查找,修改操作。
type ArrayInterface interface {
// 添加
Add(int, interface{}) // 插入元素
AddLast(interface{})
AddFirst(interface{})
// 刪除
Remove(int) interface{}
RemoveFirst() interface{}
RemoveLast() interface{}
// 查找
Find(interface{}) int // 查找元素返回第一個索引
FindAll(interface{}) []int // 查找元素返回所有索引
Contains(interface{}) bool // 查找是否存在元素
Get(int) interface{}
// 修改
Set(int, interface{})
// 基本方法
GetCapacity() int // 獲得數組容量
GetSize() int // 獲得元素個數
IsEmpty() bool // 查看數組是否為空
}
大概有3種設計方案
- 普通方案:兩倍擴容+挨個元素拷貝。
- 仿造slice切片的方案:數組做底層存儲+類似窗戶的索引+ 更靈活的擴容+數組整體拷貝。
刪除元素時不需要真的刪除,只是移動索引。
增加元素時需要往底層數組添加元素,且移動索引。 - 加入COW機制的方案:針對多線程讀多寫少場景。// 附錄2
方案1
// 附錄1
方案2: slice的方案
- 擴容策略:比較復雜
- 數據遷移策略:整體拷貝
方案3: 針對並發讀多寫少的優化
- CopyOnWriteArrayList使用場景
1、讀多寫少(白名單,黑名單,系統配置的信息,商品類目的訪問和更新場景),為什么?因為寫的時候會復制新集合。
2、集合不大,為什么?因為寫的時候會復制新集合。
實時性要求不高,為什么,因為有可能會讀取到舊的集合數據。---- 也就是允許讀到舊數據。
方案4
// 附錄4
Q:golang的slice動態擴展實現為何不用動態鏈表?
A:對內存不優化,有gc壓力。