Bounded collections
Latest stable Based on Bluetape4k release 1.11.0
BoundedStack and RingBuffer both evict the oldest value to bound memory, but expose opposite read order.
Choose by read semantics
Section titled “Choose by read semantics”| Requirement | Type | Index zero | Iteration |
|---|---|---|---|
| newest-first undo/history | BoundedStack | newest/top | newest to oldest |
| chronological recent history | RingBuffer | oldest/read head | oldest to newest |
Both validate a positive capacity and protect public reads/writes with ReentrantLock.
val stack = BoundedStack<Int>(3).apply { pushAll(1, 2, 3, 4) }val ring = RingBuffer<Int>(3).apply { addAll(1, 2, 3, 4) }
check(stack.toList() == listOf(4, 3, 2))check(ring.toList() == listOf(2, 3, 4))Both evict 1. BoundedStack.pop() removes 4 first; RingBuffer.drop(1) removes 2 first.
API semantics
Section titled “API semantics”BoundedStack offers push, pop, peek, insert, update, and remove with top-relative indexes. Empty pop/peek throws NoSuchElementException; invalid indexes throw IndexOutOfBoundsException.
RingBuffer offers add, indexed get/set, drop, removeIf, and clear with chronological indexes. Negative drop is invalid; dropping at least the current size clears the buffer.
What bounded collections are not
Section titled “What bounded collections are not”Bounded memory is not backpressure. Overflow silently replaces old data, so use a channel, queue, or persistent log when every item must be delivered. These types also do not provide blocking producer/consumer coordination.
Operations and testing
Section titled “Operations and testing”Observe eviction count, capacity saturation, and snapshot size. Test wrap-around indexing/iteration, concurrent access, invalid capacity, empty operations, and insert/remove boundaries.
Source and representative tests
Section titled “Source and representative tests”Capacity for running and waiting asynchronous work belongs in Concurrency and lifecycle.