mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
* feat: CopyOnWriteList adds more functions such as ForEach, Sort * feat: CopyOnWriteList adds more functions such as ForEach, Sort
351 lines
8.4 KiB
Go
351 lines
8.4 KiB
Go
package datastructure
|
|
|
|
import (
|
|
"reflect"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
type CopyOnWriteList[T any] struct {
|
|
data []T
|
|
lock sync.Locker
|
|
}
|
|
|
|
// NewCopyOnWriteList Creates an empty list.
|
|
func NewCopyOnWriteList[T any](data []T) *CopyOnWriteList[T] {
|
|
return &CopyOnWriteList[T]{data: data, lock: &sync.RWMutex{}}
|
|
}
|
|
|
|
func (c *CopyOnWriteList[T]) getList() []T {
|
|
return c.data
|
|
}
|
|
func (c *CopyOnWriteList[T]) setList(data []T) {
|
|
c.data = data
|
|
}
|
|
|
|
// Size returns the number of elements in this list.
|
|
func (c *CopyOnWriteList[T]) Size() int {
|
|
return len(c.getList())
|
|
}
|
|
|
|
// IsEmpty returns true if this list contains no elements.
|
|
func (c *CopyOnWriteList[T]) IsEmpty() bool {
|
|
return c.Size() == 0
|
|
}
|
|
|
|
// Contain returns true if this list contains the specified element.
|
|
func (c *CopyOnWriteList[T]) Contain(e T) bool {
|
|
list := c.getList()
|
|
return indexOf(e, list, 0, c.Size()) >= 0
|
|
}
|
|
|
|
// ValueOf returns the index of the first occurrence of the specified element in this list, or null if this list does not contain the element.
|
|
func (c *CopyOnWriteList[T]) ValueOf(index int) (*T, bool) {
|
|
list := c.getList()
|
|
if index < 0 || index >= len(c.data) {
|
|
return nil, false
|
|
}
|
|
return get(list, index), true
|
|
}
|
|
|
|
// IndexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
|
func (c *CopyOnWriteList[T]) IndexOf(e T) int {
|
|
list := c.getList()
|
|
return indexOf(e, list, 0, c.Size())
|
|
}
|
|
|
|
// indexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
|
// start the start position of the search (inclusive)
|
|
// end the end position of the search (exclusive)
|
|
func indexOf[T any](o T, e []T, start int, end int) int {
|
|
if start >= end {
|
|
return -1
|
|
}
|
|
for i := start; i < end; i++ {
|
|
if reflect.DeepEqual(e[i], o) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// LastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
|
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int {
|
|
list := c.getList()
|
|
return lastIndexOf(e, list, 0, c.Size())
|
|
}
|
|
|
|
// lastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
|
// start the start position of the search (inclusive)
|
|
// end the end position of the search (exclusive)
|
|
func lastIndexOf[T any](o T, e []T, start int, end int) int {
|
|
if start >= end {
|
|
return -1
|
|
}
|
|
for i := end - 1; i >= start; i-- {
|
|
if reflect.DeepEqual(e[i], o) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// get returns the element at the specified position in this list.
|
|
func get[T any](o []T, index int) *T {
|
|
return &o[index]
|
|
}
|
|
|
|
// Get returns the element at the specified position in this list.
|
|
func (c *CopyOnWriteList[T]) Get(index int) *T {
|
|
list := c.getList()
|
|
if index < 0 || index >= len(list) {
|
|
return nil
|
|
}
|
|
return get(list, index)
|
|
}
|
|
|
|
func (c *CopyOnWriteList[T]) set(index int, e T) (oldValue *T) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
list := c.getList()
|
|
oldValue = get(list, index)
|
|
|
|
if reflect.DeepEqual(oldValue, e) {
|
|
c.setList(list)
|
|
} else {
|
|
newList := make([]T, len(list))
|
|
copy(newList, list)
|
|
newList[index] = e
|
|
c.setList(newList)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Set replaces the element at the specified position in this list with the specified element.
|
|
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool) {
|
|
list := c.getList()
|
|
if index < 0 || index >= len(list) {
|
|
return oldValue, false
|
|
}
|
|
return c.set(index, e), true
|
|
}
|
|
|
|
// Add appends the specified element to the end of this list.
|
|
func (c *CopyOnWriteList[T]) Add(e T) bool {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
newList := make([]T, len(list)+1)
|
|
copy(newList, list)
|
|
newList[len(list)] = e
|
|
c.setList(newList)
|
|
return true
|
|
}
|
|
|
|
// AddAll appends all the elements in the specified collection to the end of this list
|
|
func (c *CopyOnWriteList[T]) AddAll(e []T) bool {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
newList := make([]T, len(list)+len(e))
|
|
copy(newList, list)
|
|
copy(newList[len(list):], e)
|
|
c.setList(newList)
|
|
return true
|
|
}
|
|
|
|
// AddByIndex inserts the specified element at the specified position in this list.
|
|
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
length := len(list)
|
|
if index < 0 || index > length {
|
|
return false
|
|
}
|
|
var newList []T
|
|
var numMove = length - index
|
|
if numMove == 0 {
|
|
newList = make([]T, length+1)
|
|
copy(newList, list)
|
|
} else {
|
|
newList = make([]T, length+1)
|
|
copy(newList, list[:index])
|
|
copy(newList[index+1:], list[index:])
|
|
}
|
|
newList[index] = e
|
|
c.setList(newList)
|
|
return true
|
|
}
|
|
|
|
// delete removes the element at the specified position in this list.
|
|
func (c *CopyOnWriteList[T]) delete(index int) *T {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
length := len(list)
|
|
|
|
oldValue := get(list, index)
|
|
numMove := length - index - 1
|
|
var newList []T
|
|
if numMove == 0 {
|
|
newList = make([]T, length-1)
|
|
copy(newList, list[:index])
|
|
} else {
|
|
newList = make([]T, length-1)
|
|
copy(newList, list[:index])
|
|
copy(newList[index:], list[index+1:])
|
|
}
|
|
|
|
c.setList(newList)
|
|
return oldValue
|
|
}
|
|
|
|
// DeleteAt removes the element at the specified position in this list.
|
|
func (c *CopyOnWriteList[T]) DeleteAt(index int) (*T, bool) {
|
|
list := c.getList()
|
|
if index < 0 || index >= len(list) {
|
|
return nil, false
|
|
}
|
|
return c.delete(index), true
|
|
}
|
|
|
|
// DeleteBy removes the first occurrence of the specified element from this list, if it is present.
|
|
func (c *CopyOnWriteList[T]) DeleteBy(o T) (*T, bool) {
|
|
list := c.getList()
|
|
index := indexOf(o, list, 0, len(list))
|
|
if index == -1 {
|
|
return nil, false
|
|
}
|
|
return c.delete(index), true
|
|
}
|
|
|
|
// DeleteRange removes from this list all the elements whose index is between fromIndex, inclusive, and toIndex, exclusive.
|
|
// left close and right open
|
|
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
length := len(list)
|
|
if start < 0 || end > length || start > end {
|
|
return
|
|
}
|
|
var newList []T
|
|
numMove := length - end
|
|
if numMove == 0 {
|
|
newList = make([]T, length-(end-start))
|
|
copy(newList, list[:start])
|
|
} else {
|
|
newList = make([]T, length-(end-start))
|
|
copy(newList, list[:start])
|
|
copy(newList[start:], list[end:])
|
|
}
|
|
c.setList(newList)
|
|
}
|
|
|
|
// DeleteIf removes all the elements of this collection that satisfy the given predicate.
|
|
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
length := len(list)
|
|
var newList []T
|
|
for i := 0; i < length; i++ {
|
|
if !f(list[i]) {
|
|
newList = append(newList, list[i])
|
|
}
|
|
}
|
|
c.setList(newList)
|
|
}
|
|
|
|
// Equal returns true if the specified object is equal to this list.
|
|
func (c *CopyOnWriteList[T]) Equal(other *[]T) bool {
|
|
if other == nil {
|
|
return false
|
|
}
|
|
if c.Size() != len(*other) {
|
|
return false
|
|
}
|
|
list := c.getList()
|
|
otherList := NewCopyOnWriteList(*other).getList()
|
|
for i := 0; i < len(list); i++ {
|
|
if !reflect.DeepEqual(list[i], otherList[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Clear removes all the elements from this list.
|
|
func (c *CopyOnWriteList[T]) Clear() {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
list = make([]T, 0)
|
|
c.setList(list)
|
|
}
|
|
|
|
// Merge a tow list to one, change the list
|
|
func (c *CopyOnWriteList[T]) Merge(other []T) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
list := c.getList()
|
|
list = append(list, other...)
|
|
c.setList(list)
|
|
}
|
|
|
|
// ForEach performs the given action for each element of the Iterable until all elements have been processed
|
|
// or the action throws an exception.
|
|
func (c *CopyOnWriteList[T]) ForEach(f func(T)) {
|
|
list := c.getList()
|
|
for i := 0; i < len(list); i++ {
|
|
f(list[i])
|
|
}
|
|
|
|
}
|
|
|
|
// Sort sorts this list according to the order induced by the specified Comparator.
|
|
func (c *CopyOnWriteList[T]) Sort(compare func(o1 T, o2 T) bool) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
list := c.getList()
|
|
|
|
sort.Slice(list, func(i, j int) bool {
|
|
return compare(list[i], list[j])
|
|
})
|
|
|
|
c.setList(list)
|
|
}
|
|
|
|
func (c *CopyOnWriteList[T]) SubList(start int, end int) (newList []T) {
|
|
lock := c.lock
|
|
lock.Lock()
|
|
list := c.getList()
|
|
length := len(list)
|
|
defer lock.Unlock()
|
|
if start < 0 || end > length || start > end {
|
|
return []T{}
|
|
}
|
|
newList = make([]T, end-start)
|
|
copy(newList, list[start:end])
|
|
c.setList(newList)
|
|
return
|
|
}
|