github.com/tursom/GoCollections@v0.3.10/collections/HashMap.go (about) 1 /* 2 * Copyright (c) 2022 tursom. All rights reserved. 3 * Use of this source code is governed by a GPL-3 4 * license that can be found in the LICENSE file. 5 */ 6 7 package collections 8 9 import ( 10 "fmt" 11 12 "github.com/tursom/GoCollections/exceptions" 13 "github.com/tursom/GoCollections/lang" 14 ) 15 16 type ( 17 //HashMap 18 HashMap[K lang.Object, V any] struct { 19 NodeMap[K, V] 20 slot []*hashMapNode[K, V] 21 loadFactor float32 22 size int 23 } 24 25 abstractHashMapNode[K lang.Object, V any] struct { 26 m *HashMap[K, V] 27 hash int32 28 } 29 30 hashMapNode[K lang.Object, V any] struct { 31 lang.BaseObject 32 abstractHashMapNode[K, V] 33 key K 34 value V 35 next *hashMapNode[K, V] 36 } 37 38 emptyHashMapSlot[K lang.Object, V any] struct { 39 lang.BaseObject 40 abstractHashMapNode[K, V] 41 } 42 ) 43 44 func NewHashMap[K lang.Object, V any]() *HashMap[K, V] { 45 return NewHashMapInitCap[K, V](16, 0.75) 46 } 47 48 func NewHashMapInitCap[K lang.Object, V any](initialCapacity int, loadFactor float32) *HashMap[K, V] { 49 m := &HashMap[K, V]{ 50 slot: make([]*hashMapNode[K, V], initialCapacity), 51 loadFactor: loadFactor, 52 } 53 m.MapNodeFinder = NewMapNodeFinderBySlot[K, V](m) 54 return m 55 } 56 57 func (m *HashMap[K, V]) String() string { 58 return MapToString[K, V](m).String() 59 } 60 61 func (m *HashMap[K, V]) FindSlot(k K) MapNode[K, V] { 62 hashCode := lang.HashCode(k) 63 hashCode ^= hashCode >> 16 64 index := int(hashCode) % len(m.slot) 65 root := m.slot[index] 66 if root == nil { 67 return &emptyHashMapSlot[K, V]{abstractHashMapNode: abstractHashMapNode[K, V]{m: m, hash: hashCode}} 68 } 69 return root 70 } 71 72 func (m *HashMap[K, V]) Loop(f func(K, V) exceptions.Exception) (err exceptions.Exception) { 73 for _, node := range m.slot { 74 for node != nil { 75 err = f(node.GetKey(), node.GetValue()) 76 if err != nil { 77 return 78 } 79 node = node.next 80 } 81 } 82 return 83 } 84 85 func (m *HashMap[K, V]) resize() { 86 slot := m.slot 87 resize := len(slot) 88 load := int(float32(m.size) / m.loadFactor) 89 for load < resize { 90 resize >>= 1 91 } 92 for load > resize { 93 resize <<= 1 94 } 95 if resize == len(slot) { 96 return 97 } 98 m.slot = make([]*hashMapNode[K, V], resize) 99 for _, node := range slot { 100 for node != nil { 101 next := node.next 102 index := node.index() 103 node.next = m.slot[index] 104 m.slot[index] = node 105 node = next 106 } 107 } 108 } 109 110 func (m *HashMap[K, V]) resizeFromRemove() { 111 if len(m.slot) > int(float32(m.size)/m.loadFactor) { 112 m.resize() 113 } 114 } 115 116 func (m *HashMap[K, V]) resizeFromAdd() { 117 if len(m.slot) < int(float32(m.size)/m.loadFactor) { 118 m.resize() 119 } 120 } 121 122 func (n *abstractHashMapNode[K, V]) index() int { 123 return int(n.hash) % len(n.m.slot) 124 } 125 126 func (e *emptyHashMapSlot[K, V]) GetKey() K { 127 return lang.Nil[K]() 128 } 129 130 func (e *emptyHashMapSlot[K, V]) GetValue() V { 131 return lang.Nil[V]() 132 } 133 134 func (e *emptyHashMapSlot[K, V]) SetValue(_ V) { 135 } 136 137 func (e *emptyHashMapSlot[K, V]) CreateNext(key K) MapNode[K, V] { 138 index := e.index() 139 node := &hashMapNode[K, V]{ 140 key: key, 141 abstractHashMapNode: abstractHashMapNode[K, V]{m: e.m, hash: lang.HashCode(key)}, 142 next: e.m.slot[index], 143 } 144 e.m.slot[index] = node 145 e.m.size++ 146 e.m.resizeFromAdd() 147 return node 148 } 149 150 func (e *emptyHashMapSlot[K, V]) GetNext() MapNode[K, V] { 151 node := e.m.slot[e.index()] 152 // required 153 if node == nil { 154 return nil 155 } 156 return node 157 } 158 159 func (e *emptyHashMapSlot[K, V]) RemoveNext() { 160 node := e.m.slot[e.index()] 161 if node != nil { 162 e.m.slot[e.index()] = node.next 163 e.m.size-- 164 e.m.resizeFromRemove() 165 } 166 } 167 168 func (s *hashMapNode[K, V]) String() string { 169 return "hashMapNode{key: " + s.key.String() + ", value: " + fmt.Sprint(s.value) + "}" 170 } 171 172 func (s *hashMapNode[K, V]) GetKey() K { 173 return s.key 174 } 175 176 func (s *hashMapNode[K, V]) GetValue() V { 177 return s.value 178 } 179 180 func (s *hashMapNode[K, V]) SetValue(value V) { 181 s.value = value 182 } 183 184 func (s *hashMapNode[K, V]) CreateNext(key K) MapNode[K, V] { 185 s.next = &hashMapNode[K, V]{ 186 key: key, 187 next: s.next, 188 abstractHashMapNode: abstractHashMapNode[K, V]{ 189 m: s.m, 190 hash: lang.HashCode(key), 191 }, 192 } 193 s.m.size++ 194 s.m.resizeFromAdd() 195 return s.next 196 } 197 198 func (s *hashMapNode[K, V]) GetNext() MapNode[K, V] { 199 if s.next == nil { 200 return nil 201 } 202 return s.next 203 } 204 205 func (s *hashMapNode[K, V]) RemoveNext() { 206 if s.next != nil { 207 s.next = s.next.next 208 s.m.size-- 209 s.m.resizeFromRemove() 210 } 211 }