immutable

package module
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2025 License: MIT Imports: 6 Imported by: 0

README

Immutable release test coverage license

This repository contains generic immutable collection types for Go. It includes List, Map, SortedMap, Set and SortedSet 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.

This project is a fork of github.com/benbjohnson/immutable with additional performance enhancements and builder APIs.

Performance: This library includes batch builders that provide high accelaration for bulk operations (vs. discreet insert), with optimized memory usage and automatic batching. Regular operations maintain ~2x overhead compared to Go's built-in collections while providing thread-safe immutability.

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.

Forked from https://github.com/benbjohnson/immutable with the following enhancements:

Performance Optimizations

Memory Architecture Improvements:

  • Hybrid Data Structures:
    • List: Uses a simple slice for small lists (< 32 elements) for up to 2x faster operations and ~85% less memory usage in common cases, transparently converting to a HAMT for larger sizes.
    • Map: Small-structure fast paths via builder initial flush and tiny array-node updates (≤ 8 keys); core Map remains HAMT.
  • Pointer-Based Array Sharing (planned): Reduce allocations in mapHashArrayNode.clone() via pointer-backed children with copy-on-write
  • Lazy Copy-on-Write: Arrays shared via pointers until actual modification, reducing memory overhead by 6-8%
  • Cache-Friendly Design: Improved memory layout for better CPU cache utilization

Concurrency with immutable collections

Immutable structures are snapshot-based: every mutation returns a new instance; the original remains unchanged. This makes concurrent reads safe without locks.

  • Recommended pattern: a single writer goroutine owns the evolving collection and applies updates received via a channel. It then sends immutable snapshots to readers.
  • Readers can safely use received snapshots without copying. Structural sharing ensures those snapshots are cheap to create and pass around.
  • If you need a single, shared, evolving reference updated by multiple goroutines, synchronize the reference update (mutex or atomic CAS on a pointer). Without that, simultaneous Enqueue/Dequeue on the same snapshot may race logically (e.g., multiple consumers reading the same head, or lost enqueues).
  • Builders are mutable conveniences and are not safe for concurrent use; keep them confined to one goroutine.
Batch Builders

Complete High-Performance Builder Suite:

  • BatchListBuilder: up 19x faster in tests (vs. discreet ops) bulk list construction with configurable batch sizes
  • BatchMapBuilder: Measured gains on bulk construction; biggest wins for initial tiny batches and small structures
  • BatchSetBuilder & BatchSortedSetBuilder: Efficient bulk set construction
  • StreamingListBuilder & StreamingMapBuilder: Auto-flush with functional operations (filter, transform)
  • SortedBatchBuilder: Optimized sorted map construction with optional sort maintenance

Functional Programming Features:

  • Stream processing with automatic memory management
  • Filter and transform operations for bulk data processing
  • Configurable auto-flush thresholds for memory efficiency
Enhanced Testing & Validation

Comprehensive Test Coverage:

  • Extensive benchmark suite measuring performance improvements
  • Memory profiling and allocation analysis
  • Race condition testing (go test -race) for thread safety validation
  • Edge case and error condition testing for all new builders
  • Large-scale performance validation (100-100K elements)
Architectural Enhancements

Thread Safety & Immutability:

  • Lock-free operations with atomic copying
  • Structural sharing maintains thread safety
  • Zero-overhead abstractions (Sets inherit Map optimizations)

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[string]()
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[string]()
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.

Searching list elements

You can check if a value exists in the list using Contains(). For comparable types, equality uses ==. For non-comparable types (e.g., []byte), it falls back to reflect.DeepEqual.

// Basic usage
l := immutable.NewList[int]()
for i := 0; i < 5; i++ { l = l.Append(i) }

fmt.Println(l.Contains(3))  // true
fmt.Println(l.Contains(10)) // false

// Non-comparable example uses DeepEqual under the hood
b := immutable.NewList[[]byte]([]byte("foo"), []byte("bar"))
fmt.Println(b.Contains([]byte("foo"))) // true

For full control and best performance on custom types, use ContainsFunc() to provide an equality function:

type node struct{ v int }
l := immutable.NewList[*node](&node{v: 1}, &node{v: 2})

eq := func(a, b *node) bool { return a != nil && b != nil && a.v == b.v }
fmt.Println(l.ContainsFunc(&node{v: 2}, eq)) // true
fmt.Println(l.ContainsFunc(&node{v: 3}, eq)) // false
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.

For even better performance with bulk operations (100+ elements), see the Advanced Batch Builders section which provides up to 19x performance improvements.

b := immutable.NewListBuilder[string]()
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"

Builders are invalid after the call to List().

Queue

An immutable FIFO queue with amortized O(1) Enqueue, Dequeue, and Peek, implemented using a two-list (Okasaki) representation. Internally it reuses List[T] for structural sharing and uses the slice fast-path for small sizes.

q := immutable.NewQueue[int]()
q = q.Enqueue(1).Enqueue(2).Enqueue(3)

v, ok := q.Peek() // v=1, ok=true

q, v, ok = q.Dequeue() // v=1, ok=true
q, v, ok = q.Dequeue() // v=2, ok=true

itr := q.Iterator()
for !itr.Done() {
    idx, x, _ := itr.Next()
    _ = idx
    _ = x
}

