High-performance, zero-GC, off-heap associative trie collections for Java and Scala powered by Project Panama Foreign Function & Memory (FFM) API (java.lang.foreign) and libexpanse.
- Zero JVM Heap & Zero GC Overhead: Collections store keys and nodes completely off-heap in native 64-byte cache lines. Zero GC pause impact even with hundreds of millions of keys.
-
Project Panama FFM (Java 22+ / 21 LTS): Uses native
java.lang.foreigndowncalls directly intolibexpanse, eliminating JNI transition penalties. -
Direct Value Slots: Directly read and write off-heap 64-bit value slots via
MemorySegmentwith zero tree re-traversals. -
Rich Collection Set:
-
ExpanseSet: High-performance ordered 64-bit set (cf. Judy1) with$O(\text{depth})$ rank & select. -
ExpanseMap: High-performance ordered 64-bit$\to$ 64-bit map (cf. JudyL). -
ExpanseStrMap: High-performance ordered String$\to$ 64-bit map (cf. JudySL). -
ExpanseBytesMap: High-performance unordered byte slice$\to$ 64-bit map (cf. JudyHS). -
SyncExpanseMap/SyncExpanseSet: Multithreaded OCC concurrent collections with optimistic readers.
-
-
Standard Java Collection Wrappers: Standard
java.util.NavigableMap<Long, Long>,java.util.NavigableSet<Long>, andjava.util.Map<String, Long>interfaces. - Big Data Ready: Designed for Apache Spark, Apache Flink, Kafka Streams, and high-frequency trading where GC pauses are unacceptable.
Not yet on Maven Central. No
io.github.oriegartifact is published yet; the version badge above renders "not found" until first publish. Build frombindings/javalocally until then. The coordinates below are the planned ones.
<dependency>
<groupId>io.github.orieg</groupId>
<artifactId>expanse-java</artifactId>
<version>0.4.0</version>
</dependency>implementation 'io.github.orieg:expanse-java:0.4.0'libraryDependencies += "io.github.orieg" % "expanse-java" % "0.4.0"import io.github.orieg.expanse.ExpanseMap;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
try (ExpanseMap map = new ExpanseMap()) {
// Fast inserts and lookups
map.put(100L, 5000L);
map.put(200L, 8000L);
long val = map.getOrDefault(100L, -1L);
System.out.println("Key 100: " + val);
// Direct off-heap value slot mutation (zero traversal overhead)
MemorySegment slot = map.insertSlot(300L);
slot.set(ValueLayout.JAVA_LONG, 0, 9999L);
System.out.println("Key 300: " + map.get(300L).getAsLong());
// O(depth) rank and range queries
long countBelow = map.countBelow(200L); // 1 key (< 200)
long countRange = map.countRange(100L, 300L); // 3 keys
// Ordered navigation
map.ceilingEntry(150L).ifPresent(e ->
System.out.println("Ceiling >= 150: " + e.key() + " -> " + e.value())
);
// Exact off-heap memory accounting
System.out.printf("Native memory used: %d bytes%n", map.memoryUsed());
}import io.github.orieg.expanse.ExpanseSet;
try (ExpanseSet set = new ExpanseSet()) {
set.add(10L);
set.add(20L);
set.add(30L);
if (set.contains(20L)) {
System.out.println("Set contains 20");
}
// 0-based rank select
set.byCount(1).ifPresent(key -> System.out.println("2nd smallest key: " + key));
// Primitive zero-allocation streaming
long sum = set.stream().sum();
}import io.github.orieg.expanse.SyncExpanseMap;
try (SyncExpanseMap map = new SyncExpanseMap()) {
// Writer thread
map.put(42L, 1000L);
// Reader thread (optimistic, zero writer contention)
try (SyncExpanseMap.Reader reader = map.reader()) {
reader.get(42L).ifPresent(v -> System.out.println("Read value: " + v));
}
}NativeLoader automatically extracts and loads the precompiled native library bundled inside the JAR for:
- Linux (
x86_64,aarch64) - macOS (
aarch64Apple Silicon,x86_64Intel) - Windows (
x86_64)
To supply an external custom build of libexpanse, specify -Dexpanse.library.path=/path/to/libexpanse.so or the EXPANSE_LIBRARY_PATH environment variable.
See docs/bindings/java.md for full architectural deep dive, Spark/Flink integration patterns, and GC benchmarking.