This is an automated email from the ASF dual-hosted git repository. bchapuis pushed a commit to branch data-refactoring in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit 5486ed1417305f2ca3ea3dfff6e6ec9999a83490 Author: Bertil Chapuis <[email protected]> AuthorDate: Sat Apr 5 11:26:52 2025 +0200 Add builders to data collections --- .../data/collection/DirectHashDataMap.java | 194 ++++++++++++++++----- .../data/collection/FixedSizeDataList.java | 60 +++++++ .../baremaps/data/collection/IndexedDataList.java | 60 +++++++ .../baremaps/data/collection/IndexedDataMap.java | 60 +++++++ .../data/collection/MemoryAlignedDataList.java | 60 +++++++ .../data/collection/MemoryAlignedDataMap.java | 59 +++++++ .../baremaps/data/collection/MonotonicDataMap.java | 78 +++++++++ .../data/collection/MonotonicFixedSizeDataMap.java | 78 +++++++++ .../data/collection/MonotonicPairedDataMap.java | 60 +++++++ .../java/org/apache/baremaps/data/DataMapTest.java | 3 +- 10 files changed, 668 insertions(+), 44 deletions(-) diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/DirectHashDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/DirectHashDataMap.java index 12af89d8b..b36005c34 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/DirectHashDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/DirectHashDataMap.java @@ -1,9 +1,12 @@ /* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,11 +27,12 @@ import org.apache.baremaps.data.memory.Memory; import org.apache.baremaps.data.type.FixedSizeDataType; /** - * A {@link DataMap} that uses direct hashing with open addressing and linear probing. - * This implementation provides O(1) access time for both get and put operations - * and doesn't have any insertion order dependencies. + * A {@link DataMap} that uses direct hashing with open addressing and linear probing. This + * implementation provides O(1) access time for both get and put operations and doesn't have any + * insertion order dependencies. * - * <p>The map size is fixed at instantiation time and cannot be resized afterward. + * <p> + * The map size is fixed at instantiation time and cannot be resized afterward. * * @param <V> the type of the values */ @@ -36,18 +40,122 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { private static final long EMPTY_KEY = Long.MIN_VALUE; private static final long TOMBSTONE = Long.MIN_VALUE + 1; - + private final FixedSizeDataType<V> dataType; private final FixedSizeDataType<Long> keyType; private final Memory<?> keyMemory; private final Memory<?> valueMemory; - + private final long capacity; private final int valueSize; private final int keySize; - + private long size; + /** + * Static factory method to create a new builder. + * + * @param <V> the type of values + * @return a new builder + */ + public static <V> Builder<V> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link DirectHashDataMap}. + * + * @param <V> the type of values + */ + public static class Builder<V> { + private FixedSizeDataType<Long> keyType; + private FixedSizeDataType<V> dataType; + private Memory<?> keyMemory; + private Memory<?> valueMemory; + private long capacity; + + /** + * Sets the key type for the map. + * + * @param keyType the data type for keys + * @return this builder + */ + public Builder<V> keyType(FixedSizeDataType<Long> keyType) { + this.keyType = keyType; + return this; + } + + /** + * Sets the data type for the map. + * + * @param dataType the data type for values + * @return this builder + */ + public Builder<V> dataType(FixedSizeDataType<V> dataType) { + this.dataType = dataType; + return this; + } + + /** + * Sets the key memory for the map. + * + * @param keyMemory the memory for keys + * @return this builder + */ + public Builder<V> keyMemory(Memory<?> keyMemory) { + this.keyMemory = keyMemory; + return this; + } + + /** + * Sets the value memory for the map. + * + * @param valueMemory the memory for values + * @return this builder + */ + public Builder<V> valueMemory(Memory<?> valueMemory) { + this.valueMemory = valueMemory; + return this; + } + + /** + * Sets the capacity for the map. + * + * @param capacity the fixed capacity of the map + * @return this builder + */ + public Builder<V> capacity(long capacity) { + this.capacity = capacity; + return this; + } + + /** + * Builds a new {@link DirectHashDataMap}. + * + * @return a new DirectHashDataMap + * @throws IllegalStateException if any required parameter is missing + */ + public DirectHashDataMap<V> build() { + if (keyType == null) { + throw new IllegalStateException("Key type must be specified"); + } + if (dataType == null) { + throw new IllegalStateException("Data type must be specified"); + } + if (keyMemory == null) { + throw new IllegalStateException("Key memory must be specified"); + } + if (valueMemory == null) { + throw new IllegalStateException("Value memory must be specified"); + } + if (capacity <= 0) { + throw new IllegalStateException("Capacity must be greater than zero"); + } + + return new DirectHashDataMap<>(keyType, dataType, keyMemory, valueMemory, capacity); + } + } + /** * Constructs a {@link DirectHashDataMap} with the specified capacity. * @@ -59,7 +167,7 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { */ public DirectHashDataMap( FixedSizeDataType<Long> keyType, - FixedSizeDataType<V> dataType, + FixedSizeDataType<V> dataType, Memory<?> keyMemory, Memory<?> valueMemory, long capacity) { @@ -71,7 +179,7 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { this.keySize = keyType.size(); this.valueSize = dataType.size(); this.size = 0; - + // Initialize all keys to EMPTY_KEY for (long i = 0; i < capacity; i++) { storeKey(i, EMPTY_KEY); @@ -101,12 +209,12 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { private long findSlot(long key, boolean forInsertion) { long index = hash(key); long tombstoneSlot = -1; - + // Linear probing to handle collisions for (long i = 0; i < capacity; i++) { long currentIndex = (index + i) % capacity; long currentKey = readKey(currentIndex); - + if (currentKey == EMPTY_KEY) { // Found empty slot return forInsertion ? (tombstoneSlot != -1 ? tombstoneSlot : currentIndex) : -1; @@ -120,12 +228,12 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { return currentIndex; } } - + // If we're inserting and found a tombstone earlier, use that if (forInsertion && tombstoneSlot != -1) { return tombstoneSlot; } - + // Map is full or key not found return -1; } @@ -179,19 +287,19 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { public V put(Long key, V value) { Objects.requireNonNull(key, "Key cannot be null"); Objects.requireNonNull(value, "Value cannot be null"); - + if (key == EMPTY_KEY || key == TOMBSTONE) { throw new IllegalArgumentException("Reserved key value: " + key); } - + long slot = findSlot(key, true); if (slot == -1) { throw new IllegalStateException("Map is full"); } - + long existingKey = readKey(slot); V previousValue = null; - + if (existingKey != EMPTY_KEY && existingKey != TOMBSTONE) { // Slot contains an existing key previousValue = readValue(slot); @@ -199,10 +307,10 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { // New entry size++; } - + storeKey(slot, key); storeValue(slot, value); - + return previousValue; } @@ -212,16 +320,16 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { if (!(keyObj instanceof Long key)) { return null; } - + if (key == EMPTY_KEY || key == TOMBSTONE) { return null; } - + long slot = findSlot(key, false); if (slot == -1) { return null; } - + return readValue(slot); } @@ -231,11 +339,11 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { if (!(keyObj instanceof Long key)) { return false; } - + if (key == EMPTY_KEY || key == TOMBSTONE) { return false; } - + return findSlot(key, false) != -1; } @@ -245,14 +353,14 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { if (value == null) { return false; } - + Iterator<V> iterator = valueIterator(); while (iterator.hasNext()) { if (value.equals(iterator.next())) { return true; } } - + return false; } @@ -277,18 +385,18 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { return new Iterator<>() { private long currentIndex = 0; private long returnedCount = 0; - + @Override public boolean hasNext() { return returnedCount < size; } - + @Override public Long next() { if (!hasNext()) { throw new NoSuchElementException(); } - + while (currentIndex < capacity) { long key = readKey(currentIndex++); if (key != EMPTY_KEY && key != TOMBSTONE) { @@ -296,7 +404,7 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { return key; } } - + throw new NoSuchElementException(); } }; @@ -308,18 +416,18 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { return new Iterator<>() { private long currentIndex = 0; private long returnedCount = 0; - + @Override public boolean hasNext() { return returnedCount < size; } - + @Override public V next() { if (!hasNext()) { throw new NoSuchElementException(); } - + while (currentIndex < capacity) { long key = readKey(currentIndex); if (key != EMPTY_KEY && key != TOMBSTONE) { @@ -328,7 +436,7 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { } currentIndex++; } - + throw new NoSuchElementException(); } }; @@ -340,18 +448,18 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { return new Iterator<>() { private long currentIndex = 0; private long returnedCount = 0; - + @Override public boolean hasNext() { return returnedCount < size; } - + @Override public Entry<Long, V> next() { if (!hasNext()) { throw new NoSuchElementException(); } - + while (currentIndex < capacity) { long key = readKey(currentIndex); if (key != EMPTY_KEY && key != TOMBSTONE) { @@ -362,7 +470,7 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { } currentIndex++; } - + throw new NoSuchElementException(); } }; @@ -377,4 +485,4 @@ public class DirectHashDataMap<V> implements DataMap<Long, V> { throw new DataCollectionException(e); } } -} \ No newline at end of file +} diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/FixedSizeDataList.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/FixedSizeDataList.java index 88bcaf1ee..0750b7569 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/FixedSizeDataList.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/FixedSizeDataList.java @@ -39,6 +39,66 @@ public class FixedSizeDataList<E> implements DataList<E> { private AtomicLong size; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link FixedSizeDataList}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private FixedSizeDataType<E> dataType; + private Memory<?> memory; + + /** + * Sets the data type for the list. + * + * @param dataType the data type + * @return this builder + */ + public Builder<E> dataType(FixedSizeDataType<E> dataType) { + this.dataType = dataType; + return this; + } + + /** + * Sets the memory for the list. + * + * @param memory the memory + * @return this builder + */ + public Builder<E> memory(Memory<?> memory) { + this.memory = memory; + return this; + } + + /** + * Builds a new {@link FixedSizeDataList}. + * + * @return a new FixedSizeDataList + * @throws IllegalStateException if the data type is missing + */ + public FixedSizeDataList<E> build() { + if (dataType == null) { + throw new IllegalStateException("Data type must be specified"); + } + + if (memory == null) { + return new FixedSizeDataList<>(dataType); + } else { + return new FixedSizeDataList<>(dataType, memory); + } + } + } + /** * Constructs a {@link FixedSizeDataList}. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataList.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataList.java index e79fa2eb3..89b887044 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataList.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataList.java @@ -33,6 +33,66 @@ public class IndexedDataList<E> implements DataList<E> { private final AppendOnlyLog<E> values; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link IndexedDataList}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private DataList<Long> index; + private AppendOnlyLog<E> values; + + /** + * Sets the index for the list. + * + * @param index the index + * @return this builder + */ + public Builder<E> index(DataList<Long> index) { + this.index = index; + return this; + } + + /** + * Sets the values for the list. + * + * @param values the values + * @return this builder + */ + public Builder<E> values(AppendOnlyLog<E> values) { + this.values = values; + return this; + } + + /** + * Builds a new {@link IndexedDataList}. + * + * @return a new IndexedDataList + * @throws IllegalStateException if values are missing + */ + public IndexedDataList<E> build() { + if (values == null) { + throw new IllegalStateException("Values must be specified"); + } + + if (index == null) { + return new IndexedDataList<>(values); + } else { + return new IndexedDataList<>(index, values); + } + } + } + /** * Constructs a {@link IndexedDataList}. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataMap.java index 346972200..5e2fad6a0 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/IndexedDataMap.java @@ -37,6 +37,66 @@ public class IndexedDataMap<E> implements DataMap<Long, E> { private final AppendOnlyLog<E> values; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link IndexedDataMap}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private Map<Long, Long> index; + private AppendOnlyLog<E> values; + + /** + * Sets the index for the map. + * + * @param index the index + * @return this builder + */ + public Builder<E> index(Map<Long, Long> index) { + this.index = index; + return this; + } + + /** + * Sets the values for the map. + * + * @param values the values + * @return this builder + */ + public Builder<E> values(AppendOnlyLog<E> values) { + this.values = values; + return this; + } + + /** + * Builds a new {@link IndexedDataMap}. + * + * @return a new IndexedDataMap + * @throws IllegalStateException if values are missing + */ + public IndexedDataMap<E> build() { + if (values == null) { + throw new IllegalStateException("Values must be specified"); + } + + if (index == null) { + return new IndexedDataMap<>(values); + } else { + return new IndexedDataMap<>(index, values); + } + } + } + /** * Constructs a {@link IndexedDataMap}. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataList.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataList.java index f335f9bd3..bc9d20784 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataList.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataList.java @@ -47,6 +47,66 @@ public class MemoryAlignedDataList<E> implements DataList<E> { private AtomicLong size; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link MemoryAlignedDataList}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private FixedSizeDataType<E> dataType; + private Memory<?> memory; + + /** + * Sets the data type for the list. + * + * @param dataType the data type + * @return this builder + */ + public Builder<E> dataType(FixedSizeDataType<E> dataType) { + this.dataType = dataType; + return this; + } + + /** + * Sets the memory for the list. + * + * @param memory the memory + * @return this builder + */ + public Builder<E> memory(Memory<?> memory) { + this.memory = memory; + return this; + } + + /** + * Builds a new {@link MemoryAlignedDataList}. + * + * @return a new MemoryAlignedDataList + * @throws IllegalStateException if the data type is missing + */ + public MemoryAlignedDataList<E> build() { + if (dataType == null) { + throw new IllegalStateException("Data type must be specified"); + } + + if (memory == null) { + return new MemoryAlignedDataList<>(dataType); + } else { + return new MemoryAlignedDataList<>(dataType, memory); + } + } + } + /** * Constructs a {@link MemoryAlignedDataList}. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataMap.java index 2d5080dea..00f0cc69f 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MemoryAlignedDataMap.java @@ -45,6 +45,65 @@ public class MemoryAlignedDataMap<E> implements DataMap<Long, E> { private final long upperBoundary; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link MemoryAlignedDataMap}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private FixedSizeDataType<E> dataType; + private Memory<?> memory; + + /** + * Sets the data type for the map. + * + * @param dataType the data type + * @return this builder + */ + public Builder<E> dataType(FixedSizeDataType<E> dataType) { + this.dataType = dataType; + return this; + } + + /** + * Sets the memory for the map. + * + * @param memory the memory + * @return this builder + */ + public Builder<E> memory(Memory<?> memory) { + this.memory = memory; + return this; + } + + /** + * Builds a new {@link MemoryAlignedDataMap}. + * + * @return a new MemoryAlignedDataMap + * @throws IllegalStateException if required parameters are missing + */ + public MemoryAlignedDataMap<E> build() { + if (dataType == null) { + throw new IllegalStateException("Data type must be specified"); + } + if (memory == null) { + throw new IllegalStateException("Memory must be specified"); + } + + return new MemoryAlignedDataMap<>(dataType, memory); + } + } + /** * Constructs a {@link MemoryAlignedDataMap}. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicDataMap.java index 557a10338..eb4308bef 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicDataMap.java @@ -42,6 +42,84 @@ public class MonotonicDataMap<E> implements DataMap<Long, E> { private long lastChunk = -1; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link MonotonicDataMap}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private DataList<Long> offsets; + private DataList<Pair<Long, Long>> keys; + private AppendOnlyLog<E> values; + + /** + * Sets the offsets for the map. + * + * @param offsets the list of offsets + * @return this builder + */ + public Builder<E> offsets(DataList<Long> offsets) { + this.offsets = offsets; + return this; + } + + /** + * Sets the keys for the map. + * + * @param keys the list of keys + * @return this builder + */ + public Builder<E> keys(DataList<Pair<Long, Long>> keys) { + this.keys = keys; + return this; + } + + /** + * Sets the values for the map. + * + * @param values the buffer of values + * @return this builder + */ + public Builder<E> values(AppendOnlyLog<E> values) { + this.values = values; + return this; + } + + /** + * Builds a new {@link MonotonicDataMap}. + * + * @return a new MonotonicDataMap + * @throws IllegalStateException if values are missing + */ + public MonotonicDataMap<E> build() { + if (values == null) { + throw new IllegalStateException("Values must be specified"); + } + + if (offsets == null && keys == null) { + return new MonotonicDataMap<>(values); + } else if (keys == null) { + keys = new MemoryAlignedDataList<>(new PairDataType<>(new LongDataType(), new LongDataType())); + return new MonotonicDataMap<>(offsets, keys, values); + } else if (offsets == null) { + offsets = new MemoryAlignedDataList<>(new LongDataType()); + return new MonotonicDataMap<>(offsets, keys, values); + } else { + return new MonotonicDataMap<>(offsets, keys, values); + } + } + } + /** * Constructs a {@link MonotonicDataMap} with default lists for storing offsets. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicFixedSizeDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicFixedSizeDataMap.java index 611dd5daa..d9809250d 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicFixedSizeDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicFixedSizeDataMap.java @@ -40,6 +40,84 @@ public class MonotonicFixedSizeDataMap<E> implements DataMap<Long, E> { private final DataList<E> values; private long lastChunk = -1; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link MonotonicFixedSizeDataMap}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private DataList<Long> offsets; + private DataList<Long> keys; + private DataList<E> values; + + /** + * Sets the offsets for the map. + * + * @param offsets the list of offsets + * @return this builder + */ + public Builder<E> offsets(DataList<Long> offsets) { + this.offsets = offsets; + return this; + } + + /** + * Sets the keys for the map. + * + * @param keys the list of keys + * @return this builder + */ + public Builder<E> keys(DataList<Long> keys) { + this.keys = keys; + return this; + } + + /** + * Sets the values for the map. + * + * @param values the list of values + * @return this builder + */ + public Builder<E> values(DataList<E> values) { + this.values = values; + return this; + } + + /** + * Builds a new {@link MonotonicFixedSizeDataMap}. + * + * @return a new MonotonicFixedSizeDataMap + * @throws IllegalStateException if values are missing + */ + public MonotonicFixedSizeDataMap<E> build() { + if (values == null) { + throw new IllegalStateException("Values must be specified"); + } + + if (offsets == null && keys == null) { + return new MonotonicFixedSizeDataMap<>(values); + } else if (offsets == null) { + offsets = new MemoryAlignedDataList<>(new LongDataType()); + return new MonotonicFixedSizeDataMap<>(offsets, keys, values); + } else if (keys == null) { + keys = new MemoryAlignedDataList<>(new LongDataType()); + return new MonotonicFixedSizeDataMap<>(offsets, keys, values); + } else { + return new MonotonicFixedSizeDataMap<>(offsets, keys, values); + } + } + } + /** * Constructs a {@link MonotonicFixedSizeDataMap} with default lists for storing offsets and keys. * diff --git a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicPairedDataMap.java b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicPairedDataMap.java index 619097058..781d8bb02 100644 --- a/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicPairedDataMap.java +++ b/baremaps-data/src/main/java/org/apache/baremaps/data/collection/MonotonicPairedDataMap.java @@ -43,6 +43,66 @@ public class MonotonicPairedDataMap<E> implements DataMap<Long, E> { private long lastChunk = -1; + /** + * Static factory method to create a new builder. + * + * @param <E> the type of elements + * @return a new builder + */ + public static <E> Builder<E> builder() { + return new Builder<>(); + } + + /** + * Builder for {@link MonotonicPairedDataMap}. + * + * @param <E> the type of elements + */ + public static class Builder<E> { + private DataList<Long> offsets; + private MemoryAlignedDataList<Pair<Long, E>> values; + + /** + * Sets the offsets for the map. + * + * @param offsets the list of offsets + * @return this builder + */ + public Builder<E> offsets(DataList<Long> offsets) { + this.offsets = offsets; + return this; + } + + /** + * Sets the values for the map. + * + * @param values the buffer of values + * @return this builder + */ + public Builder<E> values(MemoryAlignedDataList<Pair<Long, E>> values) { + this.values = values; + return this; + } + + /** + * Builds a new {@link MonotonicPairedDataMap}. + * + * @return a new MonotonicPairedDataMap + * @throws IllegalStateException if values are missing + */ + public MonotonicPairedDataMap<E> build() { + if (values == null) { + throw new IllegalStateException("Values must be specified"); + } + + if (offsets == null) { + return new MonotonicPairedDataMap<>(values); + } else { + return new MonotonicPairedDataMap<>(offsets, values); + } + } + } + /** * Constructs a {@link MonotonicPairedDataMap}. */ diff --git a/baremaps-data/src/test/java/org/apache/baremaps/data/DataMapTest.java b/baremaps-data/src/test/java/org/apache/baremaps/data/DataMapTest.java index c4c2ab38d..e7d8a8875 100644 --- a/baremaps-data/src/test/java/org/apache/baremaps/data/DataMapTest.java +++ b/baremaps-data/src/test/java/org/apache/baremaps/data/DataMapTest.java @@ -176,6 +176,7 @@ class DataMapTest { new AppendOnlyLog<>(new LongDataType(), new OffHeapMemory()))), Arguments.of(new MonotonicPairedDataMap<>(new MemoryAlignedDataList<>( new PairDataType<>(new LongDataType(), new LongDataType())))), - Arguments.of(new DirectHashDataMap<>(new LongDataType(), new LongDataType(), new OffHeapMemory(), new OffHeapMemory(), 1000))); + Arguments.of(new DirectHashDataMap<>(new LongDataType(), new LongDataType(), + new OffHeapMemory(), new OffHeapMemory(), 1000))); } }
