omap

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2022 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

omap package provides a common interface to implement ordered maps, along with a set of implementations.

As it is well-known, Go's builtin map iterator order is undefined (consider random). An ordered map (omap for short) is very similar to a builtin map, but with the advantage that iterating the keys or serializing it (e.g. to JSON) will keep the keys in same order as originally provided. There is an small overhead though, mostly in memory, but usually negligible. See benchmarks for a few comparisons among omap implementations and builtin map. A given key can hold only a single value, see omultimap if you need multiple values for the same key.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/matheusoliveira/go-ordered-map/omap"
)

func main() {
	m := omap.New[string, int]()
	m.Put("foo", 1)
	m.Put("x", -1)
	m.Put("bar", 2)
	m.Put("y", -1)
	m.Put("baz", 3)
	m.Delete("x")
	m.Delete("y")
	// iterate
	for it := m.Iterator(); it.Next(); {
		fmt.Printf("%s = %d\n", it.Key(), it.Value())
	}
	// JSON, keys are preserved in same order for marshal/unmarshal
	input := []byte(`{"hi":"Hello","name":"World!"}`)
	hello := omap.New[string, string]()
	err := json.Unmarshal(input, &hello)
	fmt.Println(hello, err)
	// marshal JSON
	output, _ := json.Marshal(hello)
	fmt.Println(string(output))
	if string(output) == string(input) {
		fmt.Println("Sucess!")
	}
	// reverse iterator
	for it := m.Iterator().MoveBack(); it.Prev(); {
		fmt.Printf("%s = %d\n", it.Key(), it.Value())
	}

}
Output:

foo = 1
bar = 2
baz = 3
omap.OMapLinked[hi:Hello name:World!] <nil>
{"hi":"Hello","name":"World!"}
Sucess!
baz = 3
bar = 2
foo = 1

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// default errors of OMap, provided in a way that errors.Is can be used easily
	ErrOMap                = errors.New("OMapError")
	ErrInvalidIteratorType = fmt.Errorf("%w: invalid iterator type, tried to operate on iterator of unexpected type (cast failed)", ErrOMap)
	ErrInvalidIteratorMap  = fmt.Errorf("%w: invalid iterator map, tried to operate on iterator of a different map instance", ErrOMap)
	ErrInvalidIteratorPos  = fmt.Errorf("%w: iterator not positionated in a valid entry (either BOF or EOF)", ErrOMap)
	ErrInvalidIteratorKey  = fmt.Errorf("%w: iterator seems valid but given key not found in the map anymore (concurrent access?)", ErrOMap)
	ErrKeyNotFound         = fmt.Errorf("%w: key not found", ErrOMap)
)
View Source
var EnableOMapBuiltin = false

This is a safe var, since OMapBuiltin should be used only for testings, since it is not actually an ordered map, one must explicitly set this variable to `true` before using it, or it will panic on initialization.

Functions

func IteratorKeysToSlice

func IteratorKeysToSlice[K comparable, V any](it OMapIterator[K, V]) []K

Iterate over the given iterator it, from the given position, and store the keys only into an slice of same type.

Note: the iterator will be at EOF after this function returns with success.

func IteratorToString

func IteratorToString[K comparable, V any](typeName string, it OMapIterator[K, V]) string

Iterate over the given iterator it, from the given position, and marshal the key/values into an string.

This is a handy function to implements fmt.Stringfier interface. Note: the iterator will be at EOF after this function returns with success.

func IteratorValuesToSlice

func IteratorValuesToSlice[K comparable, V any](it OMapIterator[K, V]) []V

Iterate over the given iterator it, from the given position, and store the values only into an slice of same type.

Note: the iterator will be at EOF after this function returns with success.

func MarshalJSON

func MarshalJSON[K comparable, V any](it OMapIterator[K, V]) ([]byte, error)

Iterate over the given iterator it, from the given position, and marshal the key/values into JSON.

This is a handy function to construct a json.Marshaler implementation. Note: the iterator will be at EOF after this function returns with success.

func MoveAfter

