1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00
Files
lancet/datastructure/list/copyonwritelist.go
Faucherwind b5f86a488c feat: CopyOnWriteList adds more functions such as ForEach, Sort... (#126)
* feat: CopyOnWriteList adds more functions such as ForEach, Sort

* feat: CopyOnWriteList adds more functions such as ForEach, Sort
2023-08-03 15:05:30 +08:00

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
}