mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
Allow users to apply functional predicates alongside 'index of' and 'last index of' search methods in this specialized list variant
380 lines
9.0 KiB
Go
380 lines
9.0 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
|
|
}
|
|
|
|
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying the
|
|
// functional predicate f(T) bool
|
|
// if not found return -1.
|
|
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int {
|
|
index := -1
|
|
data := l.getList()
|
|
for i := len(data) - 1; i >= 0; i-- {
|
|
if f(data[i]) {
|
|
index = i
|
|
break
|
|
}
|
|
}
|
|
return index
|
|
}
|
|
|
|
// IndexOfFunc returns the first index satisfying the functional predicate f(v) bool
|
|
// if not found return -1.
|
|
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int {
|
|
index := -1
|
|
data := l.getList()
|
|
for i, v := range data {
|
|
if f(v) {
|
|
index = i
|
|
break
|
|
}
|
|
}
|
|
return index
|
|
}
|
|
|
|
// 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
|
|
}
|