func MoveAfter[K comparable, V any](m OMap[K, V], targetKey K, refKey K) error

Finds targetKey and refKey in the m map, and move the targetKey entry to the position immediately after the refKey. Returns omap.ErrKeyNotFound if any of the keys cannot be found in the map, or nil otherwise.

func MoveBefore

func MoveBefore[K comparable, V any](m OMap[K, V], targetKey K, refKey K) error

Finds targetKey and refKey in the m map, and move the targetKey entry to the position immediately before the refKey. Returns omap.ErrKeyNotFound if any of the keys cannot be found in the map, or nil otherwise.

func MoveFirst

func MoveFirst[K comparable, V any](m OMap[K, V], targetKey K) error

Move targetKey in the m map at first position of the map. Returns omap.ErrKeyNotFound if the key cannot be found in the map, or nil otherwise.

func MoveLast

func MoveLast[K comparable, V any](m OMap[K, V], targetKey K) error

Move targetKey in the m map at last position of the map. Returns omap.ErrKeyNotFound if the key cannot be found in the map, or nil otherwise.

func UnmarshalJSON

func UnmarshalJSON[K comparable, V any](putFunc func(K, V), b []byte) error

Process given json at b and for each key/value found, call given putFunc function with same definition of OMap.Put to add the given key/value into a map.

This is a handy function to convert a given json to map as json.Unmarshaler interface requires.

Types

type Hasher

type Hasher interface {
	HashSum32() uint32
}

Objects that want to create a custom hashing for the key used by OMapLinkedHash must implement this interface, giving a HashSum32 func that returns the hash of the object as an uint32.

type OMap

type OMap[K comparable, V any] interface {
	// Add or update an element in the map of given key and value. If it is a new value, it should be
	// in the end of the map on iteration, if it is an update the position of the value must be
	// maintained.
	Put(key K, value V)
	// Add a given key/value to the map, after the entry pointed by it.
	PutAfter(it OMapIterator[K, V], key K, value V) error
	// Get the value pointing by key, if found ok is true, or false otherwise.
	Get(key K) (value V, ok bool)
	// Get the iterator positioned at the given key.
	// If key was not found, the iterator will return at EOF and with IsValid() returning false.
	GetIteratorAt(key K) OMapIterator[K, V]
	// Delete the entry pointing by key.
	Delete(key K)
	// Returns the iterator of this map, at the beginning.
	Iterator() OMapIterator[K, V]
	// Returns the len of the map, similar to builtin len(map).
	Len() int
}

OMap is an ordered map that holds key/value and is able to iterate over the whole data-set in the same order as insertion has happened.

func New

func New[K comparable, V any]() OMap[K, V]

Create a new map using the default implementation, which is considered the best trade-off among all. Currently, OMapLinked is the winner.

func NewOMapBuiltin

func NewOMapBuiltin[K comparable, V any]() OMap[K, V]

func NewOMapLinked

func NewOMapLinked[K comparable, V any]() OMap[K, V]

Return a new OMap based on OMapLinked implementation, see OMapLinked type for more details of the implementation.

func NewOMapLinkedHash

func NewOMapLinkedHash[K comparable, V any]() OMap[K, V]

Return a new OMap based on OMapLinkedHash implementation, see OMapLinkedHash type for more details of the implementation.

func NewOMapSimple

func NewOMapSimple[K comparable, V any]() OMap[K, V]

Create a new OMap instance using OMapSimple implementation.

func NewOMapSync

func NewOMapSync[K comparable, V any]() OMap[K, V]

Create a new OMap instance using OMapSync implementation.

type OMapBuiltin

type OMapBuiltin[K comparable, V any] struct {
	// contains filtered or unexported fields
}

DO NOT USE THIS FOR REAL!!! Implements OMap interface but not very strictly, should be use only for comparison with builtin map

func (*OMapBuiltin[K, V]) Delete

func (m *OMapBuiltin[K, V]) Delete(key K)

func (*OMapBuiltin[K, V]) Get

func (m *OMapBuiltin[K, V]) Get(key K) (V, bool)

func (*OMapBuiltin[K, V]) GetIteratorAt

