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  }