immutable

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2020 License: MIT Imports: 6 Imported by: 0

README

Modification Notes

This repository is a minor modification of Ben Johnson's Immutable Repository. Ben's version automatically chooses a predefined hasher when keys have type int, string, or []byte. However, it will not automatically choose a hasher if keys have custom types based on those types, as in the following example:

type UserName int
m := immutable.NewMap(nil)
m = m.Set(UserName("jane"), 100)
m = m.Set(UserName("susy"), 200)
m = m.Set(UserName("jane"), 300)

This modified version uses reflection to determine the kind of the key types and automatically assigns a hasher on that basis. As a result, the example above works without the need to define a custom hasher for the UserName type.

Ben's original README appears below, unmodified:

Immutable

This repository contains immutable collection types for Go. It includes List, Map, and SortedMap implementations. Immutable collections can provide efficient, lock free sharing of data by requiring that edits to the collections return new collections.

The collection types in this library are meant to mimic Go built-in collections such asslice and map. The primary usage difference between Go collections and immutable collections is that immutable collections always return a new collection on mutation so you will need to save the new reference.

Immutable collections are not for every situation, however, as they can incur additional CPU and memory overhead. Please evaluate the cost/benefit for your particular project.

Special thanks to the Immutable.js team as the List & Map implementations are loose ports from that project.

List

The List type represents a sorted, indexed collection of values and operates similarly to a Go slice. It supports efficient append, prepend, update, and slice operations.

Adding list elements

Elements can be added to the end of the list with the Append() method or added to the beginning of the list with the Prepend() method. Unlike Go slices, prepending is as efficient as appending.

// Create a list with 3 elements.
l := immutable.NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Prepend("baz")

fmt.Println(l.Len())  // 3
fmt.Println(l.Get(0)) // "baz"
fmt.Println(l.Get(1)) // "foo"
fmt.Println(l.Get(2)) // "bar"

Note that each change to the list results in a new list being created. These lists are all snapshots at that point in time and cannot be changed so they are safe to share between multiple goroutines.

Updating list elements

You can also overwrite existing elements by using the Set() method. In the following example, we'll update the third element in our list and return the new list to a new variable. You can see that our old l variable retains a snapshot of the original value.

l := immutable.NewList()
l = l.Append("foo")
l = l.Append("bar")
newList := l.Set(2, "baz")

fmt.Println(l.Get(1))       // "bar"
fmt.Println(newList.Get(1)) // "baz"
Deriving sublists

You can create a sublist by using the Slice() method. This method works with the same rules as subslicing a Go slice:

l = l.Slice(0, 2)

fmt.Println(l.Len())  // 2
fmt.Println(l.Get(0)) // "baz"
fmt.Println(l.Get(1)) // "foo"

Please note that since List follows the same rules as slices, it will panic if you try to Get(), Set(), or Slice() with indexes that are outside of the range of the List.

Iterating lists

Iterators provide a clean, simple way to iterate over the elements of the list in order. This is more efficient than simply calling Get() for each index.

Below is an example of iterating over all elements of our list from above:

itr := l.Iterator()
for !itr.Done() {
	index, value := itr.Next()
	fmt.Printf("Index %d equals %v\n", index, value)
}

// Index 0 equals baz
// Index 1 equals foo

By default iterators start from index zero, however, the Seek() method can be used to jump to a given index.

Efficiently building lists

If you are building large lists, it is significantly more efficient to use the ListBuilder. It uses nearly the same API as List except that it updates a list in-place until you are ready to use it. This can improve bulk list building by 10x or more.

b := immutable.NewListBuilder(immutable.NewList())
b.Append("foo")
b.Append("bar")
b.Set(2, "baz")

l := b.List()
fmt.Println(l.Get(0)) // "foo"
fmt.Println(l.Get(1)) // "baz"

Lists are safe to use even after you continue to use the builder. It is also safe to build on top of existing lists.

Map

The Map represents an associative array that maps unique keys to values. It is implemented to act similarly to the built-in Go map type. It is implemented as a Hash-Array Mapped Trie.

Maps require a Hasher to hash keys and check for equality. There are built-in hasher implementations for int, string, and []byte keys. You may pass in a nil hasher to NewMap() if you are using one of these key types.

Setting map key/value pairs

You can add a key/value pair to the map by using the Set() method. It will add the key if it does not exist or it will overwrite the value for the key if it does exist.

