random_map.go 1.98 KiB
package datastructure
import (
"math/rand"
"sync"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type randomMapEntry struct {
key interface{}
value interface{}
keyIndex int
}
type RandomMap struct {
rawMap map[interface{}]*randomMapEntry
keys []interface{}
size int
mutex sync.RWMutex
}
func NewRandomMap() *RandomMap {
return &RandomMap{
rawMap: make(map[interface{}]*randomMapEntry),
keys: make([]interface{}, 0),
}
}
func (rmap *RandomMap) Set(key interface{}, value interface{}) {
rmap.mutex.Lock()
if entry, exists := rmap.rawMap[key]; exists {
entry.value = value
} else {
rmap.rawMap[key] = &randomMapEntry{
key: key,
value: value,
keyIndex: rmap.size,
}
rmap.keys = append(rmap.keys, key)
rmap.size++
}
rmap.mutex.Unlock()
}
func (rmap *RandomMap) Get(key interface{}) (result interface{}, exists bool) {
rmap.mutex.RLock()
if entry, entryExists := rmap.rawMap[key]; entryExists {
result = entry.value
exists = entryExists
}
rmap.mutex.RUnlock()
return
}
func (rmap *RandomMap) Delete(key interface{}) (result interface{}, exists bool) {
rmap.mutex.RLock()
if _, entryExists := rmap.rawMap[key]; entryExists {
rmap.mutex.RUnlock()
rmap.mutex.Lock()
if entry, entryExists := rmap.rawMap[key]; entryExists {
delete(rmap.rawMap, key)
rmap.size--
if entry.keyIndex != rmap.size {
oldKey := entry.keyIndex
movedKey := rmap.keys[rmap.size]
rmap.rawMap[movedKey].keyIndex = oldKey
rmap.keys[oldKey] = movedKey
}
rmap.keys = rmap.keys[:rmap.size]
result = entry.value
exists = true
}
rmap.mutex.Unlock()
} else {
rmap.mutex.RUnlock()
}
return
}
func (rmap *RandomMap) Size() (result int) {
rmap.mutex.RLock()
result = rmap.size
rmap.mutex.RUnlock()
return
}
func (rmap *RandomMap) RandomEntry() (result interface{}) {
rmap.mutex.RLock()
if rmap.size >= 1 {
result = rmap.rawMap[rmap.keys[rand.Intn(rmap.size)]].value
}
rmap.mutex.RUnlock()
return
}