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  }