> ## Documentation Index
> Fetch the complete documentation index at: https://osinet.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# OrderedMap

> A map that preserves insertion order with stable and recency-based modes.

`OrderedMap` is a generic key-value map that guarantees iteration order. Unlike Go's built-in `map`, which randomizes iteration, `OrderedMap` lets you control whether order is stable (insertion order, even after updates) or recency-based (most recently written key comes last — useful for LRU caches).

## Installation

```go theme={null}
import "github.com/fgm/container/orderedmap"
```

## Constructor

```go theme={null}
func NewSlice[K comparable, V any](sizeHint int, stable bool) *Slice[K, V]
```

<ParamField path="sizeHint" type="int" required>
  A hint for the initial capacity of the internal slice and map. Use `0` if you
  have no estimate. This does not limit the maximum size.
</ParamField>

<ParamField path="stable" type="bool" required>
  Controls what happens when you `Store` a key that already exists.

  * `true` — **stable mode**: the key keeps its original insertion position in the order. Useful when you care about when a key first appeared.
  * `false` — **recency mode**: the key is moved to the end of the order on every write. Useful for LRU caches where the most recently touched entry should appear last.
</ParamField>

## Methods

| Method   | Signature                            | Description                                                                                           |
| -------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `Store`  | `Store(key K, value V)`              | Inserts or updates a key-value pair. In recency mode, updates an existing key's position to the end.  |
| `Load`   | `Load(key K) (value V, loaded bool)` | Returns the value for a key. `loaded` is `false` if the key is absent.                                |
| `Delete` | `Delete(key K)`                      | Removes a key and its value. No-op if the key is absent.                                              |
| `Range`  | `Range(func(key K, value V) bool)`   | Iterates over all entries in insertion/recency order. Return `false` from the callback to stop early. |
| `Len`    | `Len() int`                          | Returns the number of entries currently in the map.                                                   |

<Warning>
  `Range` may panic if the callback deletes map entries during iteration. Avoid
  modifying the map inside the callback.
</Warning>

## Stable vs. recency mode

<Tabs>
  <Tab title="stable=true (insertion order)">
    The key's position is fixed at the time of first insertion. Subsequent
    `Store` calls for the same key update the value but leave the order
    unchanged.

    ```go theme={null}
    om := orderedmap.NewSlice[string, int](4, true)
    om.Store("a", 1)
    om.Store("b", 2)
    om.Store("c", 3)
    om.Store("a", 99) // updates value; "a" stays first

    om.Range(func(k string, v int) bool {
        fmt.Println(k, v)
        return true
    })
    // Output:
    // a 99
    // b 2
    // c 3
    ```
  </Tab>

  <Tab title="stable=false (recency order)">
    Every `Store` on an existing key moves it to the end of the order. This
    makes it straightforward to build an LRU cache: the front of the iteration
    order is the least recently used entry.

    ```go theme={null}
    om := orderedmap.NewSlice[string, int](4, false)
    om.Store("a", 1)
    om.Store("b", 2)
    om.Store("c", 3)
    om.Store("a", 99) // "a" moves to the end

    om.Range(func(k string, v int) bool {
        fmt.Println(k, v)
        return true
    })
    // Output:
    // b 2
    // c 3
    // a 99
    ```
  </Tab>
</Tabs>

## Example

The following example inserts eight entries, deletes one, updates another, then
iterates over the result in order.

```go theme={null}
package main

import (
    "fmt"
    "strconv"

    "github.com/fgm/container/orderedmap"
)

func main() {
    const size = 8
    om := orderedmap.NewSlice[string, int](size, true)

    for i := 1; i <= size; i++ {
        om.Store(strconv.Itoa(i), i)
    }

    om.Delete("5")      // remove key "5"
    om.Store("1", 11)   // update key "1"; stable mode keeps it first

    fmt.Printf("Len: %d\n", om.Len())

    om.Range(func(k string, v int) bool {
        fmt.Printf("%s -> %d\n", k, v)
        return true
    })
}
// Output:
// Len: 7
// 1 -> 11
// 2 -> 2
// 3 -> 3
// 4 -> 4
// 6 -> 6
// 7 -> 7
// 8 -> 8
```

## Checking for a key before acting

`Load` returns a boolean so you can distinguish a missing key from a key that
maps to the zero value:

```go theme={null}
if v, ok := om.Load("mykey"); ok {
    fmt.Println("found:", v)
} else {
    fmt.Println("not present")
}
```

<Note>
  `OrderedMap` is not concurrency-safe. If multiple goroutines need to read or
  write the same map concurrently, add external synchronization (for example, a
  `sync.RWMutex`).
</Note>