func (m *OMapBuiltin[K, V]) GetIteratorAt(key K) OMapIterator[K, V]

func (*OMapBuiltin[K, V]) Iterator

func (m *OMapBuiltin[K, V]) Iterator() OMapIterator[K, V]

func (*OMapBuiltin[K, V]) Len

func (m *OMapBuiltin[K, V]) Len() int

func (OMapBuiltin[K, V]) MarshalJSON

func (m OMapBuiltin[K, V]) MarshalJSON() ([]byte, error)

Implement json.Marshaler interface.

func (*OMapBuiltin[K, V]) Put

func (m *OMapBuiltin[K, V]) Put(key K, value V)

func (*OMapBuiltin[K, V]) PutAfter

func (m *OMapBuiltin[K, V]) PutAfter(interfaceIt OMapIterator[K, V], key K, value V) error

func (*OMapBuiltin[K, V]) String

func (m *OMapBuiltin[K, V]) String() string

Implement fmt.Stringer

func (OMapBuiltin[K, V]) UnmarshalJSON

func (m OMapBuiltin[K, V]) UnmarshalJSON(b []byte) error

Implement json.Unmarshaler interface.

type OMapBuiltinData

type OMapBuiltinData[K comparable, V any] struct {
	// contains filtered or unexported fields
}

type OMapBuiltinIterator

type OMapBuiltinIterator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Iterator over a OMapSimple, should be created through OMapSimple.Iterator() function.

func (*OMapBuiltinIterator[K, V]) EOF

func (it *OMapBuiltinIterator[K, V]) EOF() bool

func (OMapBuiltinIterator[K, V]) IsValid

func (it OMapBuiltinIterator[K, V]) IsValid() bool

func (*OMapBuiltinIterator[K, V]) Key

func (it *OMapBuiltinIterator[K, V]) Key() K

func (*OMapBuiltinIterator[K, V]) MoveBack

func (it *OMapBuiltinIterator[K, V]) MoveBack() OMapIterator[K, V]

func (*OMapBuiltinIterator[K, V]) MoveFront

func (it *OMapBuiltinIterator[K, V]) MoveFront() OMapIterator[K, V]

func (*OMapBuiltinIterator[K, V]) Next

func (it *OMapBuiltinIterator[K, V]) Next() bool

func (*OMapBuiltinIterator[K, V]) Prev

func (it *OMapBuiltinIterator[K, V]) Prev() bool

func (*OMapBuiltinIterator[K, V]) Value

func (it *OMapBuiltinIterator[K, V]) Value() V

type OMapIterator

type OMapIterator[K comparable, V any] interface {
	// Iterate to the next record, returning true if a record was found and false otherwise.
	Next() bool
	// Returns true if the iterator is past the last record.
	EOF() bool
	// Returns the key pointing to the current record.
	Key() K
	// Returns the value pointing to the current record.
	Value() V
	// Returns true if the iterator is positioned in a valid position (e.g. not BOF/EOF)
	IsValid() bool
	// Moves the iterator to the first position (BOF), and return itself (for easy of use)
	MoveFront() OMapIterator[K, V]
	// Moves the iterator to the last position (EOF), and return itself (for easy of use)
	MoveBack() OMapIterator[K, V]
	// Moves iterator backwards, returning true if a record was found and false otherwise.
	Prev() bool
}

Iterator over OMap.

type OMapLinked

