Index Types
The GigaMap’s bitmap index supports various index types.
"Normal" Index
This is just a standard index that can include duplicate values. In fact, this is the most efficient type, as the bitmap index can compress this dataset and minimize memory overhead.
// use the builder
final GigaMap<Person> gigaMap = GigaMap.<Person>Builder()
.withBitmapIndex(PersonIndices.firstName)
.withBitmapIndex(PersonIndices.lastName)
...
.build();
// or register it after creating
GigaMap<Person> gigaMap = GigaMap.New();
gigaMap.index().bitmap().ensure(PersonIndices.firstName);
gigaMap.index().bitmap().ensure(PersonIndices.lastName);
...
Unique Index
Index with a unique constraint.
// use the builder
final GigaMap<Person> gigaMap = GigaMap.<Person>Builder()
.withBitmapUniqueIndex(PersonIndices.id)
...
.build();
// or register it after creating
GigaMap<Person> gigaMap = GigaMap.New();
gigaMap.index().bitmap().addUniqueConstraint(PersonIndices.id);
...
Identity Index
An identity index is used exclusively to identify an entity within the GigaMap. It can consist of one or more indexers.
When looking up or removing entities, the GigaMap doesn’t traverse all data, as that would be too inefficient. Instead, it creates an internal query based on the identity index definitions to look up entries. If no identity index is provided, a compound one will be created using all standard indices.
| An identity index is not a unique index. It only defines which fields are used to identify entities — it does not enforce uniqueness. If you need to ensure that no two entities share the same identity value, you must add a unique constraint separately. |
// use the builder
final GigaMap<Person> gigaMap = GigaMap.<Person>Builder()
.withBitmapIdentityIndex(PersonIndices.id)
...
.build();
// identity index with unique constraint
final GigaMap<Person> gigaMap = GigaMap.<Person>Builder()
.withBitmapIdentityIndex(PersonIndices.id)
.withBitmapUniqueIndex(PersonIndices.id) // enforce uniqueness at runtime
...
.build();
// or register it after creating
GigaMap<Person> gigaMap = GigaMap.New();
final BitmapIndices<E> bitmap = this.gigaMap.index().bitmap();
bitmap.ensure(PersonIndices.id); // add index first
bitmap.setIdentityIndices(PersonIndices.id); // set as identity
bitmap.addUniqueConstraint(PersonIndices.id); // enforce uniqueness
...
Binary Index
A special bitmap index designed for high cardinality.
This index exclusively stores long values.
Each long-bit corresponds to an entry, meaning there will be 64 entries max, no matter how high the cardinality becomes.
Currently it only supports equality queries. Range queries are not supported yet.
Zero and Negative Values
All binary indexers support zero and negative values.
Internally, each indexer maps the key to a non-zero long representation because the bitmap index uses bit positions as array indices, and a value of 0L would have no bits set.
For sub-64-bit types (Byte, Short, Integer, Float), this mapping is collision-free — no two distinct keys ever map to the same internal representation.
BinaryIndexerLong uses Long.MAX_VALUE as the internal representation for zero.
As a consequence, Long.MAX_VALUE is not supported as an index key and will throw an IllegalArgumentException.
All other long values are fully supported.
Byte Index
A composite bitmap index designed for high cardinality numeric types with range query support.
It decomposes numbers into individual bytes (base 256) and stores each byte position as a separate sub-index with at most 256 entries. This uses the same composite index infrastructure as IndexerLocalDate (which decomposes into year/month/day).
Byte indexers support both equality and range queries: is, not, in, notIn, lessThan, lessThanEqual, greaterThan, greaterThanEqual, and between.
// use the builder
final GigaMap<Product> gigaMap = GigaMap.<Product>Builder()
.withBitmapIdentityIndex(ProductIndices.price)
.build();
// query with range conditions
gigaMap.query(ProductIndices.price.between(10, 100));
gigaMap.query(ProductIndices.price.greaterThan(50));
Use byte indexers when you need range queries on numeric types with high cardinality. Use binary indexers when you only need equality queries.
Choosing Between Regular, Binary, and Byte Indexers
The bitmap index offers three families of indexers: regular indexers (e.g. IndexerString, IndexerLong), binary indexers (e.g. BinaryIndexerString, BinaryIndexerLong), and byte indexers (e.g. ByteIndexerInt, ByteIndexerLong). The right choice depends on your data characteristics and query needs.
Comparison
| Aspect | Regular Indexer | Binary Indexer | Byte Indexer |
|---|---|---|---|
Cardinality |
Low to medium (few distinct values, many entities per value) |
High (many distinct values, few entities per value) |
High (many distinct values, few entities per value) |
Query types |
Equality ( |
Equality only ( |
Equality ( |
Key type |
Any object with |
Must convert to |
Numeric types and |
Memory |
On-heap hash table |
Off-heap bit-position array |
Composite sub-indices with at most 256 entries per byte position |
Null values |
Native support |
Requires sentinel value handling |
Requires sentinel value handling |
Use Regular Indexer When
-
Indexed values have low cardinality — few distinct values shared by many entities (enums, categories, status fields)
-
You need predicate-based queries, e.g.
firstName.is(name → name.startsWith("J")) -
You need range queries via
IndexerComparing -
The key type does not naturally map to
long
Typical use cases: enumerations, boolean flags, date/time fields, categories, multi-value fields
Use Binary Indexer When
-
Indexed values have high cardinality — many distinct values (unique IDs, foreign keys)
-
Only equality queries are needed (
is,in) -
The key can be efficiently converted to
long(numeric IDs, TSID, UUID) -
Memory efficiency matters for large datasets
Typical use cases: primary/foreign key indices, UUIDs, TSIDs, unique codes or reference numbers
Use Byte Indexer When
-
Indexed values have high cardinality — many distinct values
-
You need range queries (
lessThan,greaterThan,between, etc.) on high-cardinality data -
The key is a numeric type or
Instant -
You want the benefits of bitmap indexing for high-cardinality fields without sacrificing range query support
Typical use cases: prices, quantities, timestamps (as Instant), scores, measurements, or any numeric field that requires both high-cardinality support and range filtering