From 3020e4e6ebf51282e8e5082058d2288df7a77198 Mon Sep 17 00:00:00 2001 From: storezhang Date: Thu, 28 Nov 2024 18:36:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=98=9F=E5=88=97):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- collection.go | 1 + go.mod | 8 +++ internal/kernel/collection.go | 4 +- internal/kernel/queue.go | 3 +- queue.go | 1 + queue/internal/builder/queue.go | 22 ++++++-- queue/internal/{ => core}/blocking.go | 31 +++++++---- queue/internal/core/default.go | 53 +++++++++++++++++++ .../{ => core/internal}/priority/items.go | 0 .../{ => core/internal}/priority/priority.go | 0 queue/internal/param/queue.go | 6 ++- queue/new.go | 4 +- queue/new_test.go | 13 +++++ queue/priority.go | 23 -------- 14 files changed, 126 insertions(+), 43 deletions(-) rename queue/internal/{ => core}/blocking.go (63%) create mode 100644 queue/internal/core/default.go rename queue/internal/{ => core/internal}/priority/items.go (100%) rename queue/internal/{ => core/internal}/priority/priority.go (100%) create mode 100644 queue/new_test.go delete mode 100644 queue/priority.go diff --git a/collection.go b/collection.go index fe958da..224adab 100644 --- a/collection.go +++ b/collection.go @@ -4,4 +4,5 @@ import ( "github.com/goexl/collection/internal/kernel" ) +// Collection 集合 type Collection = kernel.Collection diff --git a/go.mod b/go.mod index 2ce441c..9177d86 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module github.com/goexl/collection go 1.23 + +require github.com/stretchr/testify v1.10.0 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/internal/kernel/collection.go b/internal/kernel/collection.go index e047d82..a64d149 100644 --- a/internal/kernel/collection.go +++ b/internal/kernel/collection.go @@ -1,7 +1,9 @@ package kernel -// Collection 集合 type Collection interface { // Size 大小 Size() int + + // Empty 是否为空 + Empty() bool } diff --git a/internal/kernel/queue.go b/internal/kernel/queue.go index 07f5b46..0e815c1 100644 --- a/internal/kernel/queue.go +++ b/internal/kernel/queue.go @@ -1,6 +1,5 @@ package kernel -// Queue 队列 type Queue[T any] interface { Collection @@ -8,5 +7,5 @@ type Queue[T any] interface { Enqueue(T, ...T) // Dequeue 出队 - Dequeue() []T + Dequeue() T } diff --git a/queue.go b/queue.go index 46e0f20..1e5ec6b 100644 --- a/queue.go +++ b/queue.go @@ -4,4 +4,5 @@ import ( "github.com/goexl/collection/internal/kernel" ) +// Queue 队列 type Queue[T any] = kernel.Queue[T] diff --git a/queue/internal/builder/queue.go b/queue/internal/builder/queue.go index 5c9841b..6120601 100644 --- a/queue/internal/builder/queue.go +++ b/queue/internal/builder/queue.go @@ -2,11 +2,13 @@ package builder import ( "github.com/goexl/collection/internal/kernel" + "github.com/goexl/collection/queue/internal/core" "github.com/goexl/collection/queue/internal/param" ) type Queue[T any] struct { params *param.Queue + queue kernel.Queue[T] } func NewQueue[T any]() *Queue[T] { @@ -15,13 +17,25 @@ func NewQueue[T any]() *Queue[T] { } } -func (b *Queue[T]) Capacity(capacity int) (blocking *Queue[T]) { - b.params.Capacity = capacity - blocking = b +func (q *Queue[T]) Blocking() (queue *Queue[T]) { + q.queue = core.NewBlocking[T](q.params) + queue = q return } -func (b *Queue[T]) Build() *kernel.Queue[T] { +func (q *Queue[T]) Capacity(capacity int) (queue *Queue[T]) { + q.params.Capacity = capacity + queue = q + + return +} + +func (q *Queue[T]) Build() (queue kernel.Queue[T]) { + if nil == q.queue { + q.queue = core.NewDefault[T](q.params) + } + queue = q.queue + return } diff --git a/queue/internal/blocking.go b/queue/internal/core/blocking.go similarity index 63% rename from queue/internal/blocking.go rename to queue/internal/core/blocking.go index 7fce7aa..a479927 100644 --- a/queue/internal/blocking.go +++ b/queue/internal/core/blocking.go @@ -1,6 +1,7 @@ -package internal +package core import ( + "container/list" "sync" "github.com/goexl/collection/internal/kernel" @@ -10,7 +11,7 @@ import ( var _ kernel.Queue[int] = (*Blocking[int])(nil) type Blocking[T any] struct { - data []T + items *list.List mutex *sync.Mutex cond *sync.Cond @@ -19,7 +20,7 @@ type Blocking[T any] struct { func NewBlocking[T any](params *param.Queue) (blocking *Blocking[T]) { blocking = new(Blocking[T]) - blocking.data = make([]T, 0, params.Capacity) + blocking.items = list.New() blocking.mutex = new(sync.Mutex) blocking.cond = sync.NewCond(blocking.mutex) @@ -33,27 +34,37 @@ func (b *Blocking[T]) Enqueue(required T, optionals ...T) { defer b.mutex.Unlock() items := append([]T{required}, optionals...) - for len(b.data)+len(items) > b.params.Capacity { + for b.items.Len()+len(items) > b.params.Capacity { b.cond.Wait() } - b.data = append(b.data, items...) + for _, item := range items { + b.items.PushBack(item) + } b.cond.Broadcast() } -func (b *Blocking[T]) Dequeue() (items []T) { +func (b *Blocking[T]) Dequeue() (item T) { b.mutex.Lock() defer b.mutex.Unlock() - for len(b.data) == 0 { + for 0 == b.items.Len() { b.cond.Wait() } - items = b.data[:] - b.data = make([]T, 0, b.params.Capacity) + + if 0 != b.items.Len() { + element := b.items.Front() + b.items.Remove(element) + item = element.Value.(T) + } b.cond.Broadcast() return } func (b *Blocking[T]) Size() int { - return len(b.data) + return b.items.Len() +} + +func (b *Blocking[T]) Empty() bool { + return 0 == b.items.Len() } diff --git a/queue/internal/core/default.go b/queue/internal/core/default.go new file mode 100644 index 0000000..9a16acc --- /dev/null +++ b/queue/internal/core/default.go @@ -0,0 +1,53 @@ +package core + +import ( + "container/list" + + "github.com/goexl/collection/internal/kernel" + "github.com/goexl/collection/queue/internal/param" +) + +var _ kernel.Queue[int] = (*Default[int])(nil) + +type Default[T any] struct { + items *list.List + params *param.Queue +} + +func NewDefault[T any](params *param.Queue) *Default[T] { + return &Default[T]{ + items: list.New(), + params: params, + } +} + +func (q *Default[T]) Enqueue(required T, optionals ...T) { + q.enqueue(required) + for _, optional := range optionals { + q.enqueue(optional) + } +} + +func (q *Default[T]) Dequeue() (item T) { + if 0 != q.items.Len() { + element := q.items.Front() + q.items.Remove(element) + item = element.Value.(T) + } + + return +} + +func (q *Default[T]) Empty() bool { + return 0 == q.items.Len() +} + +func (q *Default[T]) Size() int { + return q.items.Len() +} + +func (q *Default[T]) enqueue(item T) { + for q.params.Capacity > q.items.Len() { + q.items.PushBack(item) + } +} diff --git a/queue/internal/priority/items.go b/queue/internal/core/internal/priority/items.go similarity index 100% rename from queue/internal/priority/items.go rename to queue/internal/core/internal/priority/items.go diff --git a/queue/internal/priority/priority.go b/queue/internal/core/internal/priority/priority.go similarity index 100% rename from queue/internal/priority/priority.go rename to queue/internal/core/internal/priority/priority.go diff --git a/queue/internal/param/queue.go b/queue/internal/param/queue.go index 7890307..7aec6d2 100644 --- a/queue/internal/param/queue.go +++ b/queue/internal/param/queue.go @@ -1,11 +1,15 @@ package param +import ( + "math" +) + type Queue struct { Capacity int } func NewQueue() *Queue { return &Queue{ - Capacity: 16, + Capacity: math.MaxInt, } } diff --git a/queue/new.go b/queue/new.go index 6bbcc5b..f373781 100644 --- a/queue/new.go +++ b/queue/new.go @@ -4,6 +4,6 @@ import ( "github.com/goexl/collection/queue/internal/builder" ) -func New(T any) *builder.Queue[T] { - +func New[T any]() *builder.Queue[T] { + return builder.NewQueue[T]() } diff --git a/queue/new_test.go b/queue/new_test.go new file mode 100644 index 0000000..fabf15a --- /dev/null +++ b/queue/new_test.go @@ -0,0 +1,13 @@ +package queue_test + +import ( + "testing" + + "github.com/goexl/collection/queue" + "github.com/stretchr/testify/require" +) + +func TestNew(t *testing.T) { + _queue := queue.New[int]().Build() + require.NotNil(t, _queue, "默认队列创建出错") +} diff --git a/queue/priority.go b/queue/priority.go deleted file mode 100644 index 1e38af9..0000000 --- a/queue/priority.go +++ /dev/null @@ -1,23 +0,0 @@ -package queue - -import ( - "container/heap" - - "github.com/goexl/collection/internal/kernel" - "github.com/goexl/collection/queue/internal/priority" -) - -var _ kernel.Queue[int] = (*Priority)(nil) - -// Priority 优先级队列 -type Priority[T kernel.Ranker] struct { - items priority.Items[T] -} - -func NewPriority[T kernel.Ranker]() (priority *Priority[T]) { - priority = new(Priority[T]) - priority.items = make([]priority.Items[T], 0) - heap.Init(&priority.items) - - return -}