GoLang之Map常见问题总结

GoLang之Map常见问题总结

本文基于Windos系统上Go SDK v1.18进行讲解

1.用map实现一个set,然后一次性获取set所有的key

简单版

package main

import "fmt"

func main() {
	Map := map[interface{}]struct{}{}
	Map[1] = struct{}{}
	Map[2] = struct{}{}
	Map[3] = struct{}{}
	for k, _ := range Map {
		fmt.Println(k)
	}
}

复杂版:

import "fmt"

type Set map[string] struct{}

//当前key是否在我们的Set中
func (s Set) Get(key string)bool{
   _, ok := s[key]
  return ok
}
// 添加操作
func (s Set) Add(key string){
  s[key] = struct{}{}
}
// 删除操作
func (s Set) Delete(key string){
  delete(s,key)
}

func main(){
  s := make(Set)
  s.Add("tom")
  s.Add("jake")
  fmt.Println(s.Get("tom"))
  fmt.Println(s.Get("jake"))
}

// 一次获取所有的key
keys := make([]string, 0, len(s))
for key := range s {
    keys = append(keys, key)
}

2.使用go实现一个简单的哈希表

package data

import "fmt"

//1.首先定义结构体
type MpNode struct {
   Data Dict    // 定义数据  数据为存放k v 的结构体
   Next *MpNode // 下个节点
}
type Dict struct {
   Key   string
   Value interface{}
}

//8 开始创建数组链表  也就是哈希表
// 定义数组链表
var Arr [16]*MpNode

//2 初始化
//初始化链表的头节点
func newNodeHead() *MpNode {
   node := new(MpNode)
   node.Data.Key = "头key"
   node.Data.Value = "头value"
   node.Next = nil
   return node
}

//9 初始化哈希表
func NewHash() {
   for i := 0; i < 16; i++ {
      Arr[i] = newNodeHead()
   }
}

//链方法
//3 封装结构体对象方法
// 封装key value 存放方法
func (node *MpNode) data(k string, v interface{}) *MpNode {
   if node == nil {
      node = newNodeHead()
   }
   node.Data.Key = k
   node.Data.Value = v
   return node
}

//12 根据key取value
func (node *MpNode) getKey(k string) interface{} {
   if node.Next == nil {
      return nil
   }
   for node.Next != nil {
      if node.Next.Data.Key == k {
         return node.Next.Data.Value
      } else {
         node = node.Next
      }
   }
   return nil
}

//13 根据valve取key  后面发现如果要写这个 就要给每个数组都遍历一遍后  就暂且放弃 等后续优化
//func (node *MpNode) getValue(v interface{}) string {
// if node.Next == nil {
//    return ""
// }
// for node.Next != nil {
//    if node.Next.Data.Value == v {
//       return node.Next.Data.Key
//    } else {
//       node = node.Next
//    }
// }
// return ""
//}

//4  向该链空节点创建新数据
func (node *MpNode) add(k string, v interface{}) {
   // 首先判断k是否是该链已有的key  因为根据哈希算法简化后  同样的字符串会在同样的链里存放
   if node.getKey(k) != nil {
      return
   }
   //遍历到尾节点
   for node.Next != nil {
      node = node.Next
   }
   // 创建新的尾节点
   node.Next = node.Next.data(k, v)
}

//6 发现这样打印看不太方便 于是写个遍历值
func (node *MpNode) Log() {
   if node.Next == nil {
      return
   }
   fmt.Println(node.Next.Data)
   node.Next.Log()
}

// 7计算链表长度 防止数据堆积 为后续优化做准备
func (node *MpNode) Length() int {
   if node == nil {
      return 0
   }
   i := 0
   for node.Next != nil {
      i++
      node = node.Next
   }
   return i
}

//哈希表方法
//10 往表里存key值
func SetKey(k string, v interface{}) {
   // 存k先判断存哪里  这里才使用了散列算法计算
   num := hashNum(k)
   Arr[num].add(k, v)
}
//14 取key值
func GetKey(k string) interface{} {
   num := hashNum(k)
   return Arr[num].getKey(k)
}

//11 获取16以内的散列算法
func hashNum(key string) int {
   var index int = 0
   index = int(key[0])
   // 询价累积新的数值
   for k := 0; k < len(key); k++ {
      index *= (1103515245 + int(key[k]))
   }
   // 右位移2^27次方  这里可以位移任何数  只要别太大导致直接清空
   index >>= 27
   // 按位&  这里想要求32以内就 32-1即可   也就是说  index跟 1111 进行&  得到15以内的数  跟11111取余则得31以内的数
   index &= 16 - 1

   return index
}

//5 测试下添加数据是否有问题
func MpDemo() {
   //node := newNodeHead()
   //node.add("1", "2")
   //node.add("2", 3)
   //node.Log()
   //fmt.Println(node.Length())
}

参考资料:
go语言设计与实现
简书

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoGo在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值