實現一個支持動態擴容的數組


主要考慮3個問題

  1. 主要的操作
  2. 擴容的策略
  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種設計方案

  1. 普通方案:兩倍擴容+挨個元素拷貝。
  2. 仿造slice切片的方案:數組做底層存儲+類似窗戶的索引+ 更靈活的擴容+數組整體拷貝。
    刪除元素時不需要真的刪除,只是移動索引。
    增加元素時需要往底層數組添加元素,且移動索引。
  3. 加入COW機制的方案:針對多線程讀多寫少場景。// 附錄2

方案1

// 附錄1

方案2: slice的方案

  • 擴容策略:比較復雜
  • 數據遷移策略:整體拷貝

方案3: 針對並發讀多寫少的優化

  • CopyOnWriteArrayList使用場景
    1、讀多寫少(白名單,黑名單,系統配置的信息,商品類目的訪問和更新場景),為什么?因為寫的時候會復制新集合。
    2、集合不大,為什么?因為寫的時候會復制新集合。
    實時性要求不高,為什么,因為有可能會讀取到舊的集合數據。---- 也就是允許讀到舊數據。

方案4

// 附錄4
Q:golang的slice動態擴展實現為何不用動態鏈表?
A:對內存不優化,有gc壓力。

擴展

slice並發不安全的問題

參考

  1. Go 語言實現動態數組
    https://github.com/hetong12345/goDataStructure/blob/master/array.go#L101
    https://github.com/JeffreyBool/array/blob/master/array.go
  2. 簡單說一說Java中的CopyOnWriteArrayList
  3. 並發容器之CopyOnWriteArrayList
  4. golang的slice動態擴展實現為何不用動態鏈表?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM