forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hashmap.go
131 lines (101 loc) · 2.26 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
123
124
125
126
127
128
129
130
131
package hashmap
import (
"fmt"
"hash/fnv"
)
var defaultCapacity uint64 = 1 << 10
type node struct {
key any
value any
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),
}
}
// Make creates a new HashMap instance with input size and capacity
func Make(size, capacity uint64) HashMap {
return HashMap{
size: size,
capacity: capacity,
table: make([]*node, capacity),
}
}
// Get returns value associated with given key
func (hm *HashMap) Get(key any) any {
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 any, value any) any {
return hm.putValue(hm.hash(key), key, value)
}
// Contains checks if given key is stored in hashmap
func (hm *HashMap) Contains(key any) bool {
node := hm.getNodeByHash(hm.hash(key))
return node != nil
}
func (hm *HashMap) putValue(hash uint64, key any, value any) any {
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 any, value any) *node {
return &node{
key: key,
value: value,
}
}
func newNodeWithNext(key any, value any, next *node) *node {
return &node{
key: key,
value: value,
next: next,
}
}
func (hm *HashMap) hash(key any) uint64 {
h := fnv.New64a()
_, _ = h.Write([]byte(fmt.Sprintf("%v", key)))
hashValue := h.Sum64()
return (hm.capacity - 1) & (hashValue ^ (hashValue >> 16))
}