Values may be fetched for a key using the Get() method. This method returns the value as well as a flag indicating if the key existed. The flag is useful to check if a nil value was set for a key versus a key did not exist.

m := immutable.NewMap(nil)
m = m.Set("jane", 100)
m = m.Set("susy", 200)
m = m.Set("jane", 300) // overwrite

fmt.Println(m.Len())   // 2

v, ok := m.Get("jane")
fmt.Println(v, ok)     // 300 true

v, ok = m.Get("susy")
fmt.Println(v, ok)     // 200, true

v, ok = m.Get("john")
fmt.Println(v, ok)     // nil, false
Removing map keys

Keys may be removed from the map by using the Delete() method. If the key does not exist then the original map is returned instead of a new one.

m := immutable.NewMap(nil)
m = m.Set("jane", 100)
m = m.Delete("jane")

fmt.Println(m.Len())   // 0

v, ok := m.Get("jane")
fmt.Println(v, ok)     // nil false
Iterating maps

Maps are unsorted, however, iterators can be used to loop over all key/value pairs in the collection. Unlike Go maps, iterators are deterministic when iterating over key/value pairs.

m := immutable.NewMap(nil)
m = m.Set("jane", 100)
m = m.Set("susy", 200)

itr := m.Iterator()
for !itr.Done() {
	k, v := itr.Next()
	fmt.Println(k, v)
}

// susy 200
// jane 100

Note that you should not rely on two maps with the same key/value pairs to iterate in the same order. Ordering can be insertion order dependent when two keys generate the same hash.

Efficiently building maps

If you are executing multiple mutations on a map, it can be much more efficient to use the MapBuilder. It uses nearly the same API as Map except that it updates a map in-place until you are ready to use it.

b := immutable.NewMapBuilder(immutable.NewMap(nil))
b.Set("foo", 100)
b.Set("bar", 200)
b.Set("foo", 300)

m := b.Map()
fmt.Println(m.Get("foo")) // "300"
fmt.Println(m.Get("bar")) // "200"

Maps are safe to use even after you continue to use the builder. You can also build on top of existing maps too.

Implementing a custom Hasher

If you need to use a key type besides int, string, or []byte then you'll need to create a custom Hasher implementation and pass it to NewMap() on creation.

Hashers are fairly simple. They only need to generate hashes for a given key and check equality given two keys.

type Hasher interface {
	Hash(key interface{}) uint32
	Equal(a, b interface{}) bool
}

Please see the internal intHasher, stringHasher, and byteSliceHasher for examples.

Sorted Map

The SortedMap represents an associative array that maps unique keys to values. Unlike the Map, however, keys can be iterated over in-order. It is implemented as a B+tree.

Sorted maps require a Comparer to sort keys and check for equality. There are built-in comparer implementations for int, string, and []byte keys. You may pass a nil comparer to NewSortedMap() if you are using one of these key types.

The API is identical to the Map implementation. The sorted map also has a companion SortedMapBuilder for more efficiently building maps.

Implementing a custom Comparer

If you need to use a key type besides int, string, or []byte then you'll need to create a custom Comparer implementation and pass it to NewSortedMap() on creation.

Comparers on have one method—Compare(). It works the same as the strings.Compare() function. It returns -1 if a is less than b, returns 1 if a is greater than b, and returns 0 if a is equal to b.

type Comparer interface {
	Compare(a, b interface{}) int
}

Please see the internal intComparer, stringComparer, and byteSliceComparer for examples.

Contributing

The goal of immutable is to provide stable, reasonably performant, immutable collections library for Go that has a simple, idiomatic API. As such, additional features and minor performance improvements will generally not be accepted. If you have a suggestion for a clearer API or substantial performance improvement, please open an issue first to discuss. All pull requests without a related issue will be closed immediately.

Please submit issues relating to bugs & documentation improvements.

Documentation

Overview

Package immutable provides immutable collection types.

Introduction

Immutable collections provide an efficient, safe way to share collections of data while minimizing locks. The collections in this package provide List, Map, and SortedMap implementations. These act similarly to slices and maps, respectively, except that altering a collection returns a new copy of the collection with that change.

Because collections are unable to change, they are safe for multiple goroutines to read from at the same time without a mutex. However, these types of collections come with increased CPU & memory usage as compared with Go's built-in collection types so please evaluate for your specific use.

Collection Types

The List type provides an API similar to Go slices. They allow appending, prepending, and updating of elements. Elements can also be fetched by index or iterated over using a ListIterator.

