From b5f86a488c4e70f680d96860c31a26f68962abe4 Mon Sep 17 00:00:00 2001 From: Faucherwind Date: Thu, 3 Aug 2023 15:05:30 +0800 Subject: [PATCH] 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 --- datastructure/list/copyonwritelist.go | 68 ++++++++++++- datastructure/list/copyonwritelist_test.go | 111 ++++++++++++++++++++- 2 files changed, 171 insertions(+), 8 deletions(-) diff --git a/datastructure/list/copyonwritelist.go b/datastructure/list/copyonwritelist.go index 0fbd382..915bdbd 100644 --- a/datastructure/list/copyonwritelist.go +++ b/datastructure/list/copyonwritelist.go @@ -2,6 +2,7 @@ package datastructure import ( "reflect" + "sort" "sync" ) @@ -39,12 +40,12 @@ func (c *CopyOnWriteList[T]) Contain(e T) bool { } // 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 { +func (c *CopyOnWriteList[T]) ValueOf(index int) (*T, bool) { list := c.getList() if index < 0 || index >= len(c.data) { - return nil + return nil, false } - return get(list, index) + 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. @@ -107,7 +108,6 @@ 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) @@ -288,3 +288,63 @@ func (c *CopyOnWriteList[T]) Equal(other *[]T) bool { } 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 +} diff --git a/datastructure/list/copyonwritelist_test.go b/datastructure/list/copyonwritelist_test.go index 54c1609..fdd84fd 100644 --- a/datastructure/list/copyonwritelist_test.go +++ b/datastructure/list/copyonwritelist_test.go @@ -9,11 +9,15 @@ func TestCopyOnWriteList_ValueOf(t *testing.T) { list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf") - of := list.ValueOf(3) + of, ok := list.ValueOf(3) assert.Equal(4, *of) + assert.Equal(true, ok) + + _, ok = list.ValueOf(6) + assert.Equal(false, ok) } -func TestCopyOnWriteList_Contains(t *testing.T) { +func TestCopyOnWriteList_Contain(t *testing.T) { list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) assert := internal.NewAssert(t, "CopyOnWriteList_Contains") assert.Equal(true, list.Contain(3)) @@ -25,7 +29,7 @@ func TestCopyOnWriteList_IsEmpty(t *testing.T) { assert.Equal(true, list.IsEmpty()) } -func TestCopyOnWriteList_size(t *testing.T) { +func TestCopyOnWriteList_Size(t *testing.T) { list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) assert := internal.NewAssert(t, "CopyOnWriteList_size") assert.Equal(5, list.Size()) @@ -49,6 +53,14 @@ func TestCopyOnWriteList_Set(t *testing.T) { assert := internal.NewAssert(t, "CopyOnWriteList_Set") list.Set(2, 6) assert.Equal(6, list.getList()[2]) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.Set(0, 6) + assert.Equal(6, list.getList()[0]) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.Set(0, 1) + assert.Equal(1, list.getList()[0]) } func TestCopyOnWriteList_Add(t *testing.T) { @@ -70,6 +82,14 @@ func TestCopyOnWriteList_AddByIndex(t *testing.T) { assert := internal.NewAssert(t, "CopyOnWriteList_AddByIndex") list.AddByIndex(2, 6) assert.Equal([]int{1, 2, 6, 3, 4, 5}, list.getList()) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.AddByIndex(0, 6) + assert.Equal([]int{6, 1, 2, 3, 4, 5}, list.getList()) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.AddByIndex(5, 6) + assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList()) } func TestCopyOnWriteList_DeleteAt2(t *testing.T) { @@ -77,6 +97,10 @@ func TestCopyOnWriteList_DeleteAt2(t *testing.T) { assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByIndex") list.DeleteAt(2) assert.Equal([]int{1, 2, 4, 5}, list.getList()) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.DeleteAt(4) + assert.Equal([]int{1, 2, 3, 4}, list.getList()) } func TestCopyOnWriteList_RemoveByValue(t *testing.T) { @@ -86,11 +110,15 @@ func TestCopyOnWriteList_RemoveByValue(t *testing.T) { assert.Equal([]int{1, 2, 4, 5}, list.getList()) } -func TestCopyOnWriteList_RemoveRange(t *testing.T) { +func TestCopyOnWriteList_DeleteRange(t *testing.T) { list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) assert := internal.NewAssert(t, "CopyOnWriteList_RemoveRange") list.DeleteRange(1, 3) assert.Equal([]int{1, 4, 5}, list.getList()) + + list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5}) + list.DeleteRange(0, 5) + assert.Equal([]int{}, list.getList()) } func TestCopyOnWriteList_LastIndexOf(t *testing.T) { @@ -130,3 +158,78 @@ func TestCopyOnWriteList_Equal(t *testing.T) { assert.Equal(true, list.Equal(&[]int{1, 2, 3, 4, 5, 3, 6})) } + +func TestCopyOnWriteList_ForEach(t *testing.T) { + testList := make([]int, 0) + list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6}) + assert := internal.NewAssert(t, "CopyOnWriteList_ForEach") + + list.ForEach(func(i int) { + testList = append(testList, i) + }) + assert.Equal([]int{1, 2, 3, 4, 5, 3, 6}, testList) + + list.ForEach(func(i int) { + list.Add(i) + }) + assert.Equal([]int{1, 2, 3, 4, 5, 3, 6, 1, 2, 3, 4, 5, 3, 6}, list.getList()) +} + +func TestCopyOnWriteList_Clear(t *testing.T) { + list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6}) + assert := internal.NewAssert(t, "CopyOnWriteList_Clear") + + list.Clear() + assert.Equal([]int{}, list.getList()) +} + +func TestCopyOnWriteList_Merge(t *testing.T) { + list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9}) + assert := internal.NewAssert(t, "CopyOnWriteList_Merge") + + list.Merge([]int{2, 4, 6, 8, 10}) + assert.Equal([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}, list.getList()) + +} + +func TestCopyOnWriteList_Sort(t *testing.T) { + list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + assert := internal.NewAssert(t, "CopyOnWriteList_Sort") + + list.Sort(func(i, j int) bool { + return i < j + }) + assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, list.getList()) +} + +func TestCopyOnWriteList_IndexOf(t *testing.T) { + list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf") + + assert.Equal(0, list.IndexOf(1)) + assert.Equal(9, list.IndexOf(10)) + assert.Equal(-1, list.IndexOf(11)) +} + +func TestCopyOnWriteList_SubList(t *testing.T) { + list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + + assert := internal.NewAssert(t, "CopyOnWriteList_SubList") + + list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + subList := list.SubList(1, 3) + assert.Equal([]int{3, 5}, subList) + + list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + subList = list.SubList(1, 1) + assert.Equal([]int{}, subList) + + list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + assert.Equal(10, list.Size()) + subList = list.SubList(1, 10) + assert.Equal([]int{3, 5, 7, 9, 2, 4, 6, 8, 10}, subList) + + list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}) + subList = list.SubList(11, 1) + assert.Equal([]int{}, subList) +}