// Builder
b := immutable.NewQueueBuilder[int]()
b.Enqueue(10)
b.EnqueueSlice([]int{20, 30})
finalQ := b.Queue()

Thread safety: operations return new queues; existing instances are never mutated, so concurrent reads are safe.

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 most primitive types such as int, uint, and string 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[string,int](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[string,int](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[string,int](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.

For enhanced performance with bulk operations, see the Advanced Batch Builders section which provides additional optimizations and functional programming capabilities.

b := immutable.NewMapBuilder[string,int](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"

Builders are invalid after the call to Map().

Implementing a custom Hasher

If you need to use a key type besides int, uint, or string 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.

Security Note: A poorly implemented Hasher can result in frequent hash collisions, which will degrade the Map's performance from O(log n) to O(n), making it vulnerable to algorithmic complexity attacks (a form of Denial of Service). Ensure your Hash function provides a good distribution.

type Hasher[K any] interface {
	Hash(key K) uint32
	Equal(a, b K) bool
}

Please see the internal intHasher, uintHasher, 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, uint, and string 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, uint, or string or derived types, then you'll need to create a custom Comparer implementation and pass it to NewSortedMap() on creation.

Security Note: A slow Comparer implementation can severely degrade the performance of all SortedMap operations, making it vulnerable to Denial of Service attacks. Ensure your Compare function is efficient.

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[K any] interface {
	Compare(a, b K) int
}

Please see the internal defaultComparer for an example, bearing in mind that it works for several types.

Set

The Set represents a collection of unique values, and it is implemented as a wrapper around a Map[T, struct{}].

Like Maps, Sets require a Hasher to hash keys and check for equality. There are built-in hasher implementations for most primitive types such as int, uint, and string keys. You may pass in a nil hasher to NewSet() if you are using one of these key types.

Sorted Set

The SortedSet represents a sorted collection of unique values. Unlike the Set, however, keys can be iterated over in-order. It is implemented as a B+tree.

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

The API is identical to the Set implementation.

Advanced Batch Builders

For high-performance bulk operations, this library provides advanced batch builders that can dramatically improve performance for large-scale data construction. These builders use internal batching and mutable operations to minimize allocations and provide up to 19x performance improvements for bulk operations.

Batch List Builder

The BatchListBuilder provides batched list construction with configurable batch sizes for optimal performance:

// Create a batch builder with batch size of 64
builder := immutable.NewBatchListBuilder[int](64)

// Add many elements efficiently
for i := 0; i < 10000; i++ {
    builder.Append(i)
}

// Or add slices efficiently
values := []int{1, 2, 3, 4, 5}
builder.AppendSlice(values)

list := builder.List() // 19x faster than individual Append() calls

Performance: Up to 19x faster than direct construction for large lists.

Batch Map Builder

The BatchMapBuilder provides batched map construction with automatic flushing:

// Create a batch map builder with batch size of 32
builder := immutable.NewBatchMapBuilder[string, int](nil, 32)

// Add many entries efficiently
for i := 0; i < 10000; i++ {
    builder.Set(fmt.Sprintf("key-%d", i), i)
}

// Or add from existing maps
entries := map[string]int{"a": 1, "b": 2, "c": 3}
builder.SetMap(entries)

m := builder.Map() // 8% faster + 5.8% less memory than regular builder

Performance: 8% faster with 5.8% memory reduction compared to regular builders.

Streaming Builders

Streaming builders provide auto-flush capabilities and functional operations:

// Streaming list builder with auto-flush at 1000 elements
builder := immutable.NewStreamingListBuilder[int](32, 1000)

// Functional operations
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

// Filter even numbers
builder.Filter(data, func(x int) bool { return x%2 == 0 })

// Transform by doubling
builder.Transform(data, func(x int) int { return x * 2 })

list := builder.List() // Contains processed elements
// Streaming map builder with auto-flush and bulk operations
builder := immutable.NewStreamingMapBuilder[int, string](nil, 32, 500)

// Add individual entries (auto-flushes at 500 elements)
for i := 0; i < 1000; i++ {
    builder.Set(i, fmt.Sprintf("value-%d", i))
}

// Bulk operations with auto-flush
builder.SetMany(map[int]string{10: "ten", 20: "twenty", 30: "thirty"})

m := builder.Map()
Batch Set Builders

Set builders provide efficient bulk set construction:

// Batch set builder
builder := immutable.NewBatchSetBuilder[string](nil, 64)

values := []string{"apple", "banana", "cherry", "apple"} // "apple" duplicate
builder.AddSlice(values)

set := builder.Set() // Contains 3 unique values

// Sorted set builder with sort maintenance
sortedBuilder := immutable.NewBatchSortedSetBuilder[int](nil, 32, true)
numbers := []int{5, 2, 8, 1, 9, 3}
sortedBuilder.AddSlice(numbers)

sortedSet := sortedBuilder.SortedSet() // Automatically sorted: [1, 2, 3, 5, 8, 9]
Sorted Batch Builder

For sorted maps, use SortedBatchBuilder with optional sort maintenance:

// Maintain sort order in buffer for optimal insertion
builder := immutable.NewSortedBatchBuilder[int, string](nil, 32, true)

// Add in random order - automatically maintained in sorted buffer
builder.Set(3, "three")
builder.Set(1, "one")
builder.Set(2, "two")

sm := builder.SortedMap() // Efficiently constructed sorted map
Performance Guidelines

When to use batch builders:

  • Building collections with 100+ elements
  • Bulk data import/export operations
  • Processing large datasets
  • When memory efficiency is critical

Batch size recommendations:

  • Small operations (< 1K elements): 16-32
  • Medium operations (1K-10K elements): 32-64
  • Large operations (> 10K elements): 64-128
  • Memory-constrained environments: 16-32

Performance improvements:

  • List construction: Up to 19x faster for bulk operations
  • Map construction: 8% faster with 5.8% memory reduction
  • Set construction: Inherits map performance benefits
  • Streaming operations: Automatic memory management with functional programming

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.

What's New (2025-09)
  • zero dependencies
  • Small-structure fast paths:
    • List: Batch flush extends slice-backed lists in a single allocation
    • Map: Empty-map batch flush builds an array node in one shot (last-write-wins); tiny array-node updates applied in-place when under threshold
  • New builder APIs:
    • (*BatchListBuilder).Reset() and (*BatchMapBuilder).Reset() for builder reuse without reallocations
  • Concurrency:
    • Added concurrent read benchmarks and mixed read/write benchmarks (immutable Map vs sync.Map)
    • Added concurrency correctness tests (copy-on-write isolation under concurrent readers)
Current Performance Snapshot
  • Map Get (10K): immutable ~14.5 ns/op (0 allocs); builtin map ~6.8 ns/op; sync.Map Load ~20.3 ns/op
  • Map RandomSet (10K): ~595–687 ns/op, 1421 B/op, 7 allocs/op (after tuning)
  • Concurrent reads (ns/op, lower is better):
    • 1G: immutable 3.53 vs sync.Map 6.03
    • 4G: immutable 2.31 vs sync.Map 3.21
    • 16G: immutable 2.39 vs sync.Map 3.24
  • Mixed read/write (ns/op):
    • 90/10 (9R/1W): immutable 26.0 vs sync.Map 38.4
    • 70/30 (7R/3W): immutable 24.6 vs sync.Map 65.0
    • 50/50 (5R/5W): immutable 27.3 vs sync.Map 47.4
New APIs (Builders)
// Reuse list builder across batches without reallocations
lb := immutable.NewBatchListBuilder[int](64)
// ... append/flush ...
lb.Reset() // clears state, keeps capacity

// Reuse map builder and retain hasher
mb := immutable.NewBatchMapBuilder[string,int](nil, 64)
// ... set/flush ...
mb.Reset() // clears state, preserves hasher & buffer capacity
Benchmarking & Profiling
  • Run all benchmarks with allocations:
go test -bench=. -benchmem -count=3 ./...
  • Profile a representative write-heavy benchmark:
# CPU and memory profiles (example: Map RandomSet, size=10K)
go test -bench=BenchmarkMap_RandomSet/size-10000 -benchmem -run="^$" \
  -cpuprofile=cpu.prof -memprofile=mem.prof -count=1

# Inspect hotspots
go tool pprof -top cpu.prof
go tool pprof -top -sample_index=alloc_space mem.prof

Optional: Enable PGO locally

# Generate a profile and write default.pgo
go test -bench=. -run="^$" -cpuprofile=cpu.prof -count=1
go tool pprof -proto cpu.prof > cpu.pb.gz
go tool pgo -compile=local -o default.pgo cpu.pb.gz

# Use the profile for builds/tests (Go 1.21+)
go test -bench=. -benchmem -count=3 -pgo=auto ./...
  • Compare immutable vs sync.Map concurrent reads:
go test -bench=BenchmarkConcurrentReads -benchmem -run="^$" -count=1
  • Mixed workload (reads/writes):
go test -bench=BenchmarkConcurrentMixed -benchmem -run="^$" -count=1

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 BatchListBuilder

type BatchListBuilder[T any] struct {
	// contains filtered or unexported fields
}

BatchListBuilder provides enhanced batch operations for efficient List construction. Optimized for bulk insertions with minimal allocations.

func NewBatchListBuilder

func NewBatchListBuilder[T any](batchSize int) *BatchListBuilder[T]

NewBatchListBuilder returns a new batch-optimized list builder. batchSize determines the internal buffer size for batch operations.

func (*BatchListBuilder[T]) Append

func (b *BatchListBuilder[T]) Append(value T)

Append adds a single value to the batch buffer. Values are flushed to the list when buffer reaches capacity.

func (*BatchListBuilder[T]) AppendSlice

func (b *BatchListBuilder[T]) AppendSlice(values []T)

AppendSlice adds multiple values efficiently. Automatically handles batching for optimal performance.

func (*BatchListBuilder[T]) Flush

func (b *BatchListBuilder[T]) Flush()

Flush commits all buffered values to the underlying list.

func (*BatchListBuilder[T]) Len

func (b *BatchListBuilder[T]) Len() int

Len returns the total number of elements (committed + buffered).

func (*BatchListBuilder[T]) List

func (b *BatchListBuilder[T]) List() *List[T]

List returns the final list and invalidates the builder. Automatically flushes any remaining buffered values.

func (*BatchListBuilder[T]) Reset

func (b *BatchListBuilder[T]) Reset()

Reset clears the builder state while retaining buffer capacity.

type BatchMapBuilder

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

BatchMapBuilder provides enhanced batch operations for efficient Map construction.

func NewBatchMapBuilder

func NewBatchMapBuilder[K comparable, V any](hasher Hasher[K], batchSize int) *BatchMapBuilder[K, V]

NewBatchMapBuilder returns a new batch-optimized map builder.

func (*BatchMapBuilder[K, V]) Flush

func (b *BatchMapBuilder[K, V]) Flush()

Flush commits all buffered entries to the underlying map.

func (*BatchMapBuilder[K, V]) Len

func (b *BatchMapBuilder[K, V]) Len() int

Len returns the total number of entries (committed + buffered).

func (*BatchMapBuilder[K, V]) Map

func (b *BatchMapBuilder[K, V]) Map() *Map[K, V]

Map returns the final map and invalidates the builder.

func (*BatchMapBuilder[K, V]) Reset

func (b *BatchMapBuilder[K, V]) Reset()

Reset clears the builder state while retaining buffer capacity.

func (*BatchMapBuilder[K, V]) Set

func (b *BatchMapBuilder[K, V]) Set(key K, value V)

Set adds a key/value pair to the batch buffer.

func (*BatchMapBuilder[K, V]) SetMap

func (b *BatchMapBuilder[K, V]) SetMap(entries map[K]V)

SetMap adds all entries from a regular Go map.

type BatchSetBuilder

type BatchSetBuilder[T comparable] struct {
	// contains filtered or unexported fields
}

BatchSetBuilder provides enhanced batch operations for efficient Set construction.

func NewBatchSetBuilder

func NewBatchSetBuilder[T comparable](hasher Hasher[T], batchSize int) *BatchSetBuilder[T]

NewBatchSetBuilder returns a new batch-optimized set builder.

func (*BatchSetBuilder[T]) Add

func (b *BatchSetBuilder[T]) Add(value T)

Add inserts a value into the batch buffer.

func (*BatchSetBuilder[T]) AddSlice

func (b *BatchSetBuilder[T]) AddSlice(values []T)

AddSlice adds multiple values efficiently.

func (*BatchSetBuilder[T]) Flush

func (b *BatchSetBuilder[T]) Flush()

Flush commits all buffered values to the underlying set.

func (*BatchSetBuilder[T]) Len

func (b *BatchSetBuilder[T]) Len() int

Len returns the total number of elements (committed + buffered).

func (*BatchSetBuilder[T]) Set

func (b *BatchSetBuilder[T]) Set() *Set[T]

Set returns the final set and invalidates the builder.

type BatchSortedSetBuilder

type BatchSortedSetBuilder[T cmp.Ordered] struct {
	// contains filtered or unexported fields
}

BatchSortedSetBuilder provides enhanced batch operations for efficient SortedSet construction.

func NewBatchSortedSetBuilder

func NewBatchSortedSetBuilder[T cmp.Ordered](comparer Comparer[T], batchSize int, maintainSort bool) *BatchSortedSetBuilder[T]

NewBatchSortedSetBuilder returns a new batch-optimized sorted set builder.

func (*BatchSortedSetBuilder[T]) Add

func (b *BatchSortedSetBuilder[T]) Add(value T)

Add inserts a value into the batch buffer, maintaining sort order if enabled.

func (*BatchSortedSetBuilder[T]) AddSlice

func (b *BatchSortedSetBuilder[T]) AddSlice(values []T)

AddSlice adds multiple values efficiently.

func (*BatchSortedSetBuilder[T]) Flush

func (b *BatchSortedSetBuilder[T]) Flush()

Flush commits buffered values to the sorted set.

func (*BatchSortedSetBuilder[T]) Len

func (b *BatchSortedSetBuilder[T]) Len() int

Len returns the total number of elements (committed + buffered).

func (*BatchSortedSetBuilder[T]) SortedSet

func (b *BatchSortedSetBuilder[T]) SortedSet() *SortedSet[T]

SortedSet returns the final sorted set.

type Comparer

type Comparer[K any] 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 K) int
}

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

func NewComparer

func NewComparer[K any](key K) Comparer[K]

NewComparer returns the built-in comparer for a given key type. Note that only int-ish and string-ish types are supported, despite the 'comparable' constraint. Attempts to use other types will result in a panic - users should define their own Comparers for these cases.

type Hasher

type Hasher[K any] interface {
	// Computes a hash for key.
	Hash(key K) uint32

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

Hasher hashes keys and checks them for equality.

func NewHasher

func NewHasher[K any](key K) Hasher[K]

NewHasher returns the built-in hasher for a given key type.

type List

type List[T any] struct {
	// contains filtered or unexported fields
}

List is a dense, ordered, indexed collections. They are analogous to slices in Go. A List is implemented as a relaxed-radix-balanced tree. The zero value of a List is an empty list. A list is safe for concurrent use. For smaller lists (under listSliceThreshold elements), it uses a slice internally for better performance, and will transparently switch to a trie for larger lists.

func NewList

func NewList[T any](values ...T) *List[T]

NewList returns a new empty instance of List.

func (*List[T]) Append

func (l *List[T]) Append(value T) *List[T]

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

Example
l := NewList[string]()
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[T]) Contains added in v0.6.0

func (l *List[T]) Contains(value T) bool

Contains returns true if the list contains the given value. For comparable element types, this uses ==. For non-comparable types, it falls back to reflect.DeepEqual. This method does not mutate the list and is safe for concurrent use across goroutines.

func (*List[T]) ContainsFunc added in v0.6.0

func (l *List[T]) ContainsFunc(value T, equal func(a, b T) bool) bool

ContainsFunc returns true if the list contains a value equal to the provided value using the caller-supplied equality function. The equality function should define equivalence for two values of type T and must be free of side effects. This method does not mutate the list and is safe for concurrent use across goroutines.

func (*List[T]) Get

func (l *List[T]) Get(index int) T

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[T]) Iterator

func (l *List[T]) Iterator() *ListIterator[T]

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

Example
l := NewList[string]()
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[string]()
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[T]) Len