The Map & SortedMap types provide an API similar to Go maps. They allow values to be assigned to unique keys and allow for the deletion of keys. Values can be fetched by key and key/value pairs can be iterated over using the appropriate iterator type. Both map types provide the same API. The SortedMap, however, provides iteration over sorted keys while the Map provides iteration over unsorted keys. Maps improved performance and memory usage as compared to SortedMaps.

Hashing and Sorting

Map types require the use of a Hasher implementation to calculate hashes for their keys and check for key equality. SortedMaps require the use of a Comparer implementation to sort keys in the map.

These collection types automatically provide built-in hasher and comparers for int, string, and byte slice keys. If you are using one of these key types then simply pass a nil into the constructor. Otherwise you will need to implement a custom Hasher or Comparer type. Please see the provided implementations for reference.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Comparer

type Comparer interface {
	// Returns -1 if a is less than b, returns 1 if a is greater than b,
	// and returns 0 if a is equal to b.
	Compare(a, b interface{}) int
}

Comparer allows the comparison of two keys for the purpose of sorting.

type Hasher

type Hasher interface {
	// Computes a 32-bit hash for key.
	Hash(key interface{}) uint32

	// Returns true if a and b are equal.
	Equal(a, b interface{}) bool
}

Hasher hashes keys and checks them for equality.

type List

type List struct {
	// contains filtered or unexported fields
}

List is a dense, ordered, indexed collections. They are analogous to slices in Go. They can be updated by appending to the end of the list, prepending values to the beginning of the list, or updating existing indexes in the list.

func NewList

func NewList() *List

NewList returns a new empty instance of List.

func (*List) Append

func (l *List) Append(value interface{}) *List

Append returns a new list with value added to the end of the list.

Example
l := NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Append("baz")

fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
fmt.Println(l.Get(2))
Output:

foo
bar
baz

func (*List) Get

func (l *List) Get(index int) interface{}

Get returns the value at the given index. Similar to slices, this method will panic if index is below zero or is greater than or equal to the list size.

func (*List) Iterator

func (l *List) Iterator() *ListIterator

Iterator returns a new iterator for this list positioned at the first index.

Example
l := NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Append("baz")

itr := l.Iterator()
for !itr.Done() {
	i, v := itr.Next()
	fmt.Println(i, v)
}
Output:

0 foo
1 bar
2 baz
Example (Reverse)
l := NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Append("baz")

itr := l.Iterator()
itr.Last()
for !itr.Done() {
	i, v := itr.Prev()
	fmt.Println(i, v)
}
Output:

2 baz
1 bar
0 foo

func (*List) Len

func (l *List) Len() int

Len returns the number of elements in the list.

func (*List) Prepend

func (l *List) Prepend(value interface{}) *List

Prepend returns a new list with value added to the beginning of the list.

Example
l := NewList()
l = l.Prepend("foo")
l = l.Prepend("bar")
l = l.Prepend("baz")

fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
fmt.Println(l.Get(2))
Output:

baz
bar
foo

func (*List) Set

func (l *List) Set(index int, value interface{}) *List

Set returns a new list with value set at index. Similar to slices, this method will panic if index is below zero or if the index is greater than or equal to the list size.

Example
l := NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Set(1, "baz")

fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
Output:

foo
baz

func (*List) Slice

func (l *List) Slice(start, end int) *List

Slice returns a new list of elements between start index and end index. Similar to slices, this method will panic if start or end are below zero or greater than the list size. A panic will also occur if start is greater than end.

Unlike Go slices, references to inaccessible elements will be automatically removed so they can be garbage collected.

Example
l := NewList()
l = l.Append("foo")
l = l.Append("bar")
l = l.Append("baz")
l = l.Slice(1, 3)

fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
Output:

bar
baz

type ListBuilder

type ListBuilder struct {
	// contains filtered or unexported fields
}

ListBuilder represents an efficient builder for creating Lists.

Lists returned from the builder are safe to use even after you continue to use the builder. However, for efficiency, you should only retrieve your list after you have completed building it.

func NewListBuilder

func NewListBuilder(list *List) *ListBuilder

NewListBuilder returns a new instance of ListBuilder to build on a base list.

func (*ListBuilder) Append

func (b *ListBuilder) Append(value interface{})

Append adds value to the end of the list.

Example
b := NewListBuilder(NewList())
b.Append("foo")
b.Append("bar")
b.Append("baz")

