gitee.com/quant1x/gox@v1.21.2/util/hashbidimap/hashbidimap.go (about) 1 // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package hashbidimap implements a bidirectional map backed by two hashmaps. 6 // 7 // A bidirectional map, or hash bag, is an associative data structure in which the (key,value) pairs form a one-to-one correspondence. 8 // Thus the binary relation is functional in each direction: value can also act as a key to key. 9 // A pair (a,b) thus provides a unique coupling between 'a' and 'b' so that 'b' can be found when 'a' is used as a key and 'a' can be found when 'b' is used as a key. 10 // 11 // Elements are unordered in the map. 12 // 13 // Structure is not thread safe. 14 // 15 // Reference: https://en.wikipedia.org/wiki/Bidirectional_map 16 package hashbidimap 17 18 import ( 19 "fmt" 20 "gitee.com/quant1x/gox/util/hashmap" 21 "gitee.com/quant1x/gox/util/internal" 22 ) 23 24 func assertMapImplementation() { 25 var _ internal.BidiMap = (*Map)(nil) 26 } 27 28 // Map holds the elements in two hashmaps. 29 type Map struct { 30 forwardMap hashmap.Map 31 inverseMap hashmap.Map 32 } 33 34 // New instantiates a bidirectional map. 35 func New() *Map { 36 return &Map{*hashmap.New(), *hashmap.New()} 37 } 38 39 // Put inserts element into the map. 40 func (m *Map) Put(key interface{}, value interface{}) { 41 if valueByKey, ok := m.forwardMap.Get(key); ok { 42 m.inverseMap.Remove(valueByKey) 43 } 44 if keyByValue, ok := m.inverseMap.Get(value); ok { 45 m.forwardMap.Remove(keyByValue) 46 } 47 m.forwardMap.Put(key, value) 48 m.inverseMap.Put(value, key) 49 } 50 51 // Get searches the element in the map by key and returns its value or nil if key is not found in map. 52 // Second return parameter is true if key was found, otherwise false. 53 func (m *Map) Get(key interface{}) (value interface{}, found bool) { 54 return m.forwardMap.Get(key) 55 } 56 57 // GetKey searches the element in the map by value and returns its key or nil if value is not found in map. 58 // Second return parameter is true if value was found, otherwise false. 59 func (m *Map) GetKey(value interface{}) (key interface{}, found bool) { 60 return m.inverseMap.Get(value) 61 } 62 63 // Remove removes the element from the map by key. 64 func (m *Map) Remove(key interface{}) { 65 if value, found := m.forwardMap.Get(key); found { 66 m.forwardMap.Remove(key) 67 m.inverseMap.Remove(value) 68 } 69 } 70 71 // Empty returns true if map does not contain any elements 72 func (m *Map) Empty() bool { 73 return m.Size() == 0 74 } 75 76 // Size returns number of elements in the map. 77 func (m *Map) Size() int { 78 return m.forwardMap.Size() 79 } 80 81 // Keys returns all keys (random order). 82 func (m *Map) Keys() []interface{} { 83 return m.forwardMap.Keys() 84 } 85 86 // Values returns all values (random order). 87 func (m *Map) Values() []interface{} { 88 return m.inverseMap.Keys() 89 } 90 91 // Clear removes all elements from the map. 92 func (m *Map) Clear() { 93 m.forwardMap.Clear() 94 m.inverseMap.Clear() 95 } 96 97 // String returns a string representation of container 98 func (m *Map) String() string { 99 str := "HashBidiMap\n" 100 str += fmt.Sprintf("%v", m.forwardMap) 101 return str 102 }