jianfengye/collection(https://github.com/jianfengye/collection) 這個包喜迎第一個子版本升級,從1.0.1升級到了1.1.0。此次仍是作了很多改動的。git
這個需求是這個issue提出的: https://github.com/jianfengye/collection/issues/10github
主要是在protobuf 生成的go代碼裏面是int32,int64的。數組
增長一個類型的數組實際上是很方便的事情了,只須要寫一個Int32Collection的struct, 基於AbsCollection,實現幾個必要的函數就能夠了。安全
package collection import ( "errors" "fmt" ) type Int32Collection struct { AbsCollection objs []int32 } func compareInt32(i interface{}, i2 interface{}) int { int1 := i.(int32) int2 := i2.(int32) if int1 > int2 { return 1 } if int1 < int2 { return -1 } return 0 } // NewInt32Collection create a new Int32Collection func NewInt32Collection(objs []int32) *Int32Collection { arr := &Int32Collection{ objs: objs, } arr.AbsCollection.Parent = arr arr.SetCompare(compareInt32) return arr } ...
這個是有一個讀者在公衆號留言提醒的。以前1.0.1版本的collection在new的時候直接將slice進行copy一份,是出於安全的考慮,Collection的使用必定不能修改到原有的slice。如今1.1.0在newCollection的時候並不複製slice,而是在須要對slice進行亂序或者變動操做的時候進行一次Copy操做。而我把Copy操做的時間也放到各個具體實現類中了。函數
因而ICollection多實現了一個Copy方法,它會把當前Collection的Slice複製一份出來。而後在AbsCollection中記錄一個是否已經拷貝的標記,isCopied,對於那些對原數組進行操做的方法會根據這個標記,若是以前沒有複製,就複製一份,再進行操做性能
func (arr *AbsCollection) Insert(index int, obj interface{}) ICollection { if arr.Err() != nil { return arr } if arr.Parent == nil { panic("no parent") } if arr.isCopied == false { arr.Copy() arr.isCopied = true } return arr.Parent.Insert(index, obj) }
這樣就實現了延遲拷貝的功能。優化
這個方法和Index方法是對應的,將數組的某個元素進行設置。code
這個方法的具體實現也在實現類中實現了,特別是對ObjCollection的SetIndex實現仍是須要reflect進行繞的,其餘的COllection不須要使用反射。排序
func (arr *ObjCollection) SetIndex(i int, val interface{}) ICollection { arr.objs.Index(i).Set(reflect.ValueOf(val)) return arr }
這個是這個issue提出的 https://github.com/jianfengye/collection/issues/9get
以前的Sort我是使用冒泡排序實現的,確實效率有欠考慮。
此次將Sort進行了快排實現。因爲已經又了SetIndex, Index, 等方法,因此能夠這個快排能夠直接在AbsCollection中實現就好了。
func (arr *AbsCollection) qsort(left, right int, isAscOrder bool) { tmp := arr.Index(left) p := left i, j := left, right for i <= j { for j >= p { c, err := arr.Index(j).Compare(tmp) if err != nil { arr.SetErr(err) return } if isAscOrder && c >= 0 { j-- continue } if !isAscOrder && c <= 0 { j-- continue } break } if j >= p { t, _ := arr.Index(j).ToInterface() arr.SetIndex(p, t) p = j } for i <= p { c, err := arr.Index(i).Compare(tmp) if err != nil { arr.SetErr(err) return } if isAscOrder && c <= 0 { i++ continue } if !isAscOrder && c >= 0 { i++ continue } break } if i <= p { t, _ := arr.Index(i).ToInterface() arr.SetIndex(p, t) p = i } } t, _ := tmp.ToInterface() arr.SetIndex(p, t) if p-left > 1 { arr.qsort(left, p-1, isAscOrder) } if right-p > 1 { arr.qsort(p+1, right, isAscOrder) } } func (arr *AbsCollection) Sort() ICollection { if arr.Err() != nil { return arr } if arr.compare == nil { return arr.SetErr(errors.New("sort: compare must be set")) } if arr.isCopied { arr.qsort(0, arr.Count()-1, true) return arr } arr.Copy() return arr.Sort() }
以前IMix的compare函數必定都須要調用SetCompare才能設置,如今若是這個IMix是從Collection進行建立的,好比Collection.Index(xx) IMix, 返回的IMix就直接將Collection中設置的compare函數直接傳遞過來。
這樣在使用過程當中方便了很多。
我也將各個類型的compare函數都整理在具體實現類的頭部
func compareInt32(i interface{}, i2 interface{}) int func compareInt64(i interface{}, i2 interface{}) int func compareInt(i interface{}, i2 interface{}) int func compareString(a interface{}, b interface{}) int ...
1.1.0版本主要是根據issue反饋修復了一些使用和性能上的優化點。整體以爲已經能夠發一個小版本了,因而打上了1.1.0的tag。
該項目目前也有277個star了,歡迎在業務上試用 jianfengye/collection(https://github.com/jianfengye/collection) 這個包,有問題請直接提issue,我會盡快響應。