type OMapLinked[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implements an ordered map using double-linked list for iteration.

func (*OMapLinked[K, V]) Delete

func (m *OMapLinked[K, V]) Delete(key K)

func (*OMapLinked[K, V]) Get

func (m *OMapLinked[K, V]) Get(key K) (V, bool)

func (*OMapLinked[K, V]) GetIteratorAt

func (m *OMapLinked[K, V]) GetIteratorAt(key K) OMapIterator[K, V]

func (*OMapLinked[K, V]) Iterator

func (m *OMapLinked[K, V]) Iterator() OMapIterator[K, V]

func (*OMapLinked[K, V]) Len

func (m *OMapLinked[K, V]) Len() int

func (OMapLinked[K, V]) MarshalJSON

func (m OMapLinked[K, V]) MarshalJSON() ([]byte, error)

Implement json.Marshaler interface.

func (*OMapLinked[K, V]) Put

func (m *OMapLinked[K, V]) Put(key K, value V)

func (*OMapLinked[K, V]) PutAfter

func (m *OMapLinked[K, V]) PutAfter(interfaceIt OMapIterator[K, V], key K, value V) error

func (*OMapLinked[K, V]) String

func (m *OMapLinked[K, V]) String() string

Implement fmt.Stringer

func (*OMapLinked[K, V]) UnmarshalJSON

func (m *OMapLinked[K, V]) UnmarshalJSON(b []byte) error

Implement json.Unmarshaler interface.

type OMapLinkedHash

type OMapLinkedHash[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implement an ordered map using a linked list but saving the key as an uint32 hash instead of copying the key into the map. This implementation should only be used when you have a very large object struct as K key, and preferable this object should implement Hasher interface to provide a performant hashing algorithm for the type.

func (*OMapLinkedHash[K, V]) Delete

func (m *OMapLinkedHash[K, V]) Delete(key K)

func (*OMapLinkedHash[K, V]) Get

func (m *OMapLinkedHash[K, V]) Get(key K) (V, bool)

func (*OMapLinkedHash[K, V]) GetIteratorAt

func (m *OMapLinkedHash[K, V]) GetIteratorAt(key K) OMapIterator[K, V]

func (*OMapLinkedHash[K, V]) Iterator

func (m *OMapLinkedHash[K, V]) Iterator() OMapIterator[K, V]

func (*OMapLinkedHash[K, V]) Len

func (m *OMapLinkedHash[K, V]) Len() int

func (OMapLinkedHash[K, V]) MarshalJSON

func (m OMapLinkedHash[K, V]) MarshalJSON() ([]byte, error)

Implement json.Marshaler interface.

func (*OMapLinkedHash[K, V]) Put

func (m *OMapLinkedHash[K, V]) Put(key K, value V)

func (*OMapLinkedHash[K, V]) PutAfter

func (m *OMapLinkedHash[K, V]) PutAfter(interfaceIt OMapIterator[K, V], key K, value V) error

func (*OMapLinkedHash[K, V]) String

func (m *OMapLinkedHash[K, V]) String() string

Implement fmt.Stringer

func (*OMapLinkedHash[K, V]) UnmarshalJSON

func (m *OMapLinkedHash[K, V]) UnmarshalJSON(b []byte) error

Implement json.Unmarshaler interface.

type OMapLinkedHashIterator

type OMapLinkedHashIterator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implement OMapIterator for OMapLinkedHash

func (*OMapLinkedHashIterator[K, V]) EOF

func (it *OMapLinkedHashIterator[K, V]) EOF() bool

func (*OMapLinkedHashIterator[K, V]) IsValid

func (it *OMapLinkedHashIterator[K, V]) IsValid() bool

func (*OMapLinkedHashIterator[K, V]) Key

func (it *OMapLinkedHashIterator[K, V]) Key() K

func (*OMapLinkedHashIterator[K, V]) MoveBack

func (it *OMapLinkedHashIterator[K, V]) MoveBack() OMapIterator[K, V]

func (*OMapLinkedHashIterator[K, V]) MoveFront

func (it *OMapLinkedHashIterator[K, V]) MoveFront() OMapIterator[K, V]

func (*OMapLinkedHashIterator[K, V]) Next

func (it *OMapLinkedHashIterator[K, V]) Next() bool

func (*OMapLinkedHashIterator[K, V]) Prev

func (it *OMapLinkedHashIterator[K, V]) Prev() bool

func (*OMapLinkedHashIterator[K, V]) Value

func (it *OMapLinkedHashIterator[K, V]) Value() V

type OMapLinkedIterator

type OMapLinkedIterator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implements OMapIterator for OMapLinked.

func (*OMapLinkedIterator[K, V]) EOF

func (it *OMapLinkedIterator[K, V]) EOF() bool

func (*OMapLinkedIterator[K, V]) IsValid

func (it *OMapLinkedIterator[K, V]) IsValid() bool

func (*OMapLinkedIterator[K, V]) Key

func (it *OMapLinkedIterator[K, V]) Key() K

func (*OMapLinkedIterator[K, V]) MoveBack

func (it *OMapLinkedIterator[K, V]) MoveBack() OMapIterator[K, V]

func (*OMapLinkedIterator[K, V]) MoveFront

func (it *OMapLinkedIterator[K, V]) MoveFront() OMapIterator[K, V]

func (*OMapLinkedIterator[K, V]) Next

func (it *OMapLinkedIterator[K, V]) Next() bool

func (*OMapLinkedIterator[K, V]) Prev

func (it *OMapLinkedIterator[K, V]) Prev() bool

func (*OMapLinkedIterator[K, V]) Value

func (it *OMapLinkedIterator[K, V]) Value() V

type OMapSimple

type OMapSimple[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implements a OMap interface using a very simple algorithm: it basically keeps a map[K]V to hold the mappings, and a []K slice to keep the order (hence doubling the memory used to store the keys, compared to a simple Go map).

func (*OMapSimple[K, V]) Delete

func (m *OMapSimple[K, V]) Delete(key K)

Delete the value pointing to the given key. Complexity: O(n)

func (*OMapSimple[K, V]) Get

func (m *OMapSimple[K, V]) Get(key K) (V, bool)

Get the value pointing to the given key, returning true as second argument if found, and false otherwise. Complexity: O(1), same as builtin map[key]

func (*OMapSimple[K, V]) GetIteratorAt

func (m *OMapSimple[K, V]) GetIteratorAt(key K) OMapIterator[K, V]

func (*OMapSimple[K, V]) Iterator

func (m *OMapSimple[K, V]) Iterator() OMapIterator[K, V]

Return an iterator to navigate the map.

func (*OMapSimple[K, V]) Len

func (m *OMapSimple[K, V]) Len() int

func (OMapSimple[K, V]) MarshalJSON

func (m OMapSimple[K, V]) MarshalJSON() ([]byte, error)

Implement json.Marshaler interface.

func (*OMapSimple[K, V]) Put

func (m *OMapSimple[K, V]) Put(key K, value V)

Add/overwrite the value in the map on the given key. Important to note that if a key existed and is being overwritten, the order of the old key insertion position will remain when iterating the map. Complexity: O(1)

func (*OMapSimple[K, V]) PutAfter

func (m *OMapSimple[K, V]) PutAfter(interfaceIt OMapIterator[K, V], key K, value V) error

func (*OMapSimple[K, V]) String

func (m *OMapSimple[K, V]) String() string

Implement fmt.Stringer

func (*OMapSimple[K, V]) UnmarshalJSON

func (m *OMapSimple[K, V]) UnmarshalJSON(b []byte) error

Implement json.Unmarshaler interface.

type OMapSimpleIterator

type OMapSimpleIterator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Iterator over a OMapSimple, should be created through OMapSimple.Iterator() function.

func (OMapSimpleIterator[K, V]) EOF

func (it OMapSimpleIterator[K, V]) EOF() bool

Returns true if iterator has reached the end

func (OMapSimpleIterator[K, V]) IsValid

func (it OMapSimpleIterator[K, V]) IsValid() bool

func (OMapSimpleIterator[K, V]) Key

func (it OMapSimpleIterator[K, V]) Key() K

Return the key at current record. Calling this function when EOF() is true will cause a panic.

func (*OMapSimpleIterator[K, V]) MoveBack

func (it *OMapSimpleIterator[K, V]) MoveBack() OMapIterator[K, V]

func (*OMapSimpleIterator[K, V]) MoveFront

func (it *OMapSimpleIterator[K, V]) MoveFront() OMapIterator[K, V]

func (*OMapSimpleIterator[K, V]) Next

func (it *OMapSimpleIterator[K, V]) Next() bool

Move iterator to the next record, returning true if there is a next value and false otherwise. Complexity: in general should be O(1), but it needs to skip deleted keys, so if there M deleted keys on the current position, it will be O(M). It is a trade-off to avoid making Delete O(N).

func (*OMapSimpleIterator[K, V]) Prev

func (it *OMapSimpleIterator[K, V]) Prev() bool

func (OMapSimpleIterator[K, V]) Value

func (it OMapSimpleIterator[K, V]) Value() V

Return the value at current record. Calling this function when EOF() is true will cause a panic.

type OMapSync

type OMapSync[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Implements a OMap interface using a very simple algorithm: it basically keeps a map[K]V to hold the mappings, and a []K slice to keep the order (hence doubling the memory used to store the keys, compared to a simple Go map).

func (*OMapSync[K, V]) Delete

func (m *OMapSync[K, V]) Delete(key K)

Delete the value pointing to the given key. Complexity: same as builtin [delete](https://pkg.go.dev/builtin#delete)

func (*OMapSync[K, V]) Get

func (m *OMapSync[K, V]) Get(key K) (V, bool)

Get the value pointing to the given key, returning true as second argument if found, and false otherwise. Complexity: O(1), same as builtin map[key]

func (*OMapSync[K, V]) GetIteratorAt

func (m *OMapSync[K, V]) GetIteratorAt(key K) OMapIterator[K, V]

func (*OMapSync[K, V]) Iterator

func (m *OMapSync[K, V]) Iterator() OMapIterator[K, V]

Return an iterator to navigate the map.

func (*OMapSync[K, V]) Len

func (m *OMapSync[K, V]) Len() int

func (*OMapSync[K, V]) MarshalJSON

func (m *OMapSync[K, V]) MarshalJSON() ([]byte, error)

Implement json.Marshaler interface.

func (*OMapSync[K, V]) Put

func (m *OMapSync[K, V]) Put(key K, value V)

Add/overwrite the value in the map on the given key. Important to note that if a key existed and is being overwritten, the order of the old key insertion position will remain when iterating the map. Complexity: O(1)

func (*OMapSync[K, V]) PutAfter

func (m *OMapSync[K, V]) PutAfter(interfaceIt OMapIterator[K, V], key K, value V) error

func (*OMapSync[K, V]) String

func (m *OMapSync[K, V]) String() string

Implement fmt.Stringer interface.

func (*OMapSync[K, V]) UnmarshalJSON

func (m *OMapSync[K, V]) UnmarshalJSON(b []byte) error

Implement json.Unmarshaler interface.

type OMapSyncIterator

type OMapSyncIterator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Iterator over a OMapSync, should be created through OMapSync.Iterator() function.

func (OMapSyncIterator[K, V]) EOF

func (it OMapSyncIterator[K, V]) EOF() bool

Returns true if iterator has reached the end

func (OMapSyncIterator[K, V]) IsValid

func (it OMapSyncIterator[K, V]) IsValid() bool

func (OMapSyncIterator[K, V]) Key

func (it OMapSyncIterator[K, V]) Key() K

Return the key at current record. Calling this function when EOF() is true will cause a panic.

func (*OMapSyncIterator[K, V]) MoveBack

func (it *OMapSyncIterator[K, V]) MoveBack() OMapIterator[K, V]

func (*OMapSyncIterator[K, V]) MoveFront

func (it *OMapSyncIterator[K, V]) MoveFront() OMapIterator[K, V]

func (*OMapSyncIterator[K, V]) Next

func (it *OMapSyncIterator[K, V]) Next() bool

Move iterator to the next record, returning true if there is a next value and false otherwise. Complexity: in general should be O(1), but it needs to skip deleted keys, so if there M deleted keys on the current position, it will be O(M). It is a trade-off to avoid making Delete O(N).

func (*OMapSyncIterator[K, V]) Prev

func (it *OMapSyncIterator[K, V]) Prev() bool

func (OMapSyncIterator[K, V]) Value

func (it OMapSyncIterator[K, V]) Value() V

Return the value at current record. Calling this function when EOF() is true will cause a panic.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL