-
Notifications
You must be signed in to change notification settings - Fork 11
/
hashmap.go
131 lines (101 loc) · 2.39 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 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),
}
}
// 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 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))
}