func (l *List[T]) Len() int

Len returns the number of elements in the list.

func (*List[T]) Prepend

func (l *List[T]) Prepend(value T) *List[T]

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

Example
l := NewList[string]()
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[T]) Set

func (l *List[T]) Set(index int, value T) *List[T]

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[string]()
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[T]) Slice

func (l *List[T]) Slice(start, end int) *List[T]

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[string]()
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[T any] struct {
	// contains filtered or unexported fields
}

ListBuilder represents an efficient builder for creating new Lists.

func NewListBuilder

func NewListBuilder[T any]() *ListBuilder[T]

NewListBuilder returns a new instance of ListBuilder.

func (*ListBuilder[T]) Append

func (b *ListBuilder[T]) Append(value T)

Append adds value to the end of the list.

Example
b := NewListBuilder[string]()
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[T]) Contains added in v0.6.0

func (b *ListBuilder[T]) Contains(value T) bool

Contains returns true if the underlying list contains the given value.

func (*ListBuilder[T]) ContainsFunc added in v0.6.0

func (b *ListBuilder[T]) ContainsFunc(value T, equal func(a, b T) bool) bool

ContainsFunc returns true if the underlying list contains the given value using provided equality.

func (*ListBuilder[T]) Get

func (b *ListBuilder[T]) Get(index int) T

