Collections: Lists (List, LinearList)
Bifurcan provides two primary list implementations that share a common IList interface: the immutable List and the mutable LinearList.
List (Immutable)
The immutable List is an implementation of a Relaxed Radix Balanced Tree (RRB-Tree). This advanced structure gives it powerful performance characteristics:
- Efficient modifications at both ends:
addFirst,addLast,removeFirst, andremoveLastare highly optimized. - Fast random access and updates:
nth(idx)andset(idx, val)are efficient. - Near constant-time slicing and concatenation: Operations like
slice()andconcat()are exceptionally fast, makingListideal for workflows that involve splitting and joining lists.
import io.lacuna.bifurcan.List;
// Create a list
List<String> list1 = List.of("a", "b", "c");
// Add an element
List<String> list2 = list1.addLast("d"); // list1 is unchanged
// Concatenate
List<String> list3 = list2.concat(List.of("e", "f")); // [a, b, c, d, e, f]
// Slice
List<String> slice = list3.slice(1, 4); // [b, c, d]
LinearList (Mutable)
LinearList is a mutable list that combines the benefits of java.util.ArrayList and java.util.ArrayDeque. It is backed by a circular buffer, providing:
- Constant-time additions and removals from both the front and back.
- Constant-time random-access reads and writes.
It is ideal for scenarios where you need to build up a list inside a single thread of execution before potentially converting it to an immutable List using forked().
import io.lacuna.bifurcan.LinearList;
// Create a mutable list
LinearList<Integer> list = new LinearList<>();
// Efficiently build the list
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
list.addLast(i);
} else {
list.addFirst(i);
}
}