This commit is contained in:
tursom 2022-04-23 11:53:41 +08:00
parent 8fe538eb7e
commit 0c0db78b2f
16 changed files with 533 additions and 551 deletions

View File

@ -27,27 +27,35 @@ func NewArrayListByCapacity[T lang.Object](cap int) *ArrayList[T] {
}
}
func (a ArrayList[T]) String() string {
func (a *ArrayList[T]) String() string {
return String[T](a)
}
func (a ArrayList[T]) Iterator() Iterator[T] {
func (a *ArrayList[T]) Iterator() Iterator[T] {
return a.MutableIterator()
}
func (a ArrayList[T]) Size() int {
func (a *ArrayList[T]) ListIterator() ListIterator[T] {
return a.MutableListIterator()
}
func (a *ArrayList[T]) MutableListIterator() MutableListIterator[T] {
return &arrayListIterator[T]{a, 0}
}
func (a *ArrayList[T]) Size() int {
return lang.Len(a.array)
}
func (a ArrayList[T]) IsEmpty() bool {
func (a *ArrayList[T]) IsEmpty() bool {
return a.Size() == 0
}
func (a ArrayList[T]) Contains(element T) bool {
func (a *ArrayList[T]) Contains(element T) bool {
return Contains[T](a, element)
}
func (a ArrayList[T]) ContainsAll(c Collection[T]) bool {
func (a *ArrayList[T]) ContainsAll(c Collection[T]) bool {
return ContainsAll[T](a, c)
}
@ -56,7 +64,7 @@ func (a *ArrayList[T]) Add(element T) bool {
return true
}
func (a ArrayList[T]) IndexOf(element T) int {
func (a *ArrayList[T]) IndexOf(element T) int {
for i := 0; i < a.Size(); i++ {
if lang.Equals(element, a.array[i]) {
return i
@ -90,7 +98,7 @@ func (a *ArrayList[T]) Clear() {
a.array = []T{}
}
func (a ArrayList[T]) Get(index int) (T, exceptions.Exception) {
func (a *ArrayList[T]) Get(index int) (T, exceptions.Exception) {
if index >= a.Size() {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
} else {
@ -98,8 +106,8 @@ func (a ArrayList[T]) Get(index int) (T, exceptions.Exception) {
}
}
func (a ArrayList[T]) SubList(from, to int) List[T] {
return NewSubList[T](a, from, to)
func (a *ArrayList[T]) SubList(from, to int) List[T] {
return a.SubMutableList(from, to)
}
func (a *ArrayList[T]) Set(index int, element T) exceptions.Exception {
@ -131,7 +139,9 @@ func (a *ArrayList[T]) RemoveAt(index int) exceptions.Exception {
}
func (a *ArrayList[T]) SubMutableList(from, to int) MutableList[T] {
return NewMutableSubList[T](a, from, to)
return &ArrayList[T]{
array: a.array[from:to],
}
}
func (a *ArrayList[T]) MutableIterator() MutableIterator[T] {
@ -164,3 +174,37 @@ func (a *arrayListIterator[T]) Remove() exceptions.Exception {
a.index--
return nil
}
func (a *arrayListIterator[T]) HasPrevious() bool {
return a.index > 0
}
func (a *arrayListIterator[T]) Previous() (T, exceptions.Exception) {
if a.index <= 0 || a.index >= len(a.arrayList.array) {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
a.index--
return a.arrayList.array[a.index], a.arrayList.RemoveAt(a.index)
}
func (a *arrayListIterator[T]) NextIndex() int {
return a.index
}
func (a *arrayListIterator[T]) PreviousIndex() int {
return a.index - 1
}
func (a *arrayListIterator[T]) Set(value T) exceptions.Exception {
if a.index <= 0 {
return exceptions.NewIndexOutOfBound("", nil)
}
a.arrayList.array[a.index-1] = value
return nil
}
func (a *arrayListIterator[T]) Add(value T) exceptions.Exception {
a.arrayList.AddAtIndex(a.index, value)
a.index++
return nil
}

View File

@ -2,18 +2,19 @@ package collections
import (
"fmt"
"strings"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"strings"
)
type (
Collection[T any] interface {
Iterable[T]
Collection[E any] interface {
Iterable[E]
Size() int
IsEmpty() bool
Contains(element T) bool
ContainsAll(c Collection[T]) bool
Contains(element E) bool
ContainsAll(c Collection[E]) bool
}
MutableCollection[T any] interface {
@ -33,6 +34,7 @@ type (
Get(index int) (T, exceptions.Exception)
SubList(from, to int) List[T]
ListIterator() ListIterator[T]
}
MutableList[T any] interface {
@ -43,6 +45,7 @@ type (
AddAtIndex(index int, element T) bool
RemoveAt(index int) exceptions.Exception
SubMutableList(from, to int) MutableList[T]
MutableListIterator() MutableListIterator[T]
}
)

View File

@ -1,168 +0,0 @@
package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/lang/atomic"
)
type (
ConcurrentLinkedQueueNode[T lang.Object] interface {
Get() (T, exceptions.Exception)
Remove() exceptions.Exception
RemoveAndGet() (T, exceptions.Exception)
}
ConcurrentLinkedQueue[T lang.Object] struct {
lang.BaseObject
ConcurrentLinkedStack[T]
end *concurrentLinkedStackNode[T]
}
concurrentLinkedQueueIterator[T lang.Object] struct {
node *concurrentLinkedStackNode[T]
queue *ConcurrentLinkedQueue[T]
}
)
func (q *ConcurrentLinkedQueue[T]) String() string {
return String[T](q)
}
func NewConcurrentLinkedQueue[T lang.Object]() *ConcurrentLinkedQueue[T] {
return &ConcurrentLinkedQueue[T]{}
}
func (q *ConcurrentLinkedQueue[T]) Iterator() Iterator[T] {
return q.MutableIterator()
}
func (q *ConcurrentLinkedQueue[T]) Offer(element T) exceptions.Exception {
_, err := q.offerAndGetNode(element)
return err
}
func (q *ConcurrentLinkedQueue[T]) OfferAndGetNode(element T) (ConcurrentLinkedQueueNode[T], exceptions.Exception) {
newNode, err := q.offerAndGetNode(element)
if err != nil {
return nil, err
}
return &concurrentLinkedQueueIterator[T]{queue: q, node: newNode}, nil
}
func (q *ConcurrentLinkedQueue[T]) offerAndGetNode(element T) (*concurrentLinkedStackNode[T], exceptions.Exception) {
newNode := &concurrentLinkedStackNode[T]{value: element}
q.size.Add(1)
var next **concurrentLinkedStackNode[T]
ref := q.end
switch {
case ref == nil:
next = &q.head
default:
next = &ref.next
}
for !atomic.CompareAndSwapPointer(next, nil, newNode) {
if ref == nil || ref.next == nil {
next = &q.head
ref = q.head
} else {
for ref.next != nil {
ref = ref.next
}
next = &ref.next
}
}
q.end = newNode
return newNode, nil
}
func (q *ConcurrentLinkedQueue[T]) Poll() (T, exceptions.Exception) {
return q.Pop()
}
func (q *ConcurrentLinkedQueue[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedQueueIterator[T]{queue: q, node: q.head}
}
func (q *ConcurrentLinkedQueue[T]) Size() int {
return int(q.size.Load())
}
func (q *ConcurrentLinkedQueue[T]) IsEmpty() bool {
return q.head == nil
}
func (q *ConcurrentLinkedQueue[T]) Contains(element T) bool {
return Contains[T](q, element)
}
func (q *ConcurrentLinkedQueue[T]) ContainsAll(collection Collection[T]) bool {
return ContainsAll[T](q, collection)
}
func (q *ConcurrentLinkedQueue[T]) Add(element T) bool {
exception := q.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (q *ConcurrentLinkedQueue[T]) Remove(element T) exceptions.Exception {
return Remove[T](q, element)
}
func (q *ConcurrentLinkedQueue[T]) AddAll(collection Collection[T]) bool {
return AddAll[T](q, collection)
}
func (q *ConcurrentLinkedQueue[T]) RemoveAll(collection Collection[T]) bool {
return RemoveAll[T](q, collection)
}
func (q *ConcurrentLinkedQueue[T]) RetainAll(collection Collection[T]) bool {
return RetainAll[T](q, collection)
}
func (q *ConcurrentLinkedQueue[T]) Clear() {
q.head = nil
q.end = nil
q.size.Store(0)
}
func (i *concurrentLinkedQueueIterator[T]) HasNext() bool {
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return i.node != nil
}
func (i *concurrentLinkedQueueIterator[T]) Next() (T, exceptions.Exception) {
value, err := i.Get()
i.node = i.node.next
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return value, err
}
func (i *concurrentLinkedQueueIterator[T]) Get() (T, exceptions.Exception) {
return (*i.node).value, nil
}
func (i *concurrentLinkedQueueIterator[T]) Remove() exceptions.Exception {
_, err := i.RemoveAndGet()
return err
}
func (i *concurrentLinkedQueueIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), nil
}
load := i.node
load.deleted = true
i.queue.size.Add(-1)
i.queue.deleted.Add(1)
i.queue.CleanDeleted()
i.node = load.next
return load.value, nil
}

View File

@ -1,148 +0,0 @@
package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/lang/atomic"
)
type (
ConcurrentLinkedStack[T lang.Object] struct {
lang.BaseObject
size atomic.Int32
deleted atomic.Int32
head *concurrentLinkedStackNode[T]
}
concurrentLinkedStackNode[T any] struct {
deleted bool
next *concurrentLinkedStackNode[T]
value T
}
concurrentLinkedStackIterator[T lang.Object] struct {
node *concurrentLinkedStackNode[T]
stack *ConcurrentLinkedStack[T]
}
)
func (s *ConcurrentLinkedStack[T]) String() string {
return String[T](s)
}
func NewConcurrentLinkedStack[T lang.Object]() *ConcurrentLinkedStack[T] {
return &ConcurrentLinkedStack[T]{}
}
func (s *ConcurrentLinkedStack[T]) Iterator() Iterator[T] {
return s.MutableIterator()
}
func (s *ConcurrentLinkedStack[T]) Push(element T) exceptions.Exception {
newNode := &concurrentLinkedStackNode[T]{value: element, next: s.head}
for !atomic.CompareAndSwapPointer(&s.head, newNode.next, newNode) {
newNode.next = s.head
}
s.size.Add(1)
return nil
}
func (s *ConcurrentLinkedStack[T]) Pop() (T, exceptions.Exception) {
node := s.head
for node != nil && (!atomic.CompareAndSwapPointer(&s.head, node, node.next) || node.deleted) {
node = s.head
}
if node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
s.size.Add(-1)
return node.value, nil
}
func (s *ConcurrentLinkedStack[T]) CleanDeleted() {
if s.deleted.Load() <= s.size.Load() {
return
}
s.deleted.Store(0)
node := &s.head
for node != nil && *node != nil {
if (*node).deleted {
atomic.CompareAndSwapPointer(node, *node, (*node).next)
} else {
node = &(*node).next
}
}
}
func (s *ConcurrentLinkedStack[T]) Size() int {
return int(s.size.Load())
}
func (s *ConcurrentLinkedStack[T]) IsEmpty() bool {
return s.head == nil
}
func (s *ConcurrentLinkedStack[T]) Contains(element T) bool {
return Contains[T](s, element)
}
func (s *ConcurrentLinkedStack[T]) ContainsAll(c Collection[T]) bool {
return ContainsAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) Add(element T) bool {
exception := s.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (s *ConcurrentLinkedStack[T]) Remove(element T) exceptions.Exception {
return Remove[T](s, element)
}
func (s *ConcurrentLinkedStack[T]) AddAll(c Collection[T]) bool {
return AddAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) RemoveAll(c Collection[T]) bool {
return RemoveAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) RetainAll(c Collection[T]) bool {
return RetainAll[T](s, c)
}
func (s *ConcurrentLinkedStack[T]) Clear() {
s.head = nil
s.size.Store(0)
}
func (s *ConcurrentLinkedStack[T]) MutableIterator() MutableIterator[T] {
return &concurrentLinkedStackIterator[T]{s.head, nil}
}
func (i *concurrentLinkedStackIterator[T]) HasNext() bool {
return i.node.next != nil
}
func (i *concurrentLinkedStackIterator[T]) Next() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
value := i.node.value
i.node = i.node.next
return value, nil
}
func (i *concurrentLinkedStackIterator[T]) Remove() exceptions.Exception {
if i.node == nil {
return exceptions.NewIndexOutOfBound("", nil)
}
i.node.deleted = true
i.node = i.node.next
i.stack.size.Add(-1)
i.stack.deleted.Add(1)
i.stack.CleanDeleted()
return nil
}

View File

@ -1,26 +1,58 @@
package collections
import "github.com/tursom/GoCollections/exceptions"
import "github.com/tursom/GoCollections/lang"
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type Iterator[T any] interface {
HasNext() bool
Next() (T, exceptions.Exception)
}
type (
// Iterator an iterator over a collection or another entity that can be represented as a sequence of elements.
// Allows to sequentially access the elements
Iterator[T any] interface {
// HasNext return true if the iterator has more elements
HasNext() bool
// Next returns the next element in the iteration
// return exceptions.IndexOutOfBound if there is no more element
Next() (T, exceptions.Exception)
}
type Iterable[T any] interface {
Iterator() Iterator[T]
}
// MutableIterator an iterator over a mutable collection.
// Provides the ability to remove elements while iterating.
MutableIterator[T any] interface {
Iterator[T]
// Remove removes from the underlying collection the last element returned by this iterator.
Remove() exceptions.Exception
}
type MutableIterator[T any] interface {
Iterator[T]
Remove() exceptions.Exception
}
// ListIterator an iterator over a collection that supports indexed access
ListIterator[T any] interface {
Iterator[T]
HasPrevious() bool
Previous() (T, exceptions.Exception)
NextIndex() int
PreviousIndex() int
}
type MutableIterable[T any] interface {
Iterable[T]
MutableIterator() MutableIterator[T]
}
// MutableListIterator an iterator over a mutable collection that supports indexed access
// Provides the ability to add, modify and remove elements while iterating.
MutableListIterator[T any] interface {
ListIterator[T]
MutableIterator[T]
Set(value T) exceptions.Exception
Add(value T) exceptions.Exception
}
// Iterable classes that inherit from this interface can be represented as a sequence of elements that can be iterated over.
// param T
Iterable[T any] interface {
Iterator() Iterator[T]
}
MutableIterable[T any] interface {
Iterable[T]
MutableIterator() MutableIterator[T]
}
)
func Loop[T any](iterable Iterable[T], f func(element T) exceptions.Exception) exceptions.Exception {
if f == nil || iterable == nil {

View File

@ -1,97 +0,0 @@
package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type MutableSubList[T lang.Object] struct {
lang.BaseObject
list MutableList[T]
from, to int
}
func NewMutableSubList[T lang.Object](list MutableList[T], from, to int) *MutableSubList[T] {
return &MutableSubList[T]{lang.NewBaseObject(), list, from, to}
}
func (s *MutableSubList[T]) Iterator() Iterator[T] {
iterator := s.list.Iterator()
for i := 0; i < s.from; i++ {
_, err := iterator.Next()
if err != nil {
return nil
}
}
return iterator
}
func (s *MutableSubList[T]) Size() int {
return s.to - s.from
}
func (s *MutableSubList[T]) IsEmpty() bool {
return s.Size() == 0
}
func (s *MutableSubList[T]) Contains(element T) bool {
return Contains[T](s, element)
}
func (s *MutableSubList[T]) ContainsAll(c Collection[T]) bool {
return ContainsAll[T](s, c)
}
func (s *MutableSubList[T]) Get(index int) (T, exceptions.Exception) {
return s.list.Get(index + s.from)
}
func (s *MutableSubList[T]) SubList(from, to int) List[T] {
return NewSubList[T](s, from, to)
}
func (s *MutableSubList[T]) MutableIterator() MutableIterator[T] {
return nil
}
func (s *MutableSubList[T]) Add(_ T) bool {
return false
}
func (s *MutableSubList[T]) Remove(element T) exceptions.Exception {
return nil
}
func (s *MutableSubList[T]) AddAll(_ Collection[T]) bool {
return false
}
func (s *MutableSubList[T]) RemoveAll(_ Collection[T]) bool {
return false
}
func (s *MutableSubList[T]) RetainAll(_ Collection[T]) bool {
return false
}
func (s *MutableSubList[T]) Clear() {
}
func (s *MutableSubList[T]) Set(index int, element T) exceptions.Exception {
if index >= s.to-s.from {
return exceptions.NewIndexOutOfBound("", nil)
}
return s.list.Set(index+s.from, element)
}
func (s *MutableSubList[T]) AddAtIndex(_ int, _ T) bool {
return false
}
func (s *MutableSubList[T]) RemoveAt(index int) exceptions.Exception {
return exceptions.NewOperationNotSupportedException("", nil)
}
func (s *MutableSubList[T]) SubMutableList(from, to int) MutableList[T] {
return NewMutableSubList[T](s.list, s.from+from, to)
}

View File

@ -5,9 +5,14 @@ import (
"github.com/tursom/GoCollections/lang"
)
type Queue[T lang.Object] interface {
MutableIterable[T]
type (
Queue[T lang.Object] interface {
MutableIterable[T]
Offer(element T) exceptions.Exception
Poll() (T, exceptions.Exception)
}
Offer(element T) exceptions.Exception
OfferAndGetNode(element T) (QueueNode[T], exceptions.Exception)
Poll() (T, exceptions.Exception)
}
QueueNode[T lang.Object] = StackNode[T]
)

View File

@ -1,10 +1,23 @@
package collections
import "github.com/tursom/GoCollections/exceptions"
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type Stack[T any] interface {
MutableIterable[T]
type (
Stack[T any] interface {
MutableIterable[T]
Push(element T) exceptions.Exception
Pop() (T, exceptions.Exception)
}
Push(element T) exceptions.Exception
PushAndGetNode(element T) (StackNode[T], exceptions.Exception)
Pop() (T, exceptions.Exception)
}
StackNode[T lang.Object] interface {
Set(value T) exceptions.Exception
Get() (T, exceptions.Exception)
Remove() exceptions.Exception
RemoveAndGet() (T, exceptions.Exception)
}
)

View File

@ -1,51 +0,0 @@
package collections
import (
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type SubList[T lang.Object] struct {
lang.BaseObject
list List[T]
from, to int
}
func NewSubList[T lang.Object](list List[T], from, to int) *SubList[T] {
return &SubList[T]{lang.NewBaseObject(), list, from, to}
}
func (s *SubList[T]) Iterator() Iterator[T] {
iterator := s.list.Iterator()
for i := 0; i < int(s.from); i++ {
_, err := iterator.Next()
if err != nil {
return nil
}
}
return iterator
}
func (s *SubList[T]) Size() int {
return s.to - s.from
}
func (s *SubList[T]) IsEmpty() bool {
return s.Size() == 0
}
func (s *SubList[T]) Contains(element T) bool {
return Contains[T](s, element)
}
func (s *SubList[T]) ContainsAll(c Collection[T]) bool {
return ContainsAll[T](s, c)
}
func (s *SubList[T]) Get(index int) (T, exceptions.Exception) {
return s.list.Get(index + s.from)
}
func (s *SubList[T]) SubList(from, to int) List[T] {
return NewSubList[T](s, from, to)
}

View File

@ -1,36 +1,38 @@
package collections
package concurrent
import (
"github.com/tursom/GoCollections/concurrent"
"sync"
"github.com/tursom/GoCollections/collections"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync"
)
type (
// GoSyncMap an map use go sync.Map to store hash slot
GoSyncMap[K lang.Object, V any] struct {
NodeMap[K, V]
collections.NodeMap[K, V]
m sync.Map
lock concurrent.RWLock
lock RWLock
}
)
func NewGoSyncMap[K lang.Object, V any]() *GoSyncMap[K, V] {
m := &GoSyncMap[K, V]{lock: &sync.RWMutex{}}
m.MapNodeFinder = NewMapNodeFinderBySlot[K, V](m)
m.MapNodeFinder = collections.NewMapNodeFinderBySlot[K, V](m)
return m
}
func (g *GoSyncMap[K, V]) ToString() lang.String {
return MapToString[K, V](g)
return collections.MapToString[K, V](g)
}
func (g *GoSyncMap[K, V]) findSlot(k K) MapNode[K, V] {
func (g *GoSyncMap[K, V]) findSlot(k K) collections.MapNode[K, V] {
hashCode := lang.HashCode(k)
p, _ := g.m.Load(hashCode)
root := lang.Cast[*SimpleMapNode[K, V]](p)
root := lang.Cast[*collections.SimpleMapNode[K, V]](p)
if root == nil {
root = &SimpleMapNode[K, V]{}
root = &collections.SimpleMapNode[K, V]{}
g.m.Store(hashCode, root)
}
return root

168
concurrent/LinkedQueue.go Normal file
View File

@ -0,0 +1,168 @@
package concurrent
import (
"github.com/tursom/GoCollections/collections"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/lang/atomic"
)
type (
LinkedQueue[T lang.Object] struct {
lang.BaseObject
LinkedStack[T]
end *linkedStackNode[T]
}
linkedQueueIterator[T lang.Object] struct {
node *linkedStackNode[T]
queue *LinkedQueue[T]
}
)
func (q *LinkedQueue[T]) String() string {
return collections.String[T](q)
}
func NewLinkedQueue[T lang.Object]() *LinkedQueue[T] {
return &LinkedQueue[T]{}
}
func (q *LinkedQueue[T]) Iterator() collections.Iterator[T] {
return q.MutableIterator()
}
func (q *LinkedQueue[T]) Offer(element T) exceptions.Exception {
_, err := q.offerAndGetNode(element)
return err
}
func (q *LinkedQueue[T]) OfferAndGetNode(element T) (collections.QueueNode[T], exceptions.Exception) {
newNode, err := q.offerAndGetNode(element)
if err != nil {
return nil, err
}
return &linkedQueueIterator[T]{queue: q, node: newNode}, nil
}
func (q *LinkedQueue[T]) offerAndGetNode(element T) (*linkedStackNode[T], exceptions.Exception) {
newNode := &linkedStackNode[T]{value: element}
q.size.Add(1)
var next **linkedStackNode[T]
ref := q.end
switch {
case ref == nil:
next = &q.head
default:
next = &ref.next
}
for !atomic.CompareAndSwapPointer(next, nil, newNode) {
if ref == nil || ref.next == nil {
next = &q.head
ref = q.head
} else {
for ref.next != nil {
ref = ref.next
}
next = &ref.next
}
}
q.end = newNode
return newNode, nil
}
func (q *LinkedQueue[T]) Poll() (T, exceptions.Exception) {
return q.Pop()
}
func (q *LinkedQueue[T]) MutableIterator() collections.MutableIterator[T] {
return &linkedQueueIterator[T]{queue: q, node: q.head}
}
func (q *LinkedQueue[T]) Size() int {
return int(q.size.Load())
}
func (q *LinkedQueue[T]) IsEmpty() bool {
return q.head == nil
}
func (q *LinkedQueue[T]) Contains(element T) bool {
return collections.Contains[T](q, element)
}
func (q *LinkedQueue[T]) ContainsAll(collection collections.Collection[T]) bool {
return collections.ContainsAll[T](q, collection)
}
func (q *LinkedQueue[T]) Add(element T) bool {
exception := q.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (q *LinkedQueue[T]) Remove(element T) exceptions.Exception {
return collections.Remove[T](q, element)
}
func (q *LinkedQueue[T]) AddAll(collection collections.Collection[T]) bool {
return collections.AddAll[T](q, collection)
}
func (q *LinkedQueue[T]) RemoveAll(collection collections.Collection[T]) bool {
return collections.RemoveAll[T](q, collection)
}
func (q *LinkedQueue[T]) RetainAll(collection collections.Collection[T]) bool {
return collections.RetainAll[T](q, collection)
}
func (q *LinkedQueue[T]) Clear() {
q.head = nil
q.end = nil
q.size.Store(0)
}
func (i *linkedQueueIterator[T]) HasNext() bool {
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return i.node != nil
}
func (i *linkedQueueIterator[T]) Next() (T, exceptions.Exception) {
value, err := i.Get()
i.node = i.node.next
for i.node != nil && i.node.deleted {
i.node = i.node.next
}
return value, err
}
func (i *linkedQueueIterator[T]) Get() (T, exceptions.Exception) {
return i.node.value, nil
}
func (i *linkedQueueIterator[T]) Set(value T) exceptions.Exception {
i.node.value = value
return nil
}
func (i *linkedQueueIterator[T]) Remove() exceptions.Exception {
_, err := i.RemoveAndGet()
return err
}
func (i *linkedQueueIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), nil
}
load := i.node
load.deleted = true
i.queue.size.Add(-1)
i.queue.deleted.Add(1)
i.queue.CleanDeleted()
i.node = load.next
return load.value, nil
}

View File

@ -1,13 +1,14 @@
package collections
package concurrent
import (
"fmt"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync"
"testing"
"time"
"unsafe"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
)
type data struct {
@ -21,12 +22,12 @@ func (d *data) String() string {
}
func TestConcurrentLinkedQueue_NodeSize(t *testing.T) {
fmt.Println(unsafe.Alignof(concurrentLinkedStackNode[*data]{}))
fmt.Println(unsafe.Sizeof(concurrentLinkedStackNode[*data]{}))
fmt.Println(unsafe.Alignof(linkedStackNode[*data]{}))
fmt.Println(unsafe.Sizeof(linkedStackNode[*data]{}))
}
func TestConcurrentLinkedQueue_Push(t *testing.T) {
queue := NewConcurrentLinkedQueue[*data]()
queue := NewLinkedQueue[*data]()
cond := sync.WaitGroup{}
cond.Add(1)
for i := 0; i < 10; i++ {
@ -46,11 +47,11 @@ func TestConcurrentLinkedQueue_Push(t *testing.T) {
func TestConcurrentLinkedQueue_ThreadSafe(t *testing.T) {
times := 400000
queue := NewConcurrentLinkedQueue[*data]()
queue := NewLinkedQueue[*data]()
for i := 0; i < 100; i++ {
id := i
go func() {
//nodes := make([]ConcurrentLinkedQueueNode[*data], 0)
//nodes := make([]QueueNode[*data], 0)
for j := 0; j < times; j++ {
_ = queue.Offer(&data{id: id, index: j})
//node, _ := queue.OfferAndGetNode(&data{id: id, index: j})
@ -81,8 +82,8 @@ func TestConcurrentLinkedQueue_ThreadSafe(t *testing.T) {
}
func Test_concurrentLinkedQueueIterator_Remove(t *testing.T) {
queue := NewConcurrentLinkedQueue[lang.Int]()
nodes := make([]ConcurrentLinkedQueueNode[lang.Int], 0)
queue := NewLinkedQueue[lang.Int]()
nodes := make([]QueueNode[lang.Int], 0)
for i := 0; i < 1000; i++ {
node, _ := queue.OfferAndGetNode(lang.Int(i))
nodes = append(nodes, node)

175
concurrent/LinkedStack.go Normal file
View File

@ -0,0 +1,175 @@
package concurrent
import (
"github.com/tursom/GoCollections/collections"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"github.com/tursom/GoCollections/lang/atomic"
)
type (
LinkedStack[T lang.Object] struct {
lang.BaseObject
size atomic.Int32
deleted atomic.Int32
head *linkedStackNode[T]
}
linkedStackNode[T any] struct {
deleted bool
next *linkedStackNode[T]
value T
}
linkedStackIterator[T lang.Object] struct {
node *linkedStackNode[T]
stack *LinkedStack[T]
}
)
func (s *LinkedStack[T]) String() string {
return collections.String[T](s)
}
func NewLinkedStack[T lang.Object]() *LinkedStack[T] {
return &LinkedStack[T]{}
}
func (s *LinkedStack[T]) Iterator() collections.Iterator[T] {
return s.MutableIterator()
}
func (s *LinkedStack[T]) Push(element T) exceptions.Exception {
s.push(element)
return nil
}
func (s *LinkedStack[T]) PushAndGetNode(element T) collections.StackNode[T] {
return &linkedStackIterator[T]{
node: s.push(element),
stack: s,
}
}
func (s *LinkedStack[T]) push(element T) *linkedStackNode[T] {
newNode := &linkedStackNode[T]{value: element, next: s.head}
for !atomic.CompareAndSwapPointer(&s.head, newNode.next, newNode) {
newNode.next = s.head
}
s.size.Add(1)
return newNode
}
func (s *LinkedStack[T]) Pop() (T, exceptions.Exception) {
node := s.head
for node != nil && (!atomic.CompareAndSwapPointer(&s.head, node, node.next) || node.deleted) {
node = s.head
}
if node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
s.size.Add(-1)
return node.value, nil
}
func (s *LinkedStack[T]) CleanDeleted() {
if s.deleted.Load() <= s.size.Load() {
return
}
s.deleted.Store(0)
node := &s.head
for node != nil && *node != nil {
if (*node).deleted {
atomic.CompareAndSwapPointer(node, *node, (*node).next)
} else {
node = &(*node).next
}
}
}
func (s *LinkedStack[T]) Size() int {
return int(s.size.Load())
}
func (s *LinkedStack[T]) IsEmpty() bool {
return s.head == nil
}
func (s *LinkedStack[T]) Contains(element T) bool {
return collections.Contains[T](s, element)
}
func (s *LinkedStack[T]) ContainsAll(c collections.Collection[T]) bool {
return collections.ContainsAll[T](s, c)
}
func (s *LinkedStack[T]) Add(element T) bool {
exception := s.Push(element)
exceptions.Print(exception)
return exception == nil
}
func (s *LinkedStack[T]) Remove(element T) exceptions.Exception {
return collections.Remove[T](s, element)
}
func (s *LinkedStack[T]) AddAll(c collections.Collection[T]) bool {
return collections.AddAll[T](s, c)
}
func (s *LinkedStack[T]) RemoveAll(c collections.Collection[T]) bool {
return collections.RemoveAll[T](s, c)
}
func (s *LinkedStack[T]) RetainAll(c collections.Collection[T]) bool {
return collections.RetainAll[T](s, c)
}
func (s *LinkedStack[T]) Clear() {
s.head = nil
s.size.Store(0)
}
func (s *LinkedStack[T]) MutableIterator() collections.MutableIterator[T] {
return &linkedStackIterator[T]{s.head, nil}
}
func (i *linkedStackIterator[T]) HasNext() bool {
return i.node.next != nil
}
func (i *linkedStackIterator[T]) Next() (T, exceptions.Exception) {
if i.node == nil {
return lang.Nil[T](), exceptions.NewIndexOutOfBound("", nil)
}
value := i.node.value
i.node = i.node.next
return value, nil
}
func (i *linkedStackIterator[T]) Remove() exceptions.Exception {
if i.node == nil {
return exceptions.NewIndexOutOfBound("", nil)
}
i.node.deleted = true
i.node = i.node.next
i.stack.size.Add(-1)
i.stack.deleted.Add(1)
i.stack.CleanDeleted()
return nil
}
func (i *linkedStackIterator[T]) Get() (T, exceptions.Exception) {
return i.node.value, nil
}
func (i *linkedStackIterator[T]) Set(value T) exceptions.Exception {
i.node.value = value
return nil
}
func (i *linkedStackIterator[T]) RemoveAndGet() (T, exceptions.Exception) {
i.node.deleted = true
return i.node.value, nil
}

View File

@ -1,24 +1,25 @@
package collections
package concurrent
import (
"github.com/tursom/GoCollections/concurrent"
"sync"
"github.com/tursom/GoCollections/collections"
"github.com/tursom/GoCollections/exceptions"
"github.com/tursom/GoCollections/lang"
"sync"
)
type (
LockedMutableList[T lang.Object] struct {
list MutableList[T]
lock concurrent.RWLock
list collections.MutableList[T]
lock RWLock
}
lockedMutableListIterator[T lang.Object] struct {
iterator MutableIterator[T]
lock concurrent.RWLock
iterator collections.MutableIterator[T]
lock RWLock
}
)
func MutableListWithLock[T lang.Object](list MutableList[T]) MutableList[T] {
func MutableListWithLock[T lang.Object](list collections.MutableList[T]) collections.MutableList[T] {
return &LockedMutableList[T]{
list: list,
lock: &sync.RWMutex{},
@ -26,10 +27,10 @@ func MutableListWithLock[T lang.Object](list MutableList[T]) MutableList[T] {
}
func (l *LockedMutableList[T]) String() string {
return String[T](l)
return collections.String[T](l)
}
func (l *LockedMutableList[T]) Iterator() Iterator[T] {
func (l *LockedMutableList[T]) Iterator() collections.Iterator[T] {
return l.MutableIterator()
}
@ -51,14 +52,14 @@ func (l *LockedMutableList[T]) Contains(element T) bool {
return l.list.Contains(element)
}
func (l *LockedMutableList[T]) ContainsAll(c Collection[T]) bool {
func (l *LockedMutableList[T]) ContainsAll(c collections.Collection[T]) bool {
l.lock.RLock()
defer l.lock.RUnlock()
return l.list.ContainsAll(c)
}
func (l *LockedMutableList[T]) MutableIterator() MutableIterator[T] {
func (l *LockedMutableList[T]) MutableIterator() collections.MutableIterator[T] {
return &lockedMutableListIterator[T]{l.list.MutableIterator(), l.lock}
}
@ -76,21 +77,21 @@ func (l *LockedMutableList[T]) Remove(element T) exceptions.Exception {
return l.list.Remove(element)
}
func (l *LockedMutableList[T]) AddAll(c Collection[T]) bool {
func (l *LockedMutableList[T]) AddAll(c collections.Collection[T]) bool {
l.lock.Lock()
defer l.lock.Unlock()
return l.list.AddAll(c)
}
func (l *LockedMutableList[T]) RemoveAll(c Collection[T]) bool {
func (l *LockedMutableList[T]) RemoveAll(c collections.Collection[T]) bool {
l.lock.Lock()
defer l.lock.Unlock()
return l.list.RemoveAll(c)
}
func (l *LockedMutableList[T]) RetainAll(c Collection[T]) bool {
func (l *LockedMutableList[T]) RetainAll(c collections.Collection[T]) bool {
l.lock.Lock()
defer l.lock.Unlock()
@ -111,7 +112,7 @@ func (l *LockedMutableList[T]) Get(index int) (T, exceptions.Exception) {
return l.list.Get(index)
}
func (l *LockedMutableList[T]) SubList(from, to int) List[T] {
func (l *LockedMutableList[T]) SubList(from, to int) collections.List[T] {
return l.SubMutableList(from, to)
}
@ -136,7 +137,7 @@ func (l *LockedMutableList[T]) RemoveAt(index int) exceptions.Exception {
return l.list.RemoveAt(index)
}
func (l *LockedMutableList[T]) SubMutableList(from, to int) MutableList[T] {
func (l *LockedMutableList[T]) SubMutableList(from, to int) collections.MutableList[T] {
return &LockedMutableList[T]{l.list.SubMutableList(from, to), l.lock}
}

View File

@ -116,8 +116,8 @@ func PackagePanic(panic any, exceptionMessage string) Exception {
}
switch panic.(type) {
case error:
return NewRuntimeException("", DefaultExceptionConfig().SetCause(panic))
return NewRuntimeException(exceptionMessage, DefaultExceptionConfig().SetCause(panic))
default:
return NewRuntimeException("", DefaultExceptionConfig())
return NewPackageException(panic, nil)
}
}

View File

@ -33,12 +33,14 @@ func (p *PackageException) Err() any {
func UnpackException(err any) any {
for err != nil {
switch err.(type) {
switch e := err.(type) {
case *PackageException:
err = err.(*PackageException).Err()
return err
return e.Err()
case Exception:
err = err.(Exception).Cause()
err = e.Cause()
if err == nil {
return e
}
default:
return err
}