forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hashmap.go
122 lines (93 loc) · 2.18 KB
/
hashmap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package hashmap
import (
"fmt"
"hash/fnv"
)
var defaultCapacity uint64 = 1 << 10
type node struct {
key interface{}
value interface{}
next *node
}
// HashMap is golang implementation of hashmap
type HashMap struct {
capacity uint64
size uint64
table []*node
}
// New return new HashMap instance
func New() *HashMap {
return &HashMap{
capacity: defaultCapacity,
table: make([]*node, defaultCapacity),
}
}
// Get returns value associated with given key
func (hm *HashMap) Get(key interface{}) interface{} {
node := hm.getNodeByHash(hm.hash(key))
if node != nil {
return node.value
}
return nil
}
// Put puts new key value in hashmap
func (hm *HashMap) Put(key interface{}, value interface{}) interface{} {
return hm.putValue(hm.hash(key), key, value)
}
// Contains checks if given key is stored in hashmap
func (hm *HashMap) Contains(key interface{}) bool {
node := hm.getNodeByHash(hm.hash(key))
return node != nil
}
func (hm *HashMap) putValue(hash uint64, key interface{}, value interface{}) interface{} {
if hm.capacity == 0 {
hm.capacity = defaultCapacity
hm.table = make([]*node, defaultCapacity)
}
node := hm.getNodeByHash(hash)
if node == nil {
hm.table[hash] = newNode(key, value)
} else if node.key == key {
hm.table[hash] = newNodeWithNext(key, value, node)
return value
} else {
hm.resize()
return hm.putValue(hash, key, value)
}
hm.size++
return value
}
func (hm *HashMap) getNodeByHash(hash uint64) *node {
return hm.table[hash]
}
func (hm *HashMap) resize() {
hm.capacity <<= 1
tempTable := hm.table
hm.table = make([]*node, hm.capacity)
for i := 0; i < len(tempTable); i++ {
node := tempTable[i]
if node == nil {
continue
}
hm.table[hm.hash(node.key)] = node
}
}
func newNode(key interface{}, value interface{}) *node {
return &node{
key: key,
value: value,
}
}
func newNodeWithNext(key interface{}, value interface{}, next *node) *node {
return &node{
key: key,
value: value,
next: next,
}
}
func (hm *HashMap) hash(key interface{}) uint64 {
h := fnv.New64a()
_, _ = h.Write([]byte(fmt.Sprintf("%v", key)))
hashValue := h.Sum64()
return (hm.capacity - 1) & (hashValue ^ (hashValue >> 16))
}