go-ConcurrentMap实现

niyuelin1990 · · 1062 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

用go实现ConcurrentMap

// 泛化的Map的接口类型
type GenericMap interface {
       // 获取给定键值对应的元素值。若没有对应元素值则返回nil。
       Get(key interface{}) interface{}
       // 添加键值对,并返回与给定键值对应的旧的元素值。若没有旧元素值则返回(nil, true)。
       Put(key interface{}, elem interface{}) (interface{}, bool)
       // 删除与给定键值对应的键值对,并返回旧的元素值。若没有旧元素值则返回nil。
       Remove(key interface{}) interface{}
       // 清除所有的键值对。
       Clear()
       // 获取键值对的数量。
       Len() int
       // 判断是否包含给定的键值。
       Contains(key interface{}) bool
       // 获取已排序的键值所组成的切片值。
       Keys() []interface{}
       // 获取已排序的元素值所组成的切片值。
       Elems() []interface{}
       // 获取已包含的键值对所组成的字典值。
       ToMap() map[interface{}]interface{}
       // 获取键的类型。
       KeyType() reflect.Type
       // 获取元素的类型。
       ElemType() reflect.Type
}
type ConcurrentMap interface {
       GenericMap
       String() string
}

type myConcurrentMap struct {
       m        map[interface{}]interface{}
       keyType  reflect.Type
       elemType reflect.Type
       rwmutex  sync.RWMutex
}

func (cmap *myConcurrentMap) Get(key interface{}) interface{} {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       return cmap.m[key]
}

func (cmap *myConcurrentMap) isAcceptablePair(k, e interface{}) bool {
       if k == nil || reflect.TypeOf(k) != cmap.keyType {
              return false
       }
       if e == nil || reflect.TypeOf(e) != cmap.elemType {
              return false
       }
       return true
}

func (cmap *myConcurrentMap) Put(key interface{}, elem interface{}) (interface{}, bool) {
       if !cmap.isAcceptablePair(key, elem) {
              return nil, false
       }
       cmap.rwmutex.Lock()
       defer cmap.rwmutex.Unlock()
       oldElem := cmap.m[key]
       cmap.m[key] = elem
       return oldElem, true
}

func (cmap *myConcurrentMap) Remove(key interface{}) interface{} {
       cmap.rwmutex.Lock()
       defer cmap.rwmutex.Unlock()
       oldElem := cmap.m[key]
       delete(cmap.m, key)
       return oldElem
}

func (cmap *myConcurrentMap) Clear() {
       cmap.rwmutex.Lock()
       defer cmap.rwmutex.Unlock()
       cmap.m = make(map[interface{}]interface{})
}

func (cmap *myConcurrentMap) Len() int {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       return len(cmap.m)
}

func (cmap *myConcurrentMap) Contains(key interface{}) bool {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       _, ok := cmap.m[key]
       return ok
}

func (cmap *myConcurrentMap) Keys() []interface{} {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       initialLen := len(cmap.m)
       keys := make([]interface{}, initialLen)
       index := 0
       for k, _ := range cmap.m {
              keys[index] = k
              index++
       }
       return keys
}

func (cmap *myConcurrentMap) Elems() []interface{} {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       initialLen := len(cmap.m)
       elems := make([]interface{}, initialLen)
       index := 0
       for _, v := range cmap.m {
              elems[index] = v
              index++
       }
       return elems
}

func (cmap *myConcurrentMap) ToMap() map[interface{}]interface{} {
       cmap.rwmutex.RLock()
       defer cmap.rwmutex.RUnlock()
       replica := make(map[interface{}]interface{})
       for k, v := range cmap.m {
              replica[k] = v
       }
       return replica
}

func (cmap *myConcurrentMap) KeyType() reflect.Type {
       return cmap.keyType
}

func (cmap *myConcurrentMap) ElemType() reflect.Type {
       return cmap.elemType
}

func (cmap *myConcurrentMap) String() string {
       var buf bytes.Buffer
       buf.WriteString("ConcurrentMap<")
       buf.WriteString(cmap.keyType.Kind().String())
       buf.WriteString(",")
       buf.WriteString(cmap.elemType.Kind().String())
       buf.WriteString(">{")
       first := true
       for k, v := range cmap.m {
              if first {
                     first = false
              } else {
                     buf.WriteString(" ")
              }
              buf.WriteString(fmt.Sprintf("%v", k))
              buf.WriteString(":")
              buf.WriteString(fmt.Sprintf("%v", v))
       }
       buf.WriteString("}")
       return buf.String()
}
func NewConcurrentMap(keyType, elemType reflect.Type) ConcurrentMap {
       return &myConcurrentMap{
              keyType:  keyType,
              elemType: elemType,
              m:        make(map[interface{}]interface{})}
}

func main() {
       //var cmap ConcurrentMap = &myConcurrentMap{
       //     m:        make(map[interface{}]interface{}),
       //     keyType:  reflect.TypeOf(int(2)),
       //     elemType: reflect.TypeOf(string(20))}
       cmap := NewConcurrentMap(reflect.TypeOf(int(2)), reflect.TypeOf(string(200)))
       fmt.Println(cmap)
       cmap.Put(112, "12")
       fmt.Println(cmap.String())
}


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:niyuelin1990

查看原文:go-ConcurrentMap实现

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

1062 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传