github.com/mymmsc/gox@v1.3.33/util/linkedhashmap/linkedhashmap.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 linkedhashmap is a map that preserves insertion-order.
     6  //
     7  // It is backed by a hash table to store values and doubly-linked list to store ordering.
     8  //
     9  // Structure is not thread safe.
    10  //
    11  // Reference: http://en.wikipedia.org/wiki/Associative_array
    12  package linkedhashmap
    13  
    14  import (
    15  	"fmt"
    16  	"github.com/mymmsc/gox/util"
    17  	"github.com/mymmsc/gox/util/doublylinkedlist"
    18  	"strings"
    19  )
    20  
    21  func assertMapImplementation() {
    22  	var _ util.Map = (*Map)(nil)
    23  }
    24  
    25  // Map holds the elements in a red-black tree
    26  type Map struct {
    27  	table    map[interface{}]interface{}
    28  	ordering *doublylinkedlist.List
    29  }
    30  
    31  // New instantiates a linked-hash-map.
    32  func New() *Map {
    33  	return &Map{
    34  		table:    make(map[interface{}]interface{}),
    35  		ordering: doublylinkedlist.New(),
    36  	}
    37  }
    38  
    39  // Put inserts key-value pair into the map.
    40  // Key should adhere to the comparator's type assertion, otherwise method panics.
    41  func (m *Map) Put(key interface{}, value interface{}) {
    42  	if _, contains := m.table[key]; !contains {
    43  		m.ordering.Append(key)
    44  	}
    45  	m.table[key] = value
    46  }
    47  
    48  // Get searches the element in the map by key and returns its value or nil if key is not found in tree.
    49  // Second return parameter is true if key was found, otherwise false.
    50  // Key should adhere to the comparator's type assertion, otherwise method panics.
    51  func (m *Map) Get(key interface{}) (value interface{}, found bool) {
    52  	value = m.table[key]
    53  	found = value != nil
    54  	return
    55  }
    56  
    57  // Remove removes the element from the map by key.
    58  // Key should adhere to the comparator's type assertion, otherwise method panics.
    59  func (m *Map) Remove(key interface{}) {
    60  	if _, contains := m.table[key]; contains {
    61  		delete(m.table, key)
    62  		index := m.ordering.IndexOf(key)
    63  		m.ordering.Remove(index)
    64  	}
    65  }
    66  
    67  // Empty returns true if map does not contain any elements
    68  func (m *Map) Empty() bool {
    69  	return m.Size() == 0
    70  }
    71  
    72  // Size returns number of elements in the map.
    73  func (m *Map) Size() int {
    74  	return m.ordering.Size()
    75  }
    76  
    77  // Keys returns all keys in-order
    78  func (m *Map) Keys() []interface{} {
    79  	return m.ordering.Values()
    80  }
    81  
    82  // Values returns all values in-order based on the key.
    83  func (m *Map) Values() []interface{} {
    84  	values := make([]interface{}, m.Size())
    85  	count := 0
    86  	it := m.Iterator()
    87  	for it.Next() {
    88  		values[count] = it.Value()
    89  		count++
    90  	}
    91  	return values
    92  }
    93  
    94  // Clear removes all elements from the map.
    95  func (m *Map) Clear() {
    96  	m.table = make(map[interface{}]interface{})
    97  	m.ordering.Clear()
    98  }
    99  
   100  // String returns a string representation of container
   101  func (m *Map) String() string {
   102  	str := "LinkedHashMap\nmap["
   103  	it := m.Iterator()
   104  	for it.Next() {
   105  		str += fmt.Sprintf("%v:%v ", it.Key(), it.Value())
   106  	}
   107  	return strings.TrimRight(str, " ") + "]"
   108  
   109  }