concurrent map使用

concurrent map使用


目录

  1. 概述
  2. 例子

1. 概述

  1. Go语言原生的map类型并不支持并发读写。concurrent-map提供了一种高性能的解决方案:通过对内部map进行分片,降低锁粒度,从而达到最少的锁等待时间(锁冲突)
  2. 在Go 1.9之前,go语言标准库中并没有实现并发map。在Go 1.9中,引入了sync.Map。新的sync.Map与此concurrent-map有几个关键区别。
    1. 标准库中的sync.Map是专为append-only场景设计的。因此,如果想将Map用于一个类似内存数据库,那么使用concurrent-map可能会更受益。
    2. sync.Map在读多写少性能比较好,否则并发性能很差

2. 例子

  1. 引用:
go test "github.com/orcaman/concurrent-map"
  1. 例子使用了部分方法,具体查看:concurrent_map_test.go
package main

import (
	"encoding/json"
	"fmt"
	cmap "github.com/orcaman/concurrent-map"
	"github.com/prometheus/common/log"
	"strconv"
)

type Animal struct {
	name string
}

func main() {
	m := cmap.New() // cmap.ConcurrentMap
	elephant := Animal{"elephant"}
	monkey := Animal{"monkey"}

	m.Set("elephant", elephant)	// Set:添加元素
	m.Set("monkey", monkey)

	tmp, ok := m.Get("elephant")	// Get:获取元素
	if ok == false {
		log.Error("ok should be true for item stored within the map.")
	}

	elephant, ok = tmp.(Animal) // 类型断言,转成指定类型,key为指针时需要加*
	if !ok {
		log.Error("expecting an element, not null.")
	}
	if elephant.name != "elephant" {
		log.Error("item was modified.")
	}

	if m.Has("elephant") == false {		// Has:是否有这个元素
		log.Error("element exists, expecting Has to return True.")
	}

	m.Remove("monkey")	// Remove:去除元素

	if m.Count() != 0 {
		log.Error("Expecting count to be zero once item was removed.")
	}

	monkey = Animal{"monkey"}
	m.Set("monkey", monkey)

	v, exists := m.Pop("monkey")	// Pop:从map中获取这个元素并删除

	if !exists {
		log.Error("Pop didn't find a monkey.")
	}

	m1, ok := v.(Animal)
	if !ok || m1 != monkey {
		log.Error("Pop found something else, but monkey.")
	}

	if m.Count() != 100 {	// Count: 计算map中元素个数
		log.Error("Expecting 100 element within map.")
	}

	if m.IsEmpty() == false {	// IsEmpty:判断map是否为nil
		log.Error("new map should be empty")
	}

	// 插入100个元素
	for i := 0; i < 100; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	counter := 0
	// Iterate over elements.
	for item := range m.IterBuffered() {	// IterBuffered:获取缓冲迭代器,可用于for循环
		println(item.Val)
		val := item.Val
		name := item.Val.(Animal).name
		fmt.Println(name)

		if val == nil {
			log.Error("Expecting an object.")
		}
		counter++
	}

	m.Clear()	// Clear:清空map

	// Insert 100 elements.
	for i := 0; i < 100; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}

	// Iterate over elements.
	m.IterCb(func(key string, v interface{}) {	//  IterCb:遍历map,获取key,value
		num, ok := v.(Animal)
		fmt.Println(key,"---",num.name)
		if !ok {
			log.Error("Expecting an animal object")
		}

		counter++
	})

	items := m.Items()	// Items:转换成map[string]interface{}

	if len(items) != 100 {
		log.Error("We should have counted 100 elements.")
	}

	m.Clear()
	m.Set("a", 1)
	m.Set("b", 2)
	j, err := json.Marshal(m)	// 转换成json格式
	if err != nil {
		log.Error(err)
	}
	fmt.Println(j)

	keys := m.Keys()	// Keys:获取map的key列表
	println(keys)

	animals := map[string]interface{}{
		"elephant": Animal{"elephant"},
		"monkey":   Animal{"monkey"},
	}
	m.MSet(animals)	// MSet:同时添加多个元素
	println(m.Count())

	dolphin := Animal{"dolphin"}
	whale := Animal{"whale"}
	tiger := Animal{"tiger"}
	lion := Animal{"lion"}

	cb := func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
		nv := newValue.(Animal)
		if !exists {
			return []Animal{nv}
		}
		res := valueInMap.([]Animal)
		return append(res, nv)
	}
	
	m.Set("marine", []Animal{dolphin})
	m.Upsert("marine", whale, cb)		// Upsert:插入或更新元素
	m.Upsert("predator", tiger, cb)
	m.Upsert("predator", lion, cb)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值