l := b.List()
fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
fmt.Println(l.Get(2))
Output:

foo
bar
baz

func (*ListBuilder) Get

func (b *ListBuilder) Get(index int) interface{}

Get returns the value at the given index. Similar to slices, this method will panic if index is below zero or is greater than or equal to the list size.

func (*ListBuilder) Len

func (b *ListBuilder) Len() int

Len returns the number of elements in the underlying list.

func (*ListBuilder) List

func (b *ListBuilder) List() *List

List returns the current copy of the list. The returned list is safe to use even if after the builder continues to be used.

func (*ListBuilder) Prepend

func (b *ListBuilder) Prepend(value interface{})

Prepend adds value to the beginning of the list.

Example
b := NewListBuilder(NewList())
b.Prepend("foo")
b.Prepend("bar")
b.Prepend("baz")

l := b.List()
fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
fmt.Println(l.Get(2))
Output:

baz
bar
foo

func (*ListBuilder) Set

func (b *ListBuilder) Set(index int, value interface{})

Set updates the value at the given index. Similar to slices, this method will panic if index is below zero or if the index is greater than or equal to the list size.

Example
b := NewListBuilder(NewList())
b.Append("foo")
b.Append("bar")
b.Set(1, "baz")

l := b.List()
fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
Output:

foo
baz

func (*ListBuilder) Slice

func (b *ListBuilder) Slice(start, end int)

Slice updates the list with a sublist of elements between start and end index. See List.Slice() for more details.

Example
b := NewListBuilder(NewList())
b.Append("foo")
b.Append("bar")
b.Append("baz")
b.Slice(1, 3)

l := b.List()
fmt.Println(l.Get(0))
fmt.Println(l.Get(1))
Output:

bar
baz

type ListIterator

type ListIterator struct {
	// contains filtered or unexported fields
}

ListIterator represents an ordered iterator over a list.

func (*ListIterator) Done

func (itr *ListIterator) Done() bool

Done returns true if no more elements remain in the iterator.

func (*ListIterator) First

func (itr *ListIterator) First()

First positions the iterator on the first index. If source list is empty then no change is made.

func (*ListIterator) Last

func (itr *ListIterator) Last()

Last positions the iterator on the last index. If source list is empty then no change is made.

func (*ListIterator) Next

func (itr *ListIterator) Next() (index int, value interface{})

Next returns the current index and its value & moves the iterator forward. Returns an index of -1 if the there are no more elements to return.

func (*ListIterator) Prev

func (itr *ListIterator) Prev() (index int, value interface{})

Prev returns the current index and value and moves the iterator backward. Returns an index of -1 if the there are no more elements to return.

func (*ListIterator) Seek

func (itr *ListIterator) Seek(index int)

Seek moves the iterator position to the given index in the list. Similar to Go slices, this method will panic if index is below zero or if the index is greater than or equal to the list size.

type Map

type Map struct {
	// contains filtered or unexported fields
}

Map represents an immutable hash map implementation. The map uses a Hasher to generate hashes and check for equality of key values.

It is implemented as an Hash Array Mapped Trie.

func NewMap

func NewMap(hasher Hasher) *Map

NewMap returns a new instance of Map. If hasher is nil, a default hasher implementation will automatically be chosen based on the first key added. Default hasher implementations only exist for int, string, and byte slice types.

func (*Map) Delete

func (m *Map) Delete(key interface{}) *Map

Delete returns a map with the given key removed. Removing a non-existent key will cause this method to return the same map.

Example
m := NewMap(nil)
m = m.Set("foo", "bar")
m = m.Set("baz", 100)
m = m.Delete("baz")

v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)
Output:

foo bar true
baz <nil> false

func (*Map) Get

func (m *Map) Get(key interface{}) (value interface{}, ok bool)

Get returns the value for a given key and a flag indicating whether the key exists. This flag distinguishes a nil value set on a key versus a non-existent key in the map.

func (*Map) Iterator

func (m *Map) Iterator() *MapIterator

Iterator returns a new iterator for the map.

Example
m := NewMap(nil)
m = m.Set("apple", 100)
m = m.Set("grape", 200)
m = m.Set("kiwi", 300)
m = m.Set("mango", 400)
m = m.Set("orange", 500)
m = m.Set("peach", 600)
m = m.Set("pear", 700)
m = m.Set("pineapple", 800)
m = m.Set("strawberry", 900)

itr := m.Iterator()
for !itr.Done() {
	k, v := itr.Next()
	fmt.Println(k, v)
}
Output:

mango 400
pear 700
pineapple 800
grape 200
orange 500
strawberry 900
kiwi 300
peach 600
apple 100

func (*Map) Len

func (m *Map) Len() int

Len returns the number of elements in the map.

func (*Map) Set

func (m *Map) Set(key, value interface{}) *Map

Set returns a map with the key set to the new value. A nil value is allowed.

This function will return a new map even if the updated value is the same as the existing value because Map does not track value equality.

Example
m := NewMap(nil)
m = m.Set("foo", "bar")
m = m.Set("baz", 100)

v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)

v, ok = m.Get("bat") // does not exist
fmt.Println("bat", v, ok)
Output:

foo bar true
baz 100 true
bat <nil> false

type MapBuilder

type MapBuilder struct {
	// contains filtered or unexported fields
}

MapBuilder represents an efficient builder for creating Maps.

Maps returned from the builder are safe to use even after you continue to use the builder. However, for efficiency, you should only retrieve your map after you have completed building it.

func NewMapBuilder

func NewMapBuilder(m *Map) *MapBuilder

NewMapBuilder returns a new instance of MapBuilder to build on a base map.

func (*MapBuilder) Delete

func (b *MapBuilder) Delete(key interface{})

Delete removes the given key. See Map.Delete() for additional details.

Example
b := NewMapBuilder(NewMap(nil))
b.Set("foo", "bar")
b.Set("baz", 100)
b.Delete("baz")

m := b.Map()
v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)
Output:

foo bar true
baz <nil> false

func (*MapBuilder) Get

func (b *MapBuilder) Get(key interface{}) (value interface{}, ok bool)

Get returns the value for the given key.

func (*MapBuilder) Len

func (b *MapBuilder) Len() int

Len returns the number of elements in the underlying map.

func (*MapBuilder) Map

func (b *MapBuilder) Map() *Map

Map returns the current copy of the map. The returned map is safe to use even if after the builder continues to be used.

func (*MapBuilder) Set

func (b *MapBuilder) Set(key, value interface{})

Set sets the value of the given key. See Map.Set() for additional details.

Example
b := NewMapBuilder(NewMap(nil))
b.Set("foo", "bar")
b.Set("baz", 100)

m := b.Map()
v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)

v, ok = m.Get("bat") // does not exist
fmt.Println("bat", v, ok)
Output:

foo bar true
baz 100 true
bat <nil> false

type MapIterator

type MapIterator struct {
	// contains filtered or unexported fields
}

MapIterator represents an iterator over a map's key/value pairs. Although map keys are not sorted, the iterator's order is deterministic.

func (*MapIterator) Done

func (itr *MapIterator) Done() bool

Done returns true if no more elements remain in the iterator.

func (*MapIterator) First

func (itr *MapIterator) First()

First resets the iterator to the first key/value pair.

func (*MapIterator) Next

func (itr *MapIterator) Next() (key, value interface{})

Next returns the next key/value pair. Returns a nil key when no elements remain.

type SortedMap

type SortedMap struct {
	// contains filtered or unexported fields
}

SortedMap represents a map of key/value pairs sorted by key. The sort order is determined by the Comparer used by the map.

This map is implemented as a B+tree.

func NewSortedMap

func NewSortedMap(comparer Comparer) *SortedMap

NewSortedMap returns a new instance of SortedMap. If comparer is nil then a default comparer is set after the first key is inserted. Default comparers exist for int, string, and byte slice keys.

func (*SortedMap) Delete

func (m *SortedMap) Delete(key interface{}) *SortedMap

Delete returns a copy of the map with the key removed. Returns the original map if key does not exist.

Example
m := NewSortedMap(nil)
m = m.Set("foo", "bar")
m = m.Set("baz", 100)
m = m.Delete("baz")

v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)
Output:

foo bar true
baz <nil> false

func (*SortedMap) Get

func (m *SortedMap) Get(key interface{}) (interface{}, bool)

Get returns the value for a given key and a flag indicating if the key is set. The flag can be used to distinguish between a nil-set key versus an unset key.

func (*SortedMap) Iterator

func (m *SortedMap) Iterator() *SortedMapIterator

Iterator returns a new iterator for this map positioned at the first key.

Example
m := NewSortedMap(nil)
m = m.Set("strawberry", 900)
m = m.Set("kiwi", 300)
m = m.Set("apple", 100)
m = m.Set("pear", 700)
m = m.Set("pineapple", 800)
m = m.Set("peach", 600)
m = m.Set("orange", 500)
m = m.Set("grape", 200)
m = m.Set("mango", 400)

itr := m.Iterator()
for !itr.Done() {
	k, v := itr.Next()
	fmt.Println(k, v)
}
Output:

apple 100
grape 200
kiwi 300
mango 400
orange 500
peach 600
pear 700
pineapple 800
strawberry 900

func (*SortedMap) Len

func (m *SortedMap) Len() int

Len returns the number of elements in the sorted map.

func (*SortedMap) Set

func (m *SortedMap) Set(key, value interface{}) *SortedMap

Set returns a copy of the map with the key set to the given value.

Example
m := NewSortedMap(nil)
m = m.Set("foo", "bar")
m = m.Set("baz", 100)

v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)

v, ok = m.Get("bat") // does not exist
fmt.Println("bat", v, ok)
Output:

foo bar true
baz 100 true
bat <nil> false

type SortedMapBuilder

type SortedMapBuilder struct {
	// contains filtered or unexported fields
}

SortedMapBuilder represents an efficient builder for creating sorted maps.

Maps returned from the builder are safe to use even after you continue to use the builder. However, for efficiency, you should only retrieve your map after you have completed building it.

func NewSortedMapBuilder

func NewSortedMapBuilder(m *SortedMap) *SortedMapBuilder

NewSortedMapBuilder returns a new instance of SortedMapBuilder to build on a base map.

func (*SortedMapBuilder) Delete

func (b *SortedMapBuilder) Delete(key interface{})

Delete removes the given key. See SortedMap.Delete() for additional details.

Example
b := NewSortedMapBuilder(NewSortedMap(nil))
b.Set("foo", "bar")
b.Set("baz", 100)
b.Delete("baz")

m := b.Map()
v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)
Output:

foo bar true
baz <nil> false

func (*SortedMapBuilder) Get

func (b *SortedMapBuilder) Get(key interface{}) (value interface{}, ok bool)

Get returns the value for the given key.

func (*SortedMapBuilder) Len

func (b *SortedMapBuilder) Len() int

Len returns the number of elements in the underlying map.

func (*SortedMapBuilder) Map

func (b *SortedMapBuilder) Map() *SortedMap

SortedMap returns the current copy of the map. The returned map is safe to use even if after the builder continues to be used.

func (*SortedMapBuilder) Set

func (b *SortedMapBuilder) Set(key, value interface{})

Set sets the value of the given key. See SortedMap.Set() for additional details.

Example
b := NewSortedMapBuilder(NewSortedMap(nil))
b.Set("foo", "bar")
b.Set("baz", 100)

m := b.Map()
v, ok := m.Get("foo")
fmt.Println("foo", v, ok)

v, ok = m.Get("baz")
fmt.Println("baz", v, ok)

v, ok = m.Get("bat") // does not exist
fmt.Println("bat", v, ok)
Output:

foo bar true
baz 100 true
bat <nil> false

type SortedMapIterator

type SortedMapIterator struct {
	// contains filtered or unexported fields
}

SortedMapIterator represents an iterator over a sorted map. Iteration can occur in natural or reverse order based on use of Next() or Prev().

func (*SortedMapIterator) Done

func (itr *SortedMapIterator) Done() bool

Done returns true if no more key/value pairs remain in the iterator.

func (*SortedMapIterator) First

func (itr *SortedMapIterator) First()

First moves the iterator to the first key/value pair.

func (*SortedMapIterator) Last

func (itr *SortedMapIterator) Last()

Last moves the iterator to the last key/value pair.

func (*SortedMapIterator) Next

func (itr *SortedMapIterator) Next() (key, value interface{})

Next returns the current key/value pair and moves the iterator forward. Returns a nil key if the there are no more elements to return.

func (*SortedMapIterator) Prev

func (itr *SortedMapIterator) Prev() (key, value interface{})

Prev returns the current key/value pair and moves the iterator backward. Returns a nil key if the there are no more elements to return.

func (*SortedMapIterator) Seek

func (itr *SortedMapIterator) Seek(key interface{})

Seek moves the iterator position to the given key in the map. If the key does not exist then the next key is used. If no more keys exist then the iteartor is marked as done.

Jump to

Keyboard shortcuts

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