mirror of
https://github.com/tursom/GoCollections.git
synced 2024-12-27 17:10:25 +08:00
178 lines
3.8 KiB
Go
178 lines
3.8 KiB
Go
/*
|
|
* Copyright (c) 2022 tursom. All rights reserved.
|
|
* Use of this source code is governed by a GPL-3
|
|
* license that can be found in the LICENSE file.
|
|
*/
|
|
|
|
package collections
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/tursom/GoCollections/exceptions"
|
|
"github.com/tursom/GoCollections/lang"
|
|
)
|
|
|
|
type (
|
|
MapLooper[K lang.Object, V any] interface {
|
|
Loop(func(K, V) exceptions.Exception) exceptions.Exception
|
|
}
|
|
|
|
Map[K lang.Object, V any] interface {
|
|
MapLooper[K, V]
|
|
Get(k K) (V, bool, exceptions.Exception)
|
|
}
|
|
|
|
MutableMap[K lang.Object, V any] interface {
|
|
Map[K, V]
|
|
Put(k K, v V) (bool, exceptions.Exception)
|
|
Remove(k K) (V, bool, exceptions.Exception)
|
|
}
|
|
|
|
MapNodeFinder[K lang.Object, V any] interface {
|
|
findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V])
|
|
}
|
|
|
|
MapSlotFinder[K lang.Object, V any] interface {
|
|
FindSlot(k K) (root MapNode[K, V])
|
|
}
|
|
|
|
MapNode[K lang.Object, V any] interface {
|
|
GetKey() K
|
|
GetValue() V
|
|
SetValue(value V)
|
|
CreateNext(key K) MapNode[K, V]
|
|
GetNext() MapNode[K, V]
|
|
RemoveNext()
|
|
}
|
|
|
|
SimpleMapNode[K lang.Object, V any] struct {
|
|
lang.BaseObject
|
|
key K
|
|
value V
|
|
next *SimpleMapNode[K, V]
|
|
}
|
|
|
|
NodeMap[K lang.Object, V any] struct {
|
|
lang.BaseObject
|
|
MapNodeFinder MapNodeFinder[K, V]
|
|
}
|
|
|
|
MapNodeFinderBySlot[K lang.Object, V any] struct {
|
|
lang.BaseObject
|
|
slotFinder MapSlotFinder[K, V]
|
|
}
|
|
)
|
|
|
|
func NewMapNodeFinderBySlot[K lang.Object, V any](slotFinder MapSlotFinder[K, V]) MapNodeFinder[K, V] {
|
|
return &MapNodeFinderBySlot[K, V]{slotFinder: slotFinder}
|
|
}
|
|
|
|
func MapToString[K lang.Object, V any](m MapLooper[K, V]) lang.String {
|
|
builder := strings.Builder{}
|
|
builder.WriteString("{")
|
|
_ = m.Loop(func(k K, v V) exceptions.Exception {
|
|
if builder.Len() != 1 {
|
|
builder.WriteString(", ")
|
|
}
|
|
builder.WriteString(k.String())
|
|
builder.WriteString(": ")
|
|
if ov, ok := lang.TryCast[lang.Object](v); ok {
|
|
builder.WriteString(ov.String())
|
|
} else {
|
|
builder.WriteString(fmt.Sprint(v))
|
|
}
|
|
return nil
|
|
})
|
|
builder.WriteString("}")
|
|
return lang.NewString(builder.String())
|
|
}
|
|
|
|
func (g *NodeMap[K, V]) findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V]) {
|
|
return g.MapNodeFinder.findNode(k, createIfNotExist)
|
|
}
|
|
|
|
func (g *NodeMap[K, V]) Put(k K, v V) (bool, exceptions.Exception) {
|
|
node, _ := g.findNode(k, true)
|
|
node.SetValue(v)
|
|
return true, nil
|
|
}
|
|
|
|
func (g *NodeMap[K, V]) Get(k K) (V, bool, exceptions.Exception) {
|
|
node, _ := g.findNode(k, false)
|
|
if node == nil {
|
|
return g.nil()
|
|
} else {
|
|
return node.GetValue(), true, nil
|
|
}
|
|
}
|
|
|
|
func (g *NodeMap[K, V]) Remove(k K) (V, bool, exceptions.Exception) {
|
|
node, prev := g.findNode(k, false)
|
|
if node == nil {
|
|
return g.nil()
|
|
} else {
|
|
if prev != nil {
|
|
prev.RemoveNext()
|
|
}
|
|
return node.GetValue(), true, nil
|
|
}
|
|
}
|
|
|
|
func (g *NodeMap[K, V]) nil() (V, bool, exceptions.Exception) {
|
|
return lang.Nil[V](), false, nil
|
|
}
|
|
|
|
func (m *MapNodeFinderBySlot[K, V]) findNode(k K, createIfNotExist bool) (node, prev MapNode[K, V]) {
|
|
prev = m.slotFinder.FindSlot(k)
|
|
if prev != nil {
|
|
node = prev.GetNext()
|
|
for node != nil {
|
|
if node.GetKey().Equals(k) {
|
|
return
|
|
}
|
|
prev = node
|
|
node = node.GetNext()
|
|
}
|
|
}
|
|
if createIfNotExist {
|
|
node = prev.CreateNext(k)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) String() string {
|
|
return "SimpleMapNode{key: " + s.key.String() + ", value: " + fmt.Sprint(s.value) + "}"
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) GetKey() K {
|
|
return s.key
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) GetValue() V {
|
|
return s.value
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) SetValue(value V) {
|
|
s.value = value
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) CreateNext(key K) MapNode[K, V] {
|
|
s.next = &SimpleMapNode[K, V]{key: key, next: s.next}
|
|
return s.next
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) GetNext() MapNode[K, V] {
|
|
if s.next == nil {
|
|
return nil
|
|
}
|
|
return s.next
|
|
}
|
|
|
|
func (s *SimpleMapNode[K, V]) RemoveNext() {
|
|
if s.next != nil {
|
|
s.next = s.next.next
|
|
}
|
|
}
|