Collections: Hash Sets (Set, LinearSet)

Bifurcan's Set and LinearSet are built directly on top of their Map and LinearMap counterparts, respectively. They store elements as keys in the underlying map with a placeholder value. As a result, they inherit the same performance characteristics and features.

Set (Immutable)

The immutable Set is a CHAMP-based hash set that provides:

  • Customizable Equality: You can define custom hash and equality logic for the set's elements.
  • Canonical Structure: Like Map, equivalent Set instances have an identical memory layout, leading to very fast set operations (union, difference, intersection).
  • High Performance: Efficient additions, removals, and lookups.
import io.lacuna.bifurcan.Set;

Set<String> s1 = Set.of("a", "b", "c");
Set<String> s2 = Set.of("c", "d", "e");

// Union
Set<String> union = s1.union(s2); // {a, b, c, d, e}

// Intersection
Set<String> intersection = s1.intersection(s2); // {c}

// Difference
Set<String> difference = s1.difference(s2); // {a, b}

LinearSet (Mutable)

LinearSet is the mutable counterpart, built on LinearMap. It offers:

  • Fast Iteration: Due to the contiguous memory layout of the underlying LinearMap.
  • Efficient Batch Operations: Ideal for building up a large set of elements within a single thread.
  • Customizable Equality: Supports custom hash and equality semantics.

LinearSet is perfect for scenarios where you need to perform many additions or removals before the set is used in an immutable context.

import io.lacuna.bifurcan.LinearSet;

LinearSet<Integer> set = new LinearSet<>();

// Efficiently build the set
for (int i = 0; i < 1000; i++) {
    set.add(i);
}

// You can convert it to an immutable Set when done
Set<Integer> immutableSet = Set.from(set);