From c35f873d3a42f01c325f377d9be981eea66024e7 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 16 Apr 2018 21:01:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90garray=E5=B9=B6=E5=8F=91?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E6=95=B0=E7=BB=84=E5=8C=85=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/garray/garray.go | 1 + g/container/garray/garray_int.go | 35 +++- g/container/garray/garray_interface.go | 107 +++++++++++ g/container/garray/garray_sorted_int.go | 181 ++++++++++++++++++ g/container/garray/garray_sorted_interface.go | 52 ++++- g/container/garray/garray_sorted_string.go | 176 +++++++++++++++++ g/container/garray/garray_string.go | 107 +++++++++++ 7 files changed, 647 insertions(+), 12 deletions(-) create mode 100644 g/container/garray/garray_interface.go create mode 100644 g/container/garray/garray_sorted_int.go create mode 100644 g/container/garray/garray_sorted_string.go create mode 100644 g/container/garray/garray_string.go diff --git a/g/container/garray/garray.go b/g/container/garray/garray.go index 02f068216..15bf65e3c 100644 --- a/g/container/garray/garray.go +++ b/g/container/garray/garray.go @@ -5,4 +5,5 @@ // You can obtain one at https://gitee.com/johng/gf. // 并发安全的数组. +// 底层使用通用的interface{}类型,从性能上考虑,类似于gmap那样可以为每种类型都定义一个array. package garray diff --git a/g/container/garray/garray_int.go b/g/container/garray/garray_int.go index e58e2dc0a..a966e7e16 100644 --- a/g/container/garray/garray_int.go +++ b/g/container/garray/garray_int.go @@ -9,13 +9,17 @@ package garray import "sync" type IntArray struct { - mu sync.RWMutex // 互斥锁 - array []int // 底层数组 + mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 + array []int // 底层数组 } func NewIntArray(size int, cap ... int) *IntArray { - a := &IntArray{} + a := &IntArray{} + a.size = size if len(cap) > 0 { + a.cap = cap[0] a.array = make([]int, size, cap[0]) } else { a.array = make([]int, size) @@ -76,3 +80,28 @@ func (a *IntArray) Slice() []int { a.mu.RUnlock() return array } + +// 清空数据数组 +func (a *IntArray) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]int, a.size, a.cap) + } else { + a.array = make([]int, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *IntArray) LockFunc(f func(array []int)) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *IntArray) RLockFunc(f func(array []int)) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() +} diff --git a/g/container/garray/garray_interface.go b/g/container/garray/garray_interface.go new file mode 100644 index 000000000..53ef5671c --- /dev/null +++ b/g/container/garray/garray_interface.go @@ -0,0 +1,107 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package garray + +import "sync" + +type Array struct { + mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 + array []interface{} // 底层数组 +} + +func NewArray(size int, cap ... int) *Array { + a := &Array{} + a.size = size + if len(cap) > 0 { + a.cap = cap[0] + a.array = make([]interface{}, size, cap[0]) + } else { + a.array = make([]interface{}, size) + } + return a +} + +// 获取指定索引的数据项, 调用方注意判断数组边界 +func (a *Array) Get(index int) interface{} { + a.mu.RLock() + value := a.array[index] + a.mu.RUnlock() + return value +} + +// 设置指定索引的数据项, 调用方注意判断数组边界 +func (a *Array) Set(index int, value interface{}) { + a.mu.Lock() + a.array[index] = value + a.mu.Unlock() +} + +// 在当前索引位置前插入一个数据项, 调用方注意判断数组边界 +func (a *Array) Insert(index int, value interface{}) { + a.mu.Lock() + rear := append([]interface{}{}, a.array[index : ]...) + a.array = append(a.array[0 : index], value) + a.array = append(a.array, rear...) + a.mu.Unlock() +} + +// 删除指定索引的数据项, 调用方注意判断数组边界 +func (a *Array) Remove(index int) { + a.mu.Lock() + a.array = append(a.array[ : index], a.array[index + 1 : ]...) + a.mu.RUnlock() +} + +// 追加数据项 +func (a *Array) Append(value interface{}) { + a.mu.Lock() + a.array = append(a.array, value) + a.mu.Unlock() +} + +// 数组长度 +func (a *Array) Len() int { + a.mu.RLock() + length := len(a.array) + a.mu.RUnlock() + return length +} + +// 返回原始数据数组 +func (a *Array) Slice() []interface{} { + a.mu.RLock() + array := a.array + a.mu.RUnlock() + return array +} + +// 清空数据数组 +func (a *Array) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]interface{}, a.size, a.cap) + } else { + a.array = make([]interface{}, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *Array) LockFunc(f func(array []interface{})) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *Array) RLockFunc(f func(array []interface{})) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() +} diff --git a/g/container/garray/garray_sorted_int.go b/g/container/garray/garray_sorted_int.go new file mode 100644 index 000000000..495a45708 --- /dev/null +++ b/g/container/garray/garray_sorted_int.go @@ -0,0 +1,181 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package garray + +import ( + "sync" + "gitee.com/johng/gf/g/container/gtype" +) + +// 默认按照从低到高进行排序 +type SortedIntArray struct { + mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 + array []int // 底层数组 + unique *gtype.Bool // 是否要求不能重复 + compareFunc func(v1, v2 int) int // 比较函数,返回值 -1: v1 < v2;0: v1 == v2;1: v1 > v2 +} + +func NewSortedIntArray(size int, cap ... int) *SortedIntArray { + a := &SortedIntArray { + unique : gtype.NewBool(), + compareFunc : func(v1, v2 int) int { + if v1 < v2 { + return -1 + } + if v1 > v2 { + return 1 + } + return 0 + }, + } + a.size = size + if len(cap) > 0 { + a.cap = cap[0] + a.array = make([]int, size, cap[0]) + } else { + a.array = make([]int, size) + } + return a +} + +// 添加加数据项 +func (a *SortedIntArray) Add(value int) { + index, cmp := a.Search(value) + if a.unique.Val() && cmp == 0 { + return + } + if index < 0 { + a.mu.Lock() + a.array = append(a.array, value) + a.mu.Unlock() + return + } + // 加到指定索引后面 + if cmp > 0 { + index++ + } + a.mu.Lock() + rear := append([]int{}, a.array[index : ]...) + a.array = append(a.array[0 : index], value) + a.array = append(a.array, rear...) + a.mu.Unlock() +} + +// 获取指定索引的数据项, 调用方注意判断数组边界 +func (a *SortedIntArray) Get(index int) int { + a.mu.RLock() + value := a.array[index] + a.mu.RUnlock() + return value +} + +// 删除指定索引的数据项, 调用方注意判断数组边界 +func (a *SortedIntArray) Remove(index int) { + a.mu.Lock() + a.array = append(a.array[ : index], a.array[index + 1 : ]...) + a.mu.RUnlock() +} + +// 数组长度 +func (a *SortedIntArray) Len() int { + a.mu.RLock() + length := len(a.array) + a.mu.RUnlock() + return length +} + +// 返回原始数据数组 +func (a *SortedIntArray) Slice() []int { + a.mu.RLock() + array := a.array + a.mu.RUnlock() + return array +} + +// 查找指定数值的索引位置,返回索引位置(具体匹配位置或者最后对比位置)及查找结果 +func (a *SortedIntArray) Search(value int) (int, int) { + if len(a.array) == 0 { + return -1, -2 + } + a.mu.RLock() + min := 0 + max := len(a.array) - 1 + mid := 0 + cmp := -2 + for { + if cmp == 0 || min > max { + break + } + for { + mid = int((min + max) / 2) + cmp = a.compareFunc(value, a.array[mid]) + switch cmp { + case -1 : max = mid - 1 + case 0 : + case 1 : min = mid + 1 + } + if cmp == 0 || min > max { + break + } + } + } + a.mu.RUnlock() + return mid, cmp +} + +// 设置是否允许数组唯一 +func (a *SortedIntArray) SetUnique(unique bool) { + oldUnique := a.unique.Val() + a.unique.Set(unique) + if unique && oldUnique != unique { + a.doUnique() + } +} + +// 清理数组中重复的元素项 +func (a *SortedIntArray) doUnique() { + a.mu.Lock() + i := 0 + for { + if i == len(a.array) - 1 { + break + } + if a.compareFunc(a.array[i], a.array[i + 1]) == 0 { + a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...) + } else { + i++ + } + } + a.mu.Unlock() +} + +// 清空数据数组 +func (a *SortedIntArray) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]int, a.size, a.cap) + } else { + a.array = make([]int, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *SortedIntArray) LockFunc(f func(array []int)) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *SortedIntArray) RLockFunc(f func(array []int)) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() +} \ No newline at end of file diff --git a/g/container/garray/garray_sorted_interface.go b/g/container/garray/garray_sorted_interface.go index 7207bab68..6c76eddd0 100644 --- a/g/container/garray/garray_sorted_interface.go +++ b/g/container/garray/garray_sorted_interface.go @@ -14,6 +14,8 @@ import ( // 默认按照从低到高进行排序 type SortedArray struct { mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 array []interface{} // 底层数组 unique *gtype.Bool // 是否要求不能重复 compareFunc func(v1, v2 interface{}) int // 比较函数,返回值 -1: v1 < v2;0: v1 == v2;1: v1 > v2 @@ -112,21 +114,53 @@ func (a *SortedArray) Search(value interface{}) (int, int) { return mid, cmp } +// 设置是否允许数组唯一 +func (a *SortedArray) SetUnique(unique bool) { + oldUnique := a.unique.Val() + a.unique.Set(unique) + if unique && oldUnique != unique { + a.doUnique() + } +} + // 清理数组中重复的元素项 -func (a *SortedArray) DoUnique() { +func (a *SortedArray) doUnique() { a.mu.Lock() - for i := 0; ; i ++ { + i := 0 + for { if i == len(a.array) - 1 { break } - for { - if a.compareFunc(a.array[i], a.array[i + 1]) == 0 { - a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...) - } else { - break - } + if a.compareFunc(a.array[i], a.array[i + 1]) == 0 { + a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...) + } else { + i++ } - } a.mu.Unlock() +} + +// 清空数据数组 +func (a *SortedArray) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]interface{}, a.size, a.cap) + } else { + a.array = make([]interface{}, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *SortedArray) LockFunc(f func(array []interface{})) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *SortedArray) RLockFunc(f func(array []interface{})) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() } \ No newline at end of file diff --git a/g/container/garray/garray_sorted_string.go b/g/container/garray/garray_sorted_string.go new file mode 100644 index 000000000..b4dfff8da --- /dev/null +++ b/g/container/garray/garray_sorted_string.go @@ -0,0 +1,176 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package garray + +import ( + "sync" + "gitee.com/johng/gf/g/container/gtype" + "strings" +) + +// 默认按照从低到高进行排序 +type SortedStringArray struct { + mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 + array []string // 底层数组 + unique *gtype.Bool // 是否要求不能重复 + compareFunc func(v1, v2 string) int // 比较函数,返回值 -1: v1 < v2;0: v1 == v2;1: v1 > v2 +} + +func NewSortedStringArray(size int, cap ... int) *SortedStringArray { + a := &SortedStringArray { + unique : gtype.NewBool(), + compareFunc : func(v1, v2 string) int { + return strings.Compare(v1, v2) + }, + } + a.size = size + if len(cap) > 0 { + a.cap = cap[0] + a.array = make([]string, size, cap[0]) + } else { + a.array = make([]string, size) + } + return a +} + +// 添加加数据项 +func (a *SortedStringArray) Add(value string) { + index, cmp := a.Search(value) + if a.unique.Val() && cmp == 0 { + return + } + if index < 0 { + a.mu.Lock() + a.array = append(a.array, value) + a.mu.Unlock() + return + } + // 加到指定索引后面 + if cmp > 0 { + index++ + } + a.mu.Lock() + rear := append([]string{}, a.array[index : ]...) + a.array = append(a.array[0 : index], value) + a.array = append(a.array, rear...) + a.mu.Unlock() +} + +// 获取指定索引的数据项, 调用方注意判断数组边界 +func (a *SortedStringArray) Get(index int) string { + a.mu.RLock() + value := a.array[index] + a.mu.RUnlock() + return value +} + +// 删除指定索引的数据项, 调用方注意判断数组边界 +func (a *SortedStringArray) Remove(index int) { + a.mu.Lock() + a.array = append(a.array[ : index], a.array[index + 1 : ]...) + a.mu.RUnlock() +} + +// 数组长度 +func (a *SortedStringArray) Len() int { + a.mu.RLock() + length := len(a.array) + a.mu.RUnlock() + return length +} + +// 返回原始数据数组 +func (a *SortedStringArray) Slice() []string { + a.mu.RLock() + array := a.array + a.mu.RUnlock() + return array +} + +// 查找指定数值的索引位置,返回索引位置(具体匹配位置或者最后对比位置)及查找结果 +func (a *SortedStringArray) Search(value string) (int, int) { + if len(a.array) == 0 { + return -1, -2 + } + a.mu.RLock() + min := 0 + max := len(a.array) - 1 + mid := 0 + cmp := -2 + for { + if cmp == 0 || min > max { + break + } + for { + mid = int((min + max) / 2) + cmp = a.compareFunc(value, a.array[mid]) + switch cmp { + case -1 : max = mid - 1 + case 0 : + case 1 : min = mid + 1 + } + if cmp == 0 || min > max { + break + } + } + } + a.mu.RUnlock() + return mid, cmp +} + +// 设置是否允许数组唯一 +func (a *SortedStringArray) SetUnique(unique bool) { + oldUnique := a.unique.Val() + a.unique.Set(unique) + if unique && oldUnique != unique { + a.doUnique() + } +} + +// 清理数组中重复的元素项 +func (a *SortedStringArray) doUnique() { + a.mu.Lock() + i := 0 + for { + if i == len(a.array) - 1 { + break + } + if a.compareFunc(a.array[i], a.array[i + 1]) == 0 { + a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...) + } else { + i++ + } + } + a.mu.Unlock() +} + +// 清空数据数组 +func (a *SortedStringArray) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]string, a.size, a.cap) + } else { + a.array = make([]string, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *SortedStringArray) LockFunc(f func(array []string)) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *SortedStringArray) RLockFunc(f func(array []string)) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() +} \ No newline at end of file diff --git a/g/container/garray/garray_string.go b/g/container/garray/garray_string.go new file mode 100644 index 000000000..b4c07d90c --- /dev/null +++ b/g/container/garray/garray_string.go @@ -0,0 +1,107 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package garray + +import "sync" + +type StringArray struct { + mu sync.RWMutex // 互斥锁 + cap int // 初始化设置的数组容量 + size int // 初始化设置的数组大小 + array []string // 底层数组 +} + +func NewStringArray(size int, cap ... int) *StringArray { + a := &StringArray{} + a.size = size + if len(cap) > 0 { + a.cap = cap[0] + a.array = make([]string, size, cap[0]) + } else { + a.array = make([]string, size) + } + return a +} + +// 获取指定索引的数据项, 调用方注意判断数组边界 +func (a *StringArray) Get(index int) string { + a.mu.RLock() + value := a.array[index] + a.mu.RUnlock() + return value +} + +// 设置指定索引的数据项, 调用方注意判断数组边界 +func (a *StringArray) Set(index int, value string) { + a.mu.Lock() + a.array[index] = value + a.mu.Unlock() +} + +// 在当前索引位置前插入一个数据项, 调用方注意判断数组边界 +func (a *StringArray) Insert(index int, value string) { + a.mu.Lock() + rear := append([]string{}, a.array[index : ]...) + a.array = append(a.array[0 : index], value) + a.array = append(a.array, rear...) + a.mu.Unlock() +} + +// 删除指定索引的数据项, 调用方注意判断数组边界 +func (a *StringArray) Remove(index int) { + a.mu.Lock() + a.array = append(a.array[ : index], a.array[index + 1 : ]...) + a.mu.RUnlock() +} + +// 追加数据项 +func (a *StringArray) Append(value string) { + a.mu.Lock() + a.array = append(a.array, value) + a.mu.Unlock() +} + +// 数组长度 +func (a *StringArray) Len() int { + a.mu.RLock() + length := len(a.array) + a.mu.RUnlock() + return length +} + +// 返回原始数据数组 +func (a *StringArray) Slice() []string { + a.mu.RLock() + array := a.array + a.mu.RUnlock() + return array +} + +// 清空数据数组 +func (a *StringArray) Clear() { + a.mu.Lock() + if a.cap > 0 { + a.array = make([]string, a.size, a.cap) + } else { + a.array = make([]string, a.size) + } + a.mu.Unlock() +} + +// 使用自定义方法执行加锁修改操作 +func (a *StringArray) LockFunc(f func(array []string)) { + a.mu.Lock() + f(a.array) + a.mu.Unlock() +} + +// 使用自定义方法执行加锁读取操作 +func (a *StringArray) RLockFunc(f func(array []string)) { + a.mu.RLock() + f(a.array) + a.mu.RUnlock() +}