Get returns the value at the given index.

func (*ListBuilder[T]) Iterator

func (b *ListBuilder[T]) Iterator() *ListIterator[T]

Iterator returns a new iterator for the underlying list.

func (*ListBuilder[T]) Len

func (b *ListBuilder[T]) Len() int

Len returns the number of elements in the underlying list.

func (*ListBuilder[T]) List

func (b *ListBuilder[T]) List() *List[T]

List returns the current copy of the list. The builder should not be used again after the list after this call.

func (*ListBuilder[T]) Prepend

func (b *ListBuilder[T]) Prepend(value T)

Prepend adds value to the beginning of the list.

Example
b := NewListBuilder[string]()
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[T]) Set

func (b *ListBuilder[T]) Set(index int, value T)

Set updates the value at the given index.

Example
b := NewListBuilder[string]()
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[T]) Slice

func (b *ListBuilder[T]) Slice(start, end int)

Slice updates the list with a sublist of elements between start and end index.

Example
b := NewListBuilder[string]()
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[T any] struct {
	// contains filtered or unexported fields
}

ListIterator represents an ordered iterator over a list.

func (*ListIterator[T]) Done

func (itr *ListIterator[T]) Done() bool

func (*ListIterator[T]) First

func (itr *ListIterator[T]) First()

First positions the iterator on the first index.

func (*ListIterator[T]) Last

func (itr *ListIterator[T]) Last()

Last positions the iterator on the last index.

func (*ListIterator[T]) Next

func (itr *ListIterator[T]) Next() (index int, value T)

Next returns the current index and its value & moves the iterator forward.

func (*ListIterator[T]) Prev

func (itr *ListIterator[T]) Prev() (index int, value T)

Prev returns the current index and value and moves the iterator backward.

func (*ListIterator[T]) Seek

func (itr *ListIterator[T]) Seek(index int)

Seek moves the iterator position to the given index in the list.

type Map

type Map[K, V any] 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[K, V any](hasher Hasher[K]) *Map[K, V]

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 NewMapOf

func NewMapOf[K comparable, V any](hasher Hasher[K], entries map[K]V) *Map[K, V]

NewMapOf returns a new instance of Map, containing a map of provided entries.

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[K, V]) Delete

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

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[string, any](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[K, V]) Get

func (m *Map[K, V]) Get(key K) (value V, 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[K, V]) Iterator

func (m *Map[K, V]) Iterator() *MapIterator[K, V]

Iterator returns a new iterator for the map.

Example
m := NewMap[string, int](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[K, V]) Len

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

Len returns the number of elements in the map.

func (*Map[K, V]) Set

func (m *Map[K, V]) Set(key K, value V) *Map[K, V]

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[string, any](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[K, V any] struct {
	// contains filtered or unexported fields
}

MapBuilder represents an efficient builder for creating Maps.

func NewMapBuilder

func NewMapBuilder[K, V any](hasher Hasher[K]) *MapBuilder[K, V]

NewMapBuilder returns a new instance of MapBuilder.

func (*MapBuilder[K, V]) Delete

func (b *MapBuilder[K, V]) Delete(key K)

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

Example
b := NewMapBuilder[string, any](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[K, V]) Get

func (b *MapBuilder[K, V]) Get(key K) (value V, ok bool)

Get returns the value for the given key.

func (*MapBuilder[K, V]) Iterator

func (b *MapBuilder[K, V]) Iterator() *MapIterator[K, V]

Iterator returns a new iterator for the underlying map.

func (*MapBuilder[K, V]) Len

func (b *MapBuilder[K, V]) Len() int

Len returns the number of elements in the underlying map.

func (*MapBuilder[K, V]) Map

func (b *MapBuilder[K, V]) Map() *Map[K, V]

Map returns the underlying map. Only call once. Builder is invalid after call. Will panic on second invocation.

func (*MapBuilder[K, V]) Set

func (b *MapBuilder[K, V]) Set(key K, value V)

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

Example
b := NewMapBuilder[string, any](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[K, V any] 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[K, V]) Done

func (itr *MapIterator[K, V]) Done() bool

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

func (*MapIterator[K, V]) First

func (itr *MapIterator[K, V]) First()

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

func (*MapIterator[K, V]) Next

func (itr *MapIterator[K, V]) Next() (key K, value V, ok bool)

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

type Queue added in v0.6.0

type Queue[T any] struct {
	// contains filtered or unexported fields
}

Queue is an immutable FIFO queue implemented using the classic Okasaki two-list representation. Elements are dequeued from the front list and enqueued onto the back list. When the front becomes empty and the back is non-empty, the back is reversed and becomes the new front in O(n), preserving amortized O(1) enqueue/dequeue.

Queue is safe for concurrent read access across goroutines.

func NewQueue added in v0.6.0

func NewQueue[T any](values ...T) *Queue[T]

NewQueue returns a new queue containing the provided values in order. Values are placed on the front for optimal subsequent dequeues.

func NewQueueOf added in v0.6.0

func NewQueueOf[T any](values []T) *Queue[T]

NewQueueOf returns a new queue containing the provided slice of values in order.

func (*Queue[T]) Dequeue added in v0.6.0

func (q *Queue[T]) Dequeue() (next *Queue[T], value T, ok bool)

Dequeue returns a new queue with the first value removed and the value. If the queue is empty, ok is false and next is nil.

func (*Queue[T]) Empty added in v0.6.0

func (q *Queue[T]) Empty() bool

Empty returns true if the queue is empty.

func (*Queue[T]) Enqueue added in v0.6.0

func (q *Queue[T]) Enqueue(v T) *Queue[T]

Enqueue returns a new queue with v appended to the end.

func (*Queue[T]) Iterator added in v0.6.0

func (q *Queue[T]) Iterator() *QueueIterator[T]

Iterator returns a new iterator over the queue from front to back.

func (*Queue[T]) Len added in v0.6.0

func (q *Queue[T]) Len() int

Len returns the total number of elements in the queue.

func (*Queue[T]) Peek added in v0.6.0

func (q *Queue[T]) Peek() (value T, ok bool)

Peek returns the value at the front of the queue, if any. This operation does not modify the queue.

type QueueBuilder added in v0.6.0

type QueueBuilder[T any] struct {
	// contains filtered or unexported fields
}

batched enqueues. After calling Queue(), the builder becomes invalid.

func NewQueueBuilder added in v0.6.0

func NewQueueBuilder[T any]() *QueueBuilder[T]

NewQueueBuilder returns a new builder with an empty queue.

func (*QueueBuilder[T]) Enqueue added in v0.6.0

func (b *QueueBuilder[T]) Enqueue(v T)

Enqueue appends a single value to the end of the queue.

func (*QueueBuilder[T]) EnqueueSlice added in v0.6.0

func (b *QueueBuilder[T]) EnqueueSlice(values []T)

EnqueueSlice appends all values in order.

func (*QueueBuilder[T]) Len added in v0.6.0

func (b *QueueBuilder[T]) Len() int

Len returns the current number of elements in the underlying queue.

func (*QueueBuilder[T]) Queue added in v0.6.0

func (b *QueueBuilder[T]) Queue() *Queue[T]

Queue returns the built queue and invalidates the builder.

type QueueIterator added in v0.6.0

type QueueIterator[T any] struct {
	// contains filtered or unexported fields
}

QueueIterator iterates over a Queue from front to back. It first iterates the front list from index 0..n-1, then iterates the back list in reverse (since enqueue pushes onto the logical end).

func (*QueueIterator[T]) Done added in v0.6.0

func (itr *QueueIterator[T]) Done() bool

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

func (*QueueIterator[T]) First added in v0.6.0

func (itr *QueueIterator[T]) First()

First positions the iterator at the first element.

func (*QueueIterator[T]) Next added in v0.6.0

func (itr *QueueIterator[T]) Next() (index int, value T, ok bool)

Next returns the current index and value and moves the iterator forward. ok is false if iteration is complete.

type Set

type Set[T any] struct {
	// contains filtered or unexported fields
}

Set represents a collection of unique values. The set uses a Hasher to generate hashes and check for equality of key values.

Internally, the Set stores values as keys of a Map[T,struct{}]

func NewSet

func NewSet[T any](hasher Hasher[T], values ...T) Set[T]

NewSet returns a new instance of Set.

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. NewSet can also take some initial values as varargs.

func (Set[T]) Add

func (s Set[T]) Add(value T) Set[T]

Add returns a set containing the new value.

This function will return a new set even if the set already contains the value.

func (Set[T]) Delete

func (s Set[T]) Delete(value T) Set[T]

Delete returns a set with the given key removed.

func (Set[T]) Has

func (s Set[T]) Has(val T) bool

Has returns true when the set contains the given value

func (Set[T]) Items

func (s Set[T]) Items() []T

Items returns a slice of the items inside the set

func (Set[T]) Iterator

func (s Set[T]) Iterator() *SetIterator[T]

Iterator returns a new iterator for this set positioned at the first value.

func (Set[K]) Len

func (s Set[K]) Len() int

Len returns the number of elements in the underlying map.

type SetBuilder

type SetBuilder[T any] struct {
	// contains filtered or unexported fields
}

func NewSetBuilder

func NewSetBuilder[T any](hasher Hasher[T]) *SetBuilder[T]

func (SetBuilder[T]) Delete

func (s SetBuilder[T]) Delete(val T)

func (SetBuilder[T]) Has

func (s SetBuilder[T]) Has(val T) bool

func (SetBuilder[T]) Len

func (s SetBuilder[T]) Len() int

func (SetBuilder[T]) Set

func (s SetBuilder[T]) Set(val T)

type SetIterator

type SetIterator[T any] struct {
	// contains filtered or unexported fields
}

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

func (*SetIterator[T]) Done

func (itr *SetIterator[T]) Done() bool

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

func (*SetIterator[T]) First

func (itr *SetIterator[T]) First()

First moves the iterator to the first value.

func (*SetIterator[T]) Next

func (itr *SetIterator[T]) Next() (val T, ok bool)

Next moves the iterator to the next value.

type SortedBatchBuilder

type SortedBatchBuilder[K cmp.Ordered, V any] struct {
	// contains filtered or unexported fields
}

SortedBatchBuilder provides batch operations optimized for sorted data.

func NewSortedBatchBuilder

func NewSortedBatchBuilder[K cmp.Ordered, V any](comparer Comparer[K], batchSize int, maintainSort bool) *SortedBatchBuilder[K, V]

NewSortedBatchBuilder creates a batch builder for sorted maps. If maintainSort is true, entries are kept sorted in the buffer for optimal insertion.

func (*SortedBatchBuilder[K, V]) Flush

func (b *SortedBatchBuilder[K, V]) Flush()

Flush commits buffered entries to the sorted map.

func (*SortedBatchBuilder[K, V]) Set

func (b *SortedBatchBuilder[K, V]) Set(key K, value V)

Set adds a key/value pair, maintaining sort order if enabled.

func (*SortedBatchBuilder[K, V]) SortedMap

func (b *SortedBatchBuilder[K, V]) SortedMap() *SortedMap[K, V]

SortedMap returns the final sorted map.

type SortedMap

type SortedMap[K, V any] 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[K, V any](comparer Comparer[K]) *SortedMap[K, V]

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 NewSortedMapOf

func NewSortedMapOf[K comparable, V any](comparer Comparer[K], entries map[K]V) *SortedMap[K, V]

NewSortedMapOf returns a new instance of SortedMap, containing a map of provided entries.

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[K, V]) Delete

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

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

Example
m := NewSortedMap[string, any](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[K, V]) Get

func (m *SortedMap[K, V]) Get(key K) (V, 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[K, V]) Iterator

func (m *SortedMap[K, V]) Iterator() *SortedMapIterator[K, V]

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

Example
m := NewSortedMap[string, any](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[K, V]) Len

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

Len returns the number of elements in the sorted map.

func (*SortedMap[K, V]) Set

func (m *SortedMap[K, V]) Set(key K, value V) *SortedMap[K, V]

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

Example
m := NewSortedMap[string, any](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[K, V any] struct {
	// contains filtered or unexported fields
}

SortedMapBuilder represents an efficient builder for creating sorted maps.

func NewSortedMapBuilder

func NewSortedMapBuilder[K, V any](comparer Comparer[K]) *SortedMapBuilder[K, V]

NewSortedMapBuilder returns a new instance of SortedMapBuilder.

func (*SortedMapBuilder[K, V]) Delete

func (b *SortedMapBuilder[K, V]) Delete(key K)

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

Example
b := NewSortedMapBuilder[string, any](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[K, V]) Get

func (b *SortedMapBuilder[K, V]) Get(key K) (value V, ok bool)

Get returns the value for the given key.

func (*SortedMapBuilder[K, V]) Iterator

func (b *SortedMapBuilder[K, V]) Iterator() *SortedMapIterator[K, V]

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

func (*SortedMapBuilder[K, V]) Len

func (b *SortedMapBuilder[K, V]) Len() int

Len returns the number of elements in the underlying map.

func (*SortedMapBuilder[K, V]) Map

func (b *SortedMapBuilder[K, V]) Map() *SortedMap[K, V]

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[K, V]) Set

func (b *SortedMapBuilder[K, V]) Set(key K, value V)

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

Example
b := NewSortedMapBuilder[string, any](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[K, V any] 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[K, V]) Done

func (itr *SortedMapIterator[K, V]) Done() bool

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

func (*SortedMapIterator[K, V]) First

func (itr *SortedMapIterator[K, V]) First()

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

func (*SortedMapIterator[K, V]) Last

func (itr *SortedMapIterator[K, V]) Last()

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

func (*SortedMapIterator[K, V]) Next

func (itr *SortedMapIterator[K, V]) Next() (key K, value V, ok bool)

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[K, V]) Prev

func (itr *SortedMapIterator[K, V]) Prev() (key K, value V, ok bool)

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[K, V]) Seek

func (itr *SortedMapIterator[K, V]) Seek(key K)

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.

type SortedSet

type SortedSet[T any] struct {
	// contains filtered or unexported fields
}

func NewSortedSet

func NewSortedSet[T any](comparer Comparer[T], values ...T) SortedSet[T]

NewSortedSet returns a new instance of SortedSet.

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. NewSortedSet can also take some initial values as varargs.

func (SortedSet[T]) Add

func (s SortedSet[T]) Add(value T) SortedSet[T]

Add returns a set containing the new value.

This function will return a new set even if the set already contains the value.

func (SortedSet[T]) Delete

func (s SortedSet[T]) Delete(value T) SortedSet[T]

Delete returns a set with the given key removed.

func (SortedSet[T]) Has

func (s SortedSet[T]) Has(val T) bool

Has returns true when the set contains the given value

func (SortedSet[T]) Items

func (s SortedSet[T]) Items() []T

Items returns a slice of the items inside the set

func (SortedSet[T]) Iterator

func (s SortedSet[T]) Iterator() *SortedSetIterator[T]

Iterator returns a new iterator for this set positioned at the first value.

func (SortedSet[K]) Len

func (s SortedSet[K]) Len() int

Len returns the number of elements in the underlying map.

type SortedSetBuilder

type SortedSetBuilder[T any] struct {
	// contains filtered or unexported fields
}

func NewSortedSetBuilder

func NewSortedSetBuilder[T any](comparer Comparer[T]) *SortedSetBuilder[T]

func (SortedSetBuilder[T]) Delete

func (s SortedSetBuilder[T]) Delete(val T)

func (SortedSetBuilder[T]) Has

func (s SortedSetBuilder[T]) Has(val T) bool

func (SortedSetBuilder[T]) Len

func (s SortedSetBuilder[T]) Len() int

func (SortedSetBuilder[T]) Set

func (s SortedSetBuilder[T]) Set(val T)

func (SortedSetBuilder[T]) SortedSet

func (s SortedSetBuilder[T]) SortedSet() SortedSet[T]

SortedSet returns the current copy of the set. The builder should not be used again after the list after this call.

type SortedSetIterator

type SortedSetIterator[T any] struct {
	// contains filtered or unexported fields
}

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

func (*SortedSetIterator[T]) Done

func (itr *SortedSetIterator[T]) Done() bool

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

func (*SortedSetIterator[T]) First

func (itr *SortedSetIterator[T]) First()

First moves the iterator to the first value.

func (*SortedSetIterator[T]) Last

func (itr *SortedSetIterator[T]) Last()

Last moves the iterator to the last value.

func (*SortedSetIterator[T]) Next

func (itr *SortedSetIterator[T]) Next() (val T, ok bool)

Next moves the iterator to the next value.

func (*SortedSetIterator[T]) Prev

func (itr *SortedSetIterator[T]) Prev() (val T, ok bool)

Prev moves the iterator to the previous value.

func (*SortedSetIterator[T]) Seek

func (itr *SortedSetIterator[T]) Seek(val T)

Seek moves the iterator to the given value.

If the value does not exist then the next value is used. If no more keys exist then the iterator is marked as done.

type StreamingListBuilder

type StreamingListBuilder[T any] struct {
	*BatchListBuilder[T]
	// contains filtered or unexported fields
}

StreamingListBuilder provides streaming operations with configurable flush triggers.

func NewStreamingListBuilder

func NewStreamingListBuilder[T any](batchSize, autoFlushSize int) *StreamingListBuilder[T]

NewStreamingListBuilder creates a builder with automatic flush capabilities.

func (*StreamingListBuilder[T]) Filter

func (b *StreamingListBuilder[T]) Filter(values []T, filterFn func(T) bool)

Filter processes values through a filter function before adding.

func (*StreamingListBuilder[T]) Stream

func (b *StreamingListBuilder[T]) Stream(values <-chan T)

Stream processes values through a streaming pipeline. Automatically flushes when size thresholds are reached.

func (*StreamingListBuilder[T]) Transform

func (b *StreamingListBuilder[T]) Transform(values []T, transformFn func(T) T)

Transform processes values through a transformation function.

type StreamingMapBuilder

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

StreamingMapBuilder provides streaming operations with configurable flush triggers for Maps.

func NewStreamingMapBuilder

func NewStreamingMapBuilder[K comparable, V any](hasher Hasher[K], batchSize, autoFlushSize int) *StreamingMapBuilder[K, V]

NewStreamingMapBuilder creates a map builder with automatic flush capabilities.

func (*StreamingMapBuilder[K, V]) Filter

func (b *StreamingMapBuilder[K, V]) Filter(entries []mapEntry[K, V], filterFn func(K, V) bool)

Filter processes entries through a filter function before adding.

func (*StreamingMapBuilder[K, V]) SetMany

func (b *StreamingMapBuilder[K, V]) SetMany(entries map[K]V)

SetMany adds multiple key/value pairs efficiently from a map.

func (*StreamingMapBuilder[K, V]) Stream

func (b *StreamingMapBuilder[K, V]) Stream(entries <-chan mapEntry[K, V])

Stream processes key/value pairs through a streaming pipeline.

func (*StreamingMapBuilder[K, V]) Transform

func (b *StreamingMapBuilder[K, V]) Transform(entries []mapEntry[K, V], transformFn func(K, V) (K, V))

Transform processes entries through a transformation function.

Jump to

Keyboard shortcuts

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