天天看點

Go 分布式學習利器(6)-- Map

文章目錄

  • ​​1. Map的聲明​​
  • ​​2. Map 元素通路帶來的問題​​
  • ​​3. Map 元素的周遊​​
  • ​​4. 通過Map 實作 函數對象(C++)​​
  • ​​5. 通過Map實作一個簡單Set功能​​

1. Map的聲明

基本的幾種聲明和初始化方式如下:

  • ​m := map[string]int{"one":1, "two":2, "three":3}​

  • ​m := map[string]int{}​

  • ​m["one"] = 1​

  • ​m := make(map[string]int, 10 /*表示map結構的容量*/)​

    ​ 這種方式一般對性能比較友好,因為不需要map結構的動态擴容帶來的開銷,直接将需要的容量配置設定好

測試函如下:

func TestMapInit(t *testing.T) {
  m1 := map[string]int{"one":1, "two":2, "three":3}
  t.Log(m1["two"])
  t.Log("len m1", len(m1))

  m2 := map[string]int{}
  t.Log("len m2", len(m2))

  m2["four"] = 4
  t.Log("len m2", len(m2))

  m3 := make(map[string]int, 10)
  t.Log("len m3", len(m3)) // 不支援cap 擷取map的容量
}      

2. Map 元素通路帶來的問題

我們定義一個​

​m := map[int]int{}​

​​這樣的變量,那麼該map的值已經被預設初始化為了0。

這樣的初始化方式 可能與我們實際的​​

​m[0]=0​

​ 産生沖突,是以Go語言也能夠像其他語言一樣主動判斷一個map的值是否為空,這裡主要是通過之前的Go條件語句中的條件多次指派的文法來進行的:

方式如下:

func TestJudgeMapResult(t *testing.T) {
  m1 := map[int]int{}

  t.Log(m1[0])
  //m1[0] = 0
  //t.Log(m1[0])

  if v,ok :=m1[0];ok{ // 條件多次指派,v是int類型,表示m1[0]的值;ok 是bool類型,表示是否為空
    t.Log("m1[0] is not nil", v)
  } else {
    t.Log("m1[0] is nil")
  }
}      

輸出如下:

=== RUN   TestJudgeMapResult
    map_test.go:23: 0
    map_test.go:30: m1[0] is nil      

3. Map 元素的周遊

基本文法 是通過 提到的​

​for​

​循環中的 for … range文法來進行的:

m1 := map[string]int{"one":1, "two":2, "three":3}
for k,v := range m1 {
  t.Log(k,v)
}      

輸出如下:

=== RUN   TestMapTravel
    map_test.go:37: one 1
    map_test.go:37: two 2
    map_test.go:37: three 3      

4. 通過Map 實作 函數對象(C++)

我知道C++的函數對象形态如下:

struct adder {
    adder(int n) : n_(n) {}
    int operator() (int x)const {
        return x + n_;
    }
private:
    int n_;
};

auto add_3 = adder(3); // 初始化一個函數對象,為每一個傳入的數值加3
add_3(5); //表示為5 加3      

這裡可以通過Map,将函數作為value來更加友善的實作函數對象:

func TestMapImplementFunctionTemplate(t *testing.T) {
  m1 := map[int]func(op int) int{}
  m1[1] = func(op int) int {return op} // 等值 函數
  m1[2] = func(op int) int {return op*op} // 平方值 函數
  m1[3] = func(op int) int {return op*op*op} // 立方值 函數

  t.Log(m1[1](1), m1[2](2), m1[3](3))
}      

5. 通過Map實作一個簡單Set功能

Go語言沒有天然的Set資料結構,不過這裡我們可以通過Map實作很簡單的Set功能。

基本的Set功能如下:

  • 元素具有唯一性
  • 支援 添加,删除,通路元素個數,判斷元素是否存在的功能
func TestMapImplementSet(t *testing.T) {
  Set := map[int]bool{} // 一個Set集合
  Set[1] = true // 集合的插入, 沒插入一個元素,保證一定将該元素的value置為true,即能保證集合的特性

  n := 3
  if Set[n]{
    t.Logf("%d is existing ",n )
  }else {
    t.Logf("%d is not existing. ",n )
  }

  Set[3] = true
  t.Log("len of Set ", len(Set)) // 集合的元素個數

  delete(Set,1) // 删除map中的一個元素
  m := 1
  // 判斷該元素是否存在
  if Set[m]{
    t.Logf("%d is existing ",m)
  }else {
    t.Logf("%d is not existing. ",m )
  }
}      
=== RUN   TestMapImplementSet
    map_test.go:59: 3 is not existing. 
    map_test.go:63: len of Set  2
    map_test.go:71: 1 is not existing. 
--- PASS: TestMapImplementSet (0.00s)      

繼續閱讀