diff --git a/src/jmh/java/com/trivago/kangaroo/AbstractBenchHelper.java b/src/jmh/java/com/trivago/kangaroo/AbstractBenchHelper.java index cff591e..2de6414 100644 --- a/src/jmh/java/com/trivago/kangaroo/AbstractBenchHelper.java +++ b/src/jmh/java/com/trivago/kangaroo/AbstractBenchHelper.java @@ -9,6 +9,17 @@ public abstract class AbstractBenchHelper extends AbstractCommonBenchHelper { protected static final int NUM_VALUES = 1_000_000; protected ConcurrentLongLongMap map; + /** + * Initializes the concurrent map with a pre-populated set of random key-value pairs. + * + *

The map is configured with 16 buckets, an initial capacity defined by {@code NUM_VALUES}, + * and a load factor of 0.8. When the {@code mode} parameter is {@code BUSY_WAITING}, the map is built + * with busy-waiting behavior; otherwise, a default configuration is used. After initialization, + * the map is populated with {@code NUM_VALUES} entries, each assigned random long keys and values + * generated via {@link ThreadLocalRandom}.

+ * + * @param mode the map mode that determines whether busy-waiting is enabled + */ public void initAndLoadData(PrimitiveMapBuilder.MapMode mode) { if (mode == PrimitiveMapBuilder.MapMode.BUSY_WAITING){ map = ConcurrentLongLongMap.newBuilder() diff --git a/src/jmh/java/com/trivago/kangaroo/AbstractCommonBenchHelper.java b/src/jmh/java/com/trivago/kangaroo/AbstractCommonBenchHelper.java index af4fa41..8af05e7 100644 --- a/src/jmh/java/com/trivago/kangaroo/AbstractCommonBenchHelper.java +++ b/src/jmh/java/com/trivago/kangaroo/AbstractCommonBenchHelper.java @@ -9,6 +9,12 @@ import java.util.concurrent.TimeUnit; public abstract class AbstractCommonBenchHelper { + /** + * Benchmarks the throughput of the "get" operation. + * + *

This method executes the testGet() operation using the throughput mode and measures its performance + * with 4 concurrent threads. + */ @Threads(4) @Benchmark @BenchmarkMode(Mode.Throughput) @@ -46,6 +52,13 @@ public void testRandomPutAvgTime() { testPut(); } + /** + * Measures the average execution time of all operations. + *

+ * Executes the {@code testAllOps()} method across four concurrent threads + * and reports the average execution time in nanoseconds. + *

+ */ @Threads(4) @Benchmark @BenchmarkMode(Mode.AverageTime) @@ -54,9 +67,28 @@ public void testRandomAllOpsAvgTime() { testAllOps(); } - public abstract void testGet(); + /** + * Executes the GET operation benchmark. + * + *

This abstract method should be implemented by subclasses to perform the GET operation, + * which is used in benchmarking tests to measure performance metrics such as throughput and average execution time.

+ */ +public abstract void testGet(); - public abstract void testPut(); + /** + * Executes a put operation for benchmarking purposes. + * + *

Implementations should override this method to define the logic for a put operation, + * which will be measured by throughput and average execution time benchmarks.

+ */ +public abstract void testPut(); - public abstract void testAllOps(); + /** + * Executes a comprehensive set of benchmark operations. + * + *

This abstract method should be implemented to perform a mixed workload—typically combining + * get and put operations—to simulate a realistic full-spectrum scenario. It is invoked during + * benchmarking runs to measure both throughput and average execution time in multi-threaded environments. + */ +public abstract void testAllOps(); } \ No newline at end of file diff --git a/src/jmh/java/com/trivago/kangaroo/FastutilWrapperBusyWaitingBenchmark.java b/src/jmh/java/com/trivago/kangaroo/FastutilWrapperBusyWaitingBenchmark.java index 963163f..e9c3507 100644 --- a/src/jmh/java/com/trivago/kangaroo/FastutilWrapperBusyWaitingBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/FastutilWrapperBusyWaitingBenchmark.java @@ -12,6 +12,12 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperBusyWaitingBenchmark extends AbstractBenchHelper { + /** + * Initializes and loads benchmark data using busy waiting mode. + * + *

This setup method is executed once per trial (as dictated by the @Setup(Level.Trial) + * annotation) to prepare the data required for the benchmark. + */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BUSY_WAITING); diff --git a/src/jmh/java/com/trivago/kangaroo/FastutilWrapperDefaultBenchmark.java b/src/jmh/java/com/trivago/kangaroo/FastutilWrapperDefaultBenchmark.java index d51d86f..912ee4a 100644 --- a/src/jmh/java/com/trivago/kangaroo/FastutilWrapperDefaultBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/FastutilWrapperDefaultBenchmark.java @@ -12,6 +12,14 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperDefaultBenchmark extends AbstractBenchHelper { + /** + * Initializes and loads the data required for the benchmark trial in blocking mode. + * + *

+ * This method is executed once before the benchmark trial starts and sets up the necessary data by + * invoking the initialization routine with the blocking mode specified by {@code PrimitiveMapBuilder.MapMode.BLOCKING}. + *

+ */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BLOCKING); diff --git a/src/jmh/java/com/trivago/kangaroo/JavaUtilWrapperBenchmark.java b/src/jmh/java/com/trivago/kangaroo/JavaUtilWrapperBenchmark.java index 458788e..cfe6c84 100644 --- a/src/jmh/java/com/trivago/kangaroo/JavaUtilWrapperBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/JavaUtilWrapperBenchmark.java @@ -21,6 +21,15 @@ public class JavaUtilWrapperBenchmark extends AbstractCommonBenchHelper { Map map; + /** + * Initializes the benchmark map with random long key-value pairs. + * + *

This setup method creates a {@code Long2LongOpenHashMap} with a predefined capacity and a load factor of 0.8, + * populates it with random long keys and values generated via {@code ThreadLocalRandom}, and then wraps the map with + * {@code Collections.synchronizedMap} to ensure thread-safe access during benchmark trials. + * + *

The method is executed once per trial, as indicated by the {@code @Setup(Level.Trial)} annotation. + */ @Setup(Level.Trial) public void loadData() { Long2LongOpenHashMap m = new Long2LongOpenHashMap(AbstractBenchHelper.NUM_VALUES, 0.8f); @@ -32,12 +41,26 @@ public void loadData() { map = Collections.synchronizedMap(m); } + /** + * Benchmarks a map retrieval operation using a randomly generated key. + * + *

This method generates a random key via {@link java.util.concurrent.ThreadLocalRandom} + * and retrieves the corresponding value from the synchronized map. It is designed to measure + * the performance of get operations during benchmarking tests.

+ */ @Override public void testGet() { long key = ThreadLocalRandom.current().nextLong(); map.get(key); } + /** + * Inserts a new entry into the map using randomly generated key and value. + * + *

This method generates random long values for both the key and value with + * {@link ThreadLocalRandom} and inserts the entry into the synchronized map, + * serving as a benchmark for put operations.

+ */ @Override public void testPut() { long key = ThreadLocalRandom.current().nextLong(); @@ -45,6 +68,17 @@ public void testPut() { map.put(key, value); } + /** + * Executes a randomly selected map operation for benchmarking purposes. + * + *

This method randomly performs one of three actions on the map: + *

+ * This supports mixed operation workloads during benchmark tests. + */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/long2long/AbstractLongLongBenchHelper.java b/src/jmh/java/com/trivago/kangaroo/long2long/AbstractLongLongBenchHelper.java index cacaf5a..0586a94 100644 --- a/src/jmh/java/com/trivago/kangaroo/long2long/AbstractLongLongBenchHelper.java +++ b/src/jmh/java/com/trivago/kangaroo/long2long/AbstractLongLongBenchHelper.java @@ -10,6 +10,15 @@ public abstract class AbstractLongLongBenchHelper extends AbstractCommonBenchHel protected static final int NUM_VALUES = 1_000_000; protected ConcurrentLongLongMap map; + /** + * Initializes the concurrent map with a fixed configuration and populates it with random key-value pairs. + * + *

The map is built with 16 buckets, an initial capacity of {@code NUM_VALUES} (1,000,000), and a load factor of 0.8. + * The provided map mode is used during construction. After initialization, the map is filled with + * {@code NUM_VALUES} randomly generated long key-value pairs. + * + * @param mode the map mode to be applied during the map's initialization + */ public void initAndLoadData (PrimitiveMapBuilder.MapMode mode) { map = ConcurrentLongLongMap.newBuilder() .withBuckets(16) @@ -25,12 +34,24 @@ public void initAndLoadData (PrimitiveMapBuilder.MapMode mode) { } } + /** + * Retrieves a value from the concurrent map using a randomly generated key. + * + *

This benchmark method generates a random long key via ThreadLocalRandom and uses it to perform a + * get operation on the map, facilitating the measurement of concurrent retrieval performance.

+ */ @Override public void testGet() { long key = ThreadLocalRandom.current().nextLong(); map.get(key); } + /** + * Benchmarks the put operation on the concurrent map by inserting a randomly generated key-value pair. + * + *

This method uses thread-local random values for both the key and value to simulate a put operation + * in a concurrent benchmarking scenario.

+ */ @Override public void testPut() { long key = ThreadLocalRandom.current().nextLong(); @@ -38,6 +59,16 @@ public void testPut() { map.put(key, value); } + /** + * Executes a random operation on the concurrent map. + * + *

This method randomly selects one of three operations: + *

+ */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperBusyWaitingLongLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperBusyWaitingLongLongBenchmark.java index e8733dc..7c5c4df 100644 --- a/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperBusyWaitingLongLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperBusyWaitingLongLongBenchmark.java @@ -12,6 +12,12 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperBusyWaitingLongLongBenchmark extends AbstractLongLongBenchHelper { + /** + * Initializes and loads data in busy-waiting mode for the benchmark trial. + * + *

This method is executed once before the benchmark trial begins and sets up the data by + * invoking the superclass's data initialization routine with a busy-waiting strategy. + */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BUSY_WAITING); diff --git a/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperDefaultLongLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperDefaultLongLongBenchmark.java index f20f5ca..a86ec0e 100644 --- a/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperDefaultLongLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/long2long/FastutilWrapperDefaultLongLongBenchmark.java @@ -12,6 +12,13 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperDefaultLongLongBenchmark extends AbstractLongLongBenchHelper { + /** + * Initializes and loads data for the benchmark trial. + * + *

This setup method is executed once before the benchmark trial begins. It initializes + * the necessary data structures in blocking mode by invoking {@code initAndLoadData} with + * {@code PrimitiveMapBuilder.MapMode.BLOCKING}.

+ */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BLOCKING); diff --git a/src/jmh/java/com/trivago/kangaroo/long2long/JavaConcurrentLongLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/long2long/JavaConcurrentLongLongBenchmark.java index 16ca2e7..f88c23b 100644 --- a/src/jmh/java/com/trivago/kangaroo/long2long/JavaConcurrentLongLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/long2long/JavaConcurrentLongLongBenchmark.java @@ -19,6 +19,13 @@ public class JavaConcurrentLongLongBenchmark extends AbstractCommonBenchHelper { Map map; + /** + * Initializes the concurrent map with random key-value pairs for the benchmarking trial. + * + *

This setup method, annotated with {@code @Setup(Level.Trial)}, creates a {@link java.util.concurrent.ConcurrentHashMap} + * using a predefined capacity and load factor, then populates it with entries where both keys and values are random long + * values generated by {@link java.util.concurrent.ThreadLocalRandom}. + */ @Setup(Level.Trial) public void loadData() { map = new ConcurrentHashMap<>(AbstractLongLongBenchHelper.NUM_VALUES, 0.8f); @@ -29,12 +36,25 @@ public void loadData() { } } + /** + * Benchmarks a get operation on the concurrent map by retrieving a value using a randomly generated key. + * + *

This method generates a random long key with ThreadLocalRandom and performs a lookup in the map, + * serving as part of the benchmarking process for concurrent retrieval performance. + */ @Override public void testGet() { long key = ThreadLocalRandom.current().nextLong(); map.get(key); } + /** + * Inserts a random key-value pair into the map. + * + *

This method generates random long values for both the key and the value using ThreadLocalRandom, + * and inserts the generated pair into the map. It overrides the superclass method to simulate a put + * operation within a concurrent benchmarking environment. + */ @Override public void testPut() { long key = ThreadLocalRandom.current().nextLong(); @@ -42,6 +62,18 @@ public void testPut() { map.put(key, value); } + /** + * Executes a randomly selected operation on the concurrent map. + * + *

This method simulates mixed access patterns by performing one of three operations: + *

+ * + *

These operations are used for concurrent benchmarking of map performance. + */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/long2long/JavaUtilWrapperLongLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/long2long/JavaUtilWrapperLongLongBenchmark.java index 885466c..e474368 100644 --- a/src/jmh/java/com/trivago/kangaroo/long2long/JavaUtilWrapperLongLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/long2long/JavaUtilWrapperLongLongBenchmark.java @@ -20,6 +20,15 @@ public class JavaUtilWrapperLongLongBenchmark extends AbstractCommonBenchHelper Map map; + /** + * Initializes the map with random long key-value pairs for benchmarking. + * + *

This method creates a Long2LongOpenHashMap with an initial capacity defined by + * AbstractLongLongBenchHelper.NUM_VALUES and a load factor of 0.8, populating it with + * randomly generated key-value pairs using ThreadLocalRandom. The generated map is then wrapped + * in a synchronized map to ensure thread safety during benchmark operations. This setup is + * executed once per trial as indicated by the @Setup(Level.Trial) annotation.

+ */ @Setup(Level.Trial) public void loadData() { Long2LongOpenHashMap m = new Long2LongOpenHashMap(AbstractLongLongBenchHelper.NUM_VALUES, 0.8f); @@ -31,12 +40,24 @@ public void loadData() { map = Collections.synchronizedMap(m); } + /** + * Benchmarks the retrieval of a value from the map using a randomly generated key. + * + *

This method generates a random key and retrieves the associated value from the map, helping to simulate + * random access patterns during performance measurements. + */ @Override public void testGet() { long key = ThreadLocalRandom.current().nextLong(); map.get(key); } + /** + * Inserts a random key-value pair into the map to benchmark the put operation. + * + *

This method generates random long values for both the key and the value using ThreadLocalRandom, + * then adds the pair to the map. + */ @Override public void testPut() { long key = ThreadLocalRandom.current().nextLong(); @@ -44,6 +65,18 @@ public void testPut() { map.put(key, value); } + /** + * Performs a random operation on the map. + * + *

This method randomly selects one of the following operations using a randomly generated key: + *

+ * + *

The method does not return any value. + */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/AbstractObjectLongBenchHelper.java b/src/jmh/java/com/trivago/kangaroo/object2long/AbstractObjectLongBenchHelper.java index ea02095..af1e50c 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/AbstractObjectLongBenchHelper.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/AbstractObjectLongBenchHelper.java @@ -10,6 +10,15 @@ public abstract class AbstractObjectLongBenchHelper extends AbstractCommonBenchH protected static final int NUM_VALUES = 1_000_000; protected ConcurrentObjectLongMap map; + /** + * Initializes the concurrent map and loads it with test data. + * + *

This method configures the map using a builder pattern with 16 buckets, an initial capacity of + * NUM_VALUES, the specified map mode, and a load factor of 0.8. It then populates the map with NUM_VALUES + * entries, where each entry consists of a new TestObjectKey instance and a randomly generated long value. + * + * @param mode the mode used to configure the map builder + */ public void initAndLoadData (PrimitiveMapBuilder.MapMode mode) { map = ConcurrentObjectLongMap.newBuilder() .withBuckets(16) @@ -25,12 +34,24 @@ public void initAndLoadData (PrimitiveMapBuilder.MapMode mode) { } } + /** + * Performs a benchmark retrieval operation on the concurrent map. + * + *

This method creates a new TestObjectKey and retrieves its associated value from the map, + * allowing measurement of the map's get performance. + */ @Override public void testGet() { TestObjectKey key = new TestObjectKey(); map.get(key); } + /** + * Inserts a new key-value pair into the concurrent map. + * + *

This method creates a fresh key and associates it with a randomly generated long value, + * simulating a put operation for benchmarking purposes. + */ @Override public void testPut() { TestObjectKey key = new TestObjectKey(); @@ -38,6 +59,12 @@ public void testPut() { map.put(key, value); } + /** + * Executes a random operation on the concurrent map. + * + *

This method randomly selects one of three operations—insert (put), removal (remove), or retrieval (get)— + * using a newly instantiated key for each call. When inserting, it generates a random long value to associate with the key. + */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperBusyWaitingObjectLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperBusyWaitingObjectLongBenchmark.java index 47424c2..332c4d0 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperBusyWaitingObjectLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperBusyWaitingObjectLongBenchmark.java @@ -12,6 +12,12 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperBusyWaitingObjectLongBenchmark extends AbstractObjectLongBenchHelper { + /** + * Initializes and loads data for the benchmark using a busy waiting strategy. + * + *

This setup method is executed once per trial and prepares the benchmark state by invoking + * the data initialization routine with a busy-waiting configuration.

+ */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BUSY_WAITING); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperDefaultObjectLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperDefaultObjectLongBenchmark.java index cec4cce..5dd7091 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperDefaultObjectLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/FastutilWrapperDefaultObjectLongBenchmark.java @@ -12,6 +12,12 @@ @Warmup(iterations = 3, time = 1) @Measurement(iterations = 3, time = 2) public class FastutilWrapperDefaultObjectLongBenchmark extends AbstractObjectLongBenchHelper { + /** + * Loads and initializes data for the benchmark trial. + * + *

This method is executed once per trial (annotated with {@code @Setup(Level.Trial)}) and prepares + * the benchmark environment by invoking {@code initAndLoadData} with {@code PrimitiveMapBuilder.MapMode.BLOCKING}. + */ @Setup(Level.Trial) public void loadData() { initAndLoadData(PrimitiveMapBuilder.MapMode.BLOCKING); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/JavaConcurrentObjectLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/object2long/JavaConcurrentObjectLongBenchmark.java index e790615..6ac950e 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/JavaConcurrentObjectLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/JavaConcurrentObjectLongBenchmark.java @@ -19,6 +19,15 @@ public class JavaConcurrentObjectLongBenchmark extends AbstractCommonBenchHelper Map map; + /** + * Populates the concurrent map with test data for benchmarking. + * + *

This method is executed once per trial setup. It initializes the map as a new + * {@link java.util.concurrent.ConcurrentHashMap} with an initial capacity of + * {@link AbstractObjectLongBenchHelper#NUM_VALUES} and a load factor of 0.8. The method then + * iterates {@code NUM_VALUES} times, generating a new {@link TestObjectKey} and a random + * long value for each entry, which is added to the map. + */ @Setup(Level.Trial) public void loadData() { map = new ConcurrentHashMap<>(AbstractObjectLongBenchHelper.NUM_VALUES, 0.8f); @@ -29,11 +38,25 @@ public void loadData() { } } + /** + * Executes a get operation on the concurrent map for benchmarking purposes. + * + *

+ * This method retrieves a value from the map using a new instance of {@code TestObjectKey}, + * measuring the performance of read operations in a concurrent environment. + *

+ */ @Override public void testGet() { map.get(new TestObjectKey()); } + /** + * Executes a put operation by inserting a new key-value pair into the concurrent map. + * + *

This method creates a new instance of TestObjectKey and associates it with a random long value, + * simulating a put operation for benchmark testing. + */ @Override public void testPut() { TestObjectKey key = new TestObjectKey(); @@ -41,6 +64,17 @@ public void testPut() { map.put(key, value); } + /** + * Executes a random operation on the concurrent map used for benchmarking. + * + *

This method simulates a mixed workload by randomly choosing one of three actions: + *

+ * The operation is selected using a thread-local random generator. + */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/JavaUtilWrapperObjectLongBenchmark.java b/src/jmh/java/com/trivago/kangaroo/object2long/JavaUtilWrapperObjectLongBenchmark.java index d794de2..c6e7db7 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/JavaUtilWrapperObjectLongBenchmark.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/JavaUtilWrapperObjectLongBenchmark.java @@ -20,6 +20,13 @@ public class JavaUtilWrapperObjectLongBenchmark extends AbstractCommonBenchHelpe Map map; + /** + * Initializes the benchmark map with random key-value pairs. + * + *

This method creates an {@code Object2LongOpenHashMap} with a predefined capacity and load factor, + * populates it with random long values using new {@code TestObjectKey} instances, and wraps the map + * in a synchronized wrapper. It is executed once per trial as part of the benchmark setup.

+ */ @Setup(Level.Trial) public void loadData() { Object2LongOpenHashMap m = new Object2LongOpenHashMap<>(AbstractObjectLongBenchHelper.NUM_VALUES, 0.8f); @@ -31,11 +38,23 @@ public void loadData() { map = Collections.synchronizedMap(m); } + /** + * Executes a benchmark test for the get operation on the map. + * + *

This method retrieves a value using a newly instantiated TestObjectKey to measure the performance of + * map lookup operations as part of the benchmark. + */ @Override public void testGet() { map.get(new TestObjectKey()); } + /** + * Inserts a new key-value pair into the map used for benchmarking. + * + *

This method creates a new instance of TestObjectKey and generates a random long value, + * then adds the pair to the map. + */ @Override public void testPut() { TestObjectKey key = new TestObjectKey(); @@ -43,6 +62,18 @@ public void testPut() { map.put(key, value); } + /** + * Executes one of the map operations (put, remove, or get) at random. + * + *

This method randomly selects one of three operations to perform on the map: + *

    + *
  • Put - Inserts a new {@code TestObjectKey} with a randomly generated long value. + *
  • Remove - Removes an entry associated with a new {@code TestObjectKey}. + *
  • Get - Retrieves the value for a new {@code TestObjectKey}. + *
+ * Each operation uses a freshly created instance of {@code TestObjectKey}. Note that no operation result is returned. + *

+ */ @Override public void testAllOps() { int op = ThreadLocalRandom.current().nextInt(3); diff --git a/src/jmh/java/com/trivago/kangaroo/object2long/TestObjectKey.java b/src/jmh/java/com/trivago/kangaroo/object2long/TestObjectKey.java index 2957802..e9584ef 100644 --- a/src/jmh/java/com/trivago/kangaroo/object2long/TestObjectKey.java +++ b/src/jmh/java/com/trivago/kangaroo/object2long/TestObjectKey.java @@ -6,6 +6,14 @@ public class TestObjectKey { private final int id = ThreadLocalRandom.current().nextInt(); + /** + * Returns the hash code for this object based on its unique identifier. + *

+ * The hash code is computed by applying {@link Integer#hashCode(int)} to the {@code id} field. + *

+ * + * @return the hash code derived from the object's {@code id} + */ @Override public int hashCode() { return Integer.hashCode(id); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/PrimitiveConcurrentMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/PrimitiveConcurrentMap.java index 5ce9579..3e90c55 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/PrimitiveConcurrentMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/PrimitiveConcurrentMap.java @@ -16,6 +16,16 @@ public abstract class PrimitiveConcurrentMap implements PrimitiveKeyMap { protected final int numBuckets; protected final ReadWriteLock[] locks; + /** + * Constructs a new {@code PrimitiveConcurrentMap} with the specified number of buckets. + * + *

The map is initialized with a fixed number of buckets, each protected by a separate {@link ReentrantReadWriteLock} + * for thread safety. The {@code numBuckets} parameter must be within the range [1, 100,000,000]; otherwise, an + * {@link IllegalArgumentException} is thrown. + * + * @param numBuckets the number of buckets for the map; must be between 1 and 100,000,000 + * @throws IllegalArgumentException if {@code numBuckets} is less than 1 or greater than 100,000,000 + */ protected PrimitiveConcurrentMap (int numBuckets) { if (numBuckets < 1 || numBuckets > 100_000_000) throw new IllegalArgumentException("numBuckets must be between 1 and 100_000_000, but: "+ numBuckets); @@ -25,7 +35,14 @@ protected PrimitiveConcurrentMap (int numBuckets) { locks[i] = new ReentrantReadWriteLock(); }//new - /** Lock must be held! */ + /** + * Retrieves the mapping function for the bucket at the specified index. + *

+ * Precondition: The appropriate lock must be held when calling this method. + * + * @param index the index of the bucket whose mapping function is to be retrieved + * @return the mapping function associated with the specified bucket index + */ protected abstract Function mapAt (int index); @Override @@ -77,14 +94,44 @@ protected int getBucket(long key) { return bucket(hash, numBuckets); } + /** + * Computes the bucket index for the given integer key. + * + *

+ * The key is used as its own hash code and passed to the static {@link #bucket(int, int)} method, + * which applies a mixing function to distribute entries uniformly across the available buckets. + *

+ * + * @param key the integer key for which to compute the bucket index + * @return the computed bucket index, within the range [0, numBuckets) + */ protected int getBucket(int key) { return bucket(key, numBuckets);// Integer.hashCode(key) == key } + /** + * Computes the bucket index for the given key. + * + *

If the key is {@code null}, returns a default index of 0; otherwise, uses the key's hash + * code and the total number of buckets to compute the appropriate bucket index.

+ * + * @param key the key used to determine the bucket index, may be {@code null} + * @return the computed bucket index for the key + */ protected int getBucket (Object key) { return key != null ? bucket(key.hashCode(), numBuckets) : 0; } + /** + * Computes the bucket index for the given hash value. + * + *

This method applies a mixing function to the input hash and returns the absolute value of the remainder + * when divided by the total number of buckets. The resulting index is within the range [0, bucketSize). + * + * @param hash the hash value to be mixed + * @param bucketSize the total number of available buckets; must be positive + * @return the computed bucket index + */ public static int bucket (int hash, int bucketSize) { return Math.abs(HashCommon.mix(hash) % bucketSize); } diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntFloatMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntFloatMap.java index e94aec3..d5eaf8f 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntFloatMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntFloatMap.java @@ -6,10 +6,32 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingIntFloatMap extends ConcurrentIntFloatMap { + /** + * Constructs a new ConcurrentBusyWaitingIntFloatMap with the specified configuration. + * + * This map employs busy waiting for lock acquisition and delegates initialization to its superclass. + * It partitions data into a specified number of buckets, defines an initial capacity and load factor, + * and uses a default value for missing keys. + * + * @param numBuckets the number of buckets used for partitioning the map for concurrent access + * @param initialCapacity the initial capacity of the map + * @param loadFactor the load factor that triggers resizing when exceeded + * @param defaultValue the default value returned when a key is not present in the map + */ public ConcurrentBusyWaitingIntFloatMap (int numBuckets, int initialCapacity, float loadFactor, float defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks if the map contains the specified key. + * + *

This method continuously attempts to acquire a read lock on the bucket associated + * with the key using busy waiting. Once the lock is obtained, it checks whether the key + * exists in the corresponding bucket.

+ * + * @param key the key to check in the map + * @return {@code true} if the key is present, {@code false} otherwise + */ @Override public boolean containsKey(int key) { int bucket = getBucket(key); @@ -28,6 +50,15 @@ public boolean containsKey(int key) { } } + /** + * Retrieves the value associated with the specified key from the map. + * + *

This method continuously attempts to acquire the read lock for the bucket corresponding to the key via busy waiting. + * It returns the value mapped to the key if present, or the default value otherwise. + * + * @param key the key whose associated value is to be returned + * @return the value associated with the key, or the default value if the key does not exist + */ @Override public float get (int key) { int bucket = getBucket(key); @@ -46,6 +77,16 @@ public float get (int key) { } } + /** + * Inserts or updates the value for the specified key in the map. + * + *

This method acquires a write lock for the appropriate bucket using busy waiting. Once the lock is acquired, it updates + * the mapping for the key and returns the previous value associated with the key, or the default value if no mapping existed. + * + * @param key the key for which the value is to be inserted or updated + * @param value the value to associate with the specified key + * @return the previous value associated with the key, or the default value if there was no mapping + */ @Override public float put(int key, float value) { int bucket = getBucket(key); @@ -64,6 +105,16 @@ public float put(int key, float value) { } } + /** + * Removes the mapping for the specified key and returns its associated value. + * + * This method busy-waits to acquire the write lock for the bucket determined by the key, then + * removes the key from that bucket. If the key is present, its associated value is returned; + * otherwise, the map's default value is returned. + * + * @param key the key whose mapping is to be removed + * @return the value previously associated with the key, or the default value if no mapping existed + */ @Override public float remove(int key) { int bucket = getBucket(key); @@ -82,6 +133,17 @@ public float remove(int key) { } } + /** + * Removes the mapping for the specified key if it is currently associated with the given value. + *

+ * This method repeatedly attempts to acquire the write lock for the key's bucket using busy waiting. + * If the current value associated with the key equals the specified value, the mapping is removed. + *

+ * + * @param key the key whose mapping is to be conditionally removed + * @param value the expected value associated with the key for removal to occur + * @return {@code true} if the mapping was present and removed, {@code false} otherwise + */ @Override public boolean remove(int key, float value) { int bucket = getBucket(key); @@ -100,6 +162,18 @@ public boolean remove(int key, float value) { } } + /** + * Computes and returns the value associated with the specified key if it is not already present. + * + *

+ * This method busy-waits to acquire a write lock for the bucket corresponding to the key. Once the lock is obtained, + * it either returns the existing value or computes and stores a new value using the provided mapping function. + *

+ * + * @param key the key for which the value should be computed if absent + * @param mappingFunction the function to compute a new value if the key is not already present + * @return the current value associated with the key, either existing or newly computed + */ @Override public float computeIfAbsent(int key, Int2FloatFunction mappingFunction) { int bucket = getBucket(key); @@ -118,6 +192,17 @@ public float computeIfAbsent(int key, Int2FloatFunction mappingFunction) { } } + /** + * Computes a new value for the specified key if it is already present. + * + *

This method repeatedly attempts to acquire the write lock for the bucket corresponding to the key + * using busy waiting. Once the lock is obtained, it applies the provided mapping function to the key and its + * current value to compute an updated value. + * + * @param key the key whose associated value is to be updated if present + * @param mappingFunction a function that computes a new value from the key and its current value + * @return the updated value associated with the key, or the current value if the mapping function does not alter it + */ @Override public float computeIfPresent(int key, BiFunction mappingFunction) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntIntMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntIntMap.java index 0e22bb2..6ccffd0 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntIntMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentBusyWaitingIntIntMap.java @@ -6,10 +6,31 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingIntIntMap extends ConcurrentIntIntMap { + /** + * Constructs a new ConcurrentBusyWaitingIntIntMap with the specified configuration parameters. + * + *

This implementation partitions its data into a fixed number of buckets and uses busy waiting to acquire + * locks for thread-safe access. Initialization is delegated to the superclass, ConcurrentIntIntMap. + * + * @param numBuckets the number of buckets used for partitioning the map + * @param initialCapacity the initial capacity of the map + * @param loadFactor the load factor that influences the map's resizing threshold + * @param defaultValue the default value to return when a key is not found + */ public ConcurrentBusyWaitingIntIntMap (int numBuckets, int initialCapacity, float loadFactor, int defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Determines if the map contains the specified key. + * + *

This method calculates the bucket corresponding to the key and repeatedly attempts to acquire a + * read lock using busy waiting. Once the lock is obtained, it verifies the presence of the key in the + * associated bucket.

+ * + * @param key the key whose presence in the map is to be tested + * @return {@code true} if the key exists in the map; {@code false} otherwise + */ @Override public boolean containsKey(int key) { int bucket = getBucket(key); @@ -46,6 +67,17 @@ public int get(int key) { } } + /** + * Inserts or updates the value for the specified key. + *

+ * This method acquires the write lock on the appropriate bucket using a busy-wait + * mechanism. Once the lock is obtained, it updates the mapping for the given key by + * delegating to the underlying map implementation. + * + * @param key the key whose value is to be inserted or updated + * @param value the value to associate with the key + * @return the previous value associated with the key, or a default value if no mapping existed + */ @Override public int put(int key, int value) { int bucket = getBucket(key); @@ -64,6 +96,16 @@ public int put(int key, int value) { } } + /** + * Removes the mapping for the specified key from the map. + * + *

This method repeatedly attempts to acquire the write lock for the bucket + * corresponding to the given key using a busy waiting strategy. Once the lock is + * obtained, it removes the mapping and returns the previously associated value. + * + * @param key the key whose mapping should be removed + * @return the value that was associated with the key, or the default value if no mapping existed + */ @Override public int remove(int key) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntFloatMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntFloatMap.java index 8cf7244..9463ec3 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntFloatMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntFloatMap.java @@ -13,6 +13,19 @@ public class ConcurrentIntFloatMap extends PrimitiveConcurrentMap protected final Int2FloatOpenHashMap[] maps; protected final float defaultValue; + /** + * Constructs a concurrent map that maps integer keys to float values using a segmented bucket approach. + *

+ * The map is divided into multiple buckets to support concurrent access. Each bucket is initialized + * as an instance of {@code Int2FloatOpenHashMap} with the specified initial capacity and load factor. + * The specified default value is returned for any key that is not present in the map. + *

+ * + * @param numBuckets the number of buckets used for concurrency segmentation + * @param initialCapacity the initial capacity for each bucket + * @param loadFactor the load factor that determines when each bucket's capacity should be increased + * @param defaultValue the value returned for keys that do not exist in the map + */ public ConcurrentIntFloatMap( int numBuckets, int initialCapacity, @@ -26,11 +39,29 @@ public ConcurrentIntFloatMap( maps[i] = new Int2FloatOpenHashMap(initialCapacity, loadFactor); } + /** + * Retrieves the mapping function for the specified bucket index. + * + *

This method returns the internal mapping function (bucket) corresponding to the given index, + * allowing for thread-safe operations on that segment of the map. + * + * @param index the index of the bucket to access + * @return the mapping function for the specified bucket index + */ @Override protected Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains the specified key. + * + *

This method determines the appropriate bucket for the key, acquires a read lock on that bucket, + * and then verifies if the key is present in the corresponding map.

+ * + * @param key the key to check + * @return true if the map contains a mapping for the specified key, false otherwise + */ public boolean containsKey(int key) { int bucket = getBucket(key); @@ -43,6 +74,15 @@ public boolean containsKey(int key) { } } + /** + * Retrieves the value associated with the specified key. + *

+ * If the key is not present in the map, the default value is returned. + *

+ * + * @param key the key whose associated value is to be returned + * @return the float value associated with the key, or the default value if the key is absent + */ public float get(int key) { int bucket = getBucket(key); @@ -55,6 +95,17 @@ public float get(int key) { } } + /** + * Inserts or updates the value associated with the specified key. + * + *

If the key already has an associated value, that value is replaced and returned. + * If the key is not present, the key is mapped to the given value and the default map value + * is returned. This operation is thread-safe.

+ * + * @param key the key whose mapping is to be inserted or updated + * @param value the new float value to associate with the key + * @return the previous float value associated with the key, or the default value if none existed + */ public float put(int key, float value) { int bucket = getBucket(key); @@ -67,8 +118,22 @@ public float put(int key, float value) { } } - public float getDefaultValue (){ return defaultValue; } - + /** + * Returns the default float value used in the map for keys that have no associated value. + * + * @return the default float value + */ +public float getDefaultValue (){ return defaultValue; } + + /** + * Removes the entry for the specified key in a thread-safe manner. + *

+ * Returns the value previously associated with the key, or the default value if the key was not present. + *

+ * + * @param key the key of the entry to remove + * @return the value previously associated with the specified key, or the default value if none existed + */ public float remove(int key) { int bucket = getBucket(key); @@ -81,6 +146,13 @@ public float remove(int key) { } } + /** + * Removes the entry for the specified key only if it is currently mapped to the given value. + * + * @param key the key to remove + * @param value the value expected to be associated with the key + * @return {@code true} if the mapping was removed, or {@code false} if the key was not mapped to the specified value + */ public boolean remove(int key, float value) { int bucket = getBucket(key); @@ -93,6 +165,16 @@ public boolean remove(int key, float value) { } } + /** + * Computes and associates a value with the specified key if it is not already present. + * This method acquires a write lock on the relevant bucket to ensure thread safety, then either + * returns the existing value or computes a new one using the provided mapping function, stores it, + * and returns it. + * + * @param key the key for which the value should be computed if absent + * @param mappingFunction the function to compute a value when the key is absent + * @return the current value associated with the key, whether already present or newly computed + */ public float computeIfAbsent(int key, Int2FloatFunction mappingFunction) { int bucket = getBucket(key); @@ -105,6 +187,17 @@ public float computeIfAbsent(int key, Int2FloatFunction mappingFunction) { } } + /** + * Computes a new value for the given key if it is already present in the map. + * + *

If the key exists, the supplied mapping function is applied to the key and its current value, + * and the mapping is updated with the computed result in a thread-safe manner. If the key is not + * present, the mapping function is not invoked and the map remains unchanged.

+ * + * @param key the key whose value is to be computed and potentially updated + * @param mappingFunction a function that takes the key and its current value to compute a new value + * @return the new value associated with the key, or the default value if the key was not present + */ public float computeIfPresent(int key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -117,6 +210,16 @@ public float computeIfPresent(int key, BiFunction mapping } } + /** + * Returns a new builder for configuring and constructing {@code ConcurrentIntFloatMap} instances. + * + *

The returned builder lets you define map properties such as the number of buckets, initial capacity, + * load factor, and default value for absent keys. When the builder's {@code build()} method is called, it + * selects the appropriate implementation—either a busy-waiting or blocking version—based on the current map mode. + * If no default value is specified, 0 is used.

+ * + * @return a new {@code PrimitiveMapBuilder} for creating {@code ConcurrentIntFloatMap} instances with the desired configuration + */ public static PrimitiveMapBuilder newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntIntMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntIntMap.java index f738b7e..3694a55 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntIntMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/intkey/ConcurrentIntIntMap.java @@ -13,6 +13,17 @@ public class ConcurrentIntIntMap extends PrimitiveConcurrentMap protected final Int2IntOpenHashMap[] maps; protected final int defaultValue; + /** + * Constructs a new ConcurrentIntIntMap with the specified number of buckets, initial capacity, load factor, and default value. + * + *

This constructor creates an array of Int2IntOpenHashMap instances, one per bucket, where each map is initialized with + * the given initial capacity and load factor. The provided default value is stored and used for any key that is not present. + * + * @param numBuckets the number of buckets to divide the map into + * @param initialCapacity the initial capacity of each bucket's map + * @param loadFactor the load factor for each bucket's map + * @param defaultValue the default value returned for missing keys + */ public ConcurrentIntIntMap( int numBuckets, int initialCapacity, @@ -26,11 +37,25 @@ public ConcurrentIntIntMap( maps[i] = new Int2IntOpenHashMap(initialCapacity, loadFactor); } + /** + * Retrieves the mapping function for the bucket at the specified index. + * + * @param index the index of the bucket to retrieve + * @return the mapping function corresponding to the bucket at the given index + */ @Override protected Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains an entry for the specified key. + * + *

This thread-safe method uses a read lock on the appropriate bucket to verify the presence of the key in the map.

+ * + * @param key the key to check in the map + * @return {@code true} if the map contains an entry for the key, {@code false} otherwise + */ public boolean containsKey(int key) { int bucket = getBucket(key); @@ -43,6 +68,16 @@ public boolean containsKey(int key) { } } + /** + * Retrieves the value associated with the specified key in a thread-safe manner. + *

+ * This method acquires a read lock on the bucket corresponding to the provided key + * and returns its value. If the key is not found, the default value is returned. + *

+ * + * @param key the key whose associated value is to be returned + * @return the value mapped to the key, or the default value if no mapping exists + */ public int get (int key) { int bucket = getBucket(key); @@ -55,6 +90,17 @@ public int get (int key) { } } + /** + * Inserts or updates the value associated with the specified key. + * + *

This method determines the bucket corresponding to the key, acquires the bucket's write lock, + * and updates the underlying map with the new value. It returns the previous value associated with the key, + * or the default value if no mapping was present. + * + * @param key the key to update + * @param value the value to associate with the key + * @return the previous value associated with the key, or the default value if the key was not present + */ public int put(int key, int value) { int bucket = getBucket(key); @@ -67,8 +113,23 @@ public int put(int key, int value) { } } - public int getDefaultValue (){ return defaultValue; } - + /** + * Returns the default value used for keys that are not present in the map. + * + * @return the default value. + */ +public int getDefaultValue (){ return defaultValue; } + + /** + * Removes the mapping for the specified key and returns the associated value. + * + *

This method identifies the corresponding bucket for the key, acquires a write lock on that bucket, + * and removes the key-value mapping. It returns the value that was previously associated with the key, + * or the map's default value if no mapping was present.

+ * + * @param key the key whose mapping is to be removed + * @return the value associated with the key before removal, or the default value if the key was not mapped + */ public int remove(int key) { int bucket = getBucket(key); @@ -81,6 +142,15 @@ public int remove(int key) { } } + /** + * Removes the entry for the specified key only if it is currently associated with the given value. + *

+ * This method ensures thread-safe removal by acquiring a write lock on the bucket corresponding to the key. + * + * @param key the key whose mapping is to be conditionally removed + * @param value the value expected to be associated with the key + * @return {@code true} if the entry was removed, {@code false} otherwise + */ public boolean remove(int key, int value) { int bucket = getBucket(key); @@ -93,6 +163,15 @@ public boolean remove(int key, int value) { } } + /** + * Atomically computes and associates a value for the specified key if absent. + * If no value is present for the key, the provided mapping function is applied to compute a new value, + * which is then stored and returned. If a value already exists, it is simply returned. + * + * @param key the key for which the value is to be computed + * @param mappingFunction the function to compute a value for the key if it is not already present + * @return the existing or computed value associated with the specified key + */ public int computeIfAbsent(int key, Int2IntFunction mappingFunction) { int bucket = getBucket(key); @@ -105,6 +184,17 @@ public int computeIfAbsent(int key, Int2IntFunction mappingFunction) { } } + /** + * Atomically updates the value for the specified key if a mapping is present. + * + *

If the key is currently mapped to a value, this method applies the provided mapping function + * to compute a new value and updates the mapping accordingly. If the key is not present, + * the default value is returned. + * + * @param key the key whose associated value is to be updated + * @param mappingFunction the function that computes a new value from the key and its current value + * @return the updated value for the key if present; otherwise, the default value + */ public int computeIfPresent(int key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -117,6 +207,16 @@ public int computeIfPresent(int key, BiFunction mappi } } + /** + * Creates a builder for constructing instances of ConcurrentIntIntMap. + * + *

The returned builder allows configuration of map parameters such as the number of buckets, initial capacity, + * load factor, and default value for missing keys. When the build method is invoked, the builder creates a map + * instance based on the configured map mode: a ConcurrentBusyWaitingIntIntMap is returned for BUSY_WAITING mode, + * and a ConcurrentIntIntMap for BLOCKING mode. If no default value is set, zero is used.

+ * + * @return a builder for creating ConcurrentIntIntMap instances + */ public static PrimitiveMapBuilder newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongFloatMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongFloatMap.java index 9e18a06..67bc9ee 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongFloatMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongFloatMap.java @@ -6,10 +6,31 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingLongFloatMap extends ConcurrentLongFloatMap { + /** + * Constructs a new ConcurrentBusyWaitingLongFloatMap with the specified configuration. + * + *

This constructor initializes a concurrent map for long keys and float values that employs busy waiting + * for lock acquisition. The map is partitioned into the specified number of buckets, uses the given initial capacity + * and load factor, and returns the provided default value when a key is not present.

+ * + * @param numBuckets the number of buckets for partitioning the map + * @param initialCapacity the initial capacity of the map + * @param loadFactor the load factor that determines when the map should be resized + * @param defaultValue the default float value returned if a key is absent + */ public ConcurrentBusyWaitingLongFloatMap (int numBuckets, int initialCapacity, float loadFactor, float defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks whether the map contains the specified key. + * + *

This method determines the appropriate bucket for the key and uses a busy-wait loop to acquire a read lock. Once the lock is acquired, + * it queries the underlying map to check for the key's presence. + * + * @param key the key to check for presence in the map + * @return {@code true} if the key exists in the map, otherwise {@code false} + */ @Override public boolean containsKey(long key) { int bucket = getBucket(key); @@ -46,6 +67,16 @@ public float get(long key) { } } + /** + * Inserts or updates the mapping for the specified key using busy waiting until a write lock is acquired. + * + *

The method identifies the appropriate bucket based on the key, then repeatedly attempts to acquire the corresponding + * write lock. Once the lock is obtained, it updates the value associated with the key and returns the previous value. + * + * @param key the key whose mapping is to be updated + * @param value the new value to associate with the key + * @return the previous value associated with the key, or the default value if no mapping existed + */ @Override public float put(long key, float value) { int bucket = getBucket(key); @@ -64,6 +95,17 @@ public float put(long key, float value) { } } + /** + * Removes the entry for the specified key from the map. + * + *

This method determines the appropriate bucket for the key and repeatedly attempts + * to acquire the corresponding write lock using busy waiting. Once the lock is acquired, + * it removes the key and returns the value that was previously associated with it. If the + * key is not present, the default value is returned. + * + * @param key the key whose entry is to be removed + * @return the value associated with the removed key, or the default value if the key was not present + */ @Override public float remove(long key) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongIntMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongIntMap.java index a08057d..7ba5ec6 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongIntMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongIntMap.java @@ -6,10 +6,33 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingLongIntMap extends ConcurrentLongIntMap { + /** + * Constructs a new ConcurrentBusyWaitingLongIntMap with the specified configuration. + *

+ * This map partitions its storage into the given number of buckets to facilitate concurrent access, + * using busy waiting for lock acquisition. Each bucket is initialized with the specified capacity and load factor, + * and the supplied default value is returned for absent keys. + * + * @param numBuckets the number of partitions for concurrent access + * @param initialCapacity the starting capacity for each bucket + * @param loadFactor the load factor threshold for resizing each bucket + * @param defaultValue the value to return when a key is not present in the map + */ public ConcurrentBusyWaitingLongIntMap (int numBuckets, int initialCapacity, float loadFactor, int defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks whether the map contains the specified key. + * + *

+ * This method calculates the appropriate bucket for the given key and repeatedly attempts to acquire a read lock + * using busy waiting. Once the lock is acquired, it checks if the key exists in the bucket. + *

+ * + * @param key the key to search for in the map + * @return {@code true} if the key is present, {@code false} otherwise + */ @Override public boolean containsKey(long key) { int bucket = getBucket(key); @@ -46,6 +69,17 @@ public int get(long key) { } } + /** + * Inserts or updates the value associated with the specified key. + * + *

This method repeatedly attempts to acquire a write lock on the bucket for the given key using busy waiting. + * Once the lock is obtained, it updates the stored value for the key and returns the previous value associated with it, + * or a default value if the key was not previously mapped. + * + * @param key the key whose value is to be inserted or updated + * @param value the new value to associate with the key + * @return the previous value associated with the key, or the default if none existed + */ @Override public int put(long key, int value) { int bucket = getBucket(key); @@ -64,6 +98,16 @@ public int put(long key, int value) { } } + /** + * Removes the mapping for the specified key from the map. + * + *

This method uses busy waiting to acquire the write lock associated with the bucket + * containing the key. Once the appropriate lock is obtained, it removes the key-value + * pair and returns the value that was previously associated with the key. + * + * @param key the long key whose mapping is to be removed + * @return the value previously associated with the key, or the map's default value if not present + */ @Override public int remove(long key) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongLongMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongLongMap.java index 80917cd..1a77783 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongLongMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongLongMap.java @@ -6,10 +6,31 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingLongLongMap extends ConcurrentLongLongMap { + /** + * Constructs a ConcurrentBusyWaitingLongLongMap with the specified configuration. + * + *

This constructor initializes the map by partitioning it into a fixed number of buckets to support concurrent + * operations via busy-waiting locks. The initial capacity and load factor influence the map's performance and resizing behavior, + * while the default value is returned for keys that are not present.

+ * + * @param numBuckets the number of buckets used to partition the map + * @param initialCapacity the initial capacity for each bucket + * @param loadFactor the factor that determines when the map should be resized + * @param defaultValue the default value returned for missing keys + */ public ConcurrentBusyWaitingLongLongMap (int numBuckets, int initialCapacity, float loadFactor, long defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks if the map contains the specified key. + * + *

This method busy-waits until a read lock on the corresponding bucket is acquired, then it verifies + * the presence of the key in the underlying map. + * + * @param key the key to check for presence + * @return {@code true} if the key exists in the map; {@code false} otherwise + */ @Override public boolean containsKey(long key) { int bucket = getBucket(key); @@ -46,6 +67,17 @@ public long get(long key) { } } + /** + * Inserts or updates the mapping for the specified key with the given value. + * + *

This method employs a busy-waiting strategy to acquire the write lock on the bucket corresponding to the key. + * Once the lock is obtained, it updates the underlying map and returns the previous value associated with the key, + * or the default value if the key was not present. + * + * @param key the key whose mapping is to be updated + * @param value the value to associate with the key + * @return the previous value associated with the key, or the default value if the key did not have a mapping + */ @Override public long put(long key, long value) { int bucket = getBucket(key); @@ -64,6 +96,14 @@ public long put(long key, long value) { } } + /** + * Removes the mapping for the specified key. + * + *

This method repeatedly attempts to acquire the write lock for the bucket associated with the given key using a busy-waiting strategy. Once the lock is acquired, it removes and returns the value associated with the key from the underlying map. + * + * @param key the key whose mapping is to be removed + * @return the value previously associated with the key, or the default value if the key was not present + */ @Override public long remove(long key) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongObjectMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongObjectMap.java index 76e2352..373018c 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongObjectMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentBusyWaitingLongObjectMap.java @@ -6,10 +6,28 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingLongObjectMap extends ConcurrentLongObjectMap { + /** + * Constructs a new ConcurrentBusyWaitingLongObjectMap with the specified number of buckets, initial capacity, load factor, and default value. + * + * @param numBuckets the number of buckets used for segmenting the map + * @param initialCapacity the initial total capacity of the map + * @param loadFactor the load factor threshold for resizing the map + * @param defaultValue the default value returned when a key is not present + */ public ConcurrentBusyWaitingLongObjectMap (int numBuckets, int initialCapacity, float loadFactor, V defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks if the map contains a mapping for the specified key. + * + *

This method repeatedly attempts to acquire a read lock for the bucket corresponding + * to the specified key using busy waiting. Once the lock is acquired, it returns whether + * the underlying bucket map contains the key.

+ * + * @param key the key whose presence is to be tested + * @return {@code true} if a mapping for the key exists; {@code false} otherwise + */ @Override public boolean containsKey(long key) { int bucket = getBucket(key); @@ -28,6 +46,16 @@ public boolean containsKey(long key) { } } + /** + * Retrieves the value associated with the specified key. + * + *

This method returns the value mapped to the key if present; otherwise, it returns + * the default value. It acquires the corresponding bucket's read lock using a busy waiting approach, + * continuously yielding with {@code Thread.onSpinWait()} until the lock is obtained. + * + * @param key the key whose associated value is to be retrieved + * @return the value associated with the key, or the default value if the key is not present + */ @Override public V get (long key) { int bucket = getBucket(key); @@ -46,6 +74,17 @@ public V get (long key) { } } + /** + * Inserts or updates the mapping for the specified key using busy waiting for write lock acquisition. + * + *

This method determines the corresponding bucket for the key and repeatedly attempts to acquire the + * write lock. Once the lock is held, it delegates the put operation to the underlying bucket map and returns + * the previous value associated with the key, if any. + * + * @param key the key for which the value is being stored + * @param value the new value to associate with the key + * @return the previous value associated with the key, or null if no mapping existed + */ @Override public V put (long key, V value) { int bucket = getBucket(key); @@ -64,6 +103,16 @@ public V put (long key, V value) { } } + /** + * Removes the entry associated with the specified key from the map. + * + *

The method identifies the correct bucket for the key and continually attempts to acquire the bucket's + * write lock using busy waiting. When the lock is acquired, it removes the key from the corresponding bucket's + * underlying map. + * + * @param key the key whose mapping is to be removed + * @return the previous value associated with the key, or {@code null} if no mapping existed + */ @Override public V remove (long key) { int bucket = getBucket(key); @@ -82,6 +131,14 @@ public V remove (long key) { } } + /** + * Conditionally removes the mapping for the specified key if it is currently associated with the given value. + * This method busy-waits to acquire a write lock on the bucket corresponding to the key before attempting removal. + * + * @param key the key whose mapping is to be removed + * @param value the expected value associated with the key + * @return true if the mapping was removed, false otherwise + */ @Override public boolean remove (long key, V value) { int bucket = getBucket(key); @@ -100,6 +157,17 @@ public boolean remove (long key, V value) { } } + /** + * Computes and stores a value for the specified key if it is not already present. + * + *

This method identifies the bucket corresponding to the key and employs a busy waiting loop to acquire its + * write lock. Once the lock is acquired, if the key is absent, the provided mapping function is used to compute + * and store the value, which is then returned.

+ * + * @param key the key whose value is to be computed if absent + * @param mappingFunction the function to compute a value when the key is not mapped + * @return the current (existing or computed) value associated with the specified key + */ @Override public V computeIfAbsent (long key, Long2ObjectFunction mappingFunction) { int bucket = getBucket(key); @@ -118,6 +186,16 @@ public V computeIfAbsent (long key, Long2ObjectFunction mappingFunction) { } } + /** + * Computes a new mapping for the specified key if it is already present. + * + *

This method continually attempts to acquire a write lock on the bucket corresponding to the key using a busy-wait loop. + * Once the lock is acquired, if the key exists, it applies the provided mapping function to compute and update the value associated with the key. + * + * @param key the key whose associated value is to be computed + * @param mappingFunction a function that takes the key and its current value and returns the new value + * @return the new value associated with the specified key, or {@code null} if the key was not present + */ @Override public V computeIfPresent (long key, BiFunction mappingFunction) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongFloatMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongFloatMap.java index 8809d30..effb87d 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongFloatMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongFloatMap.java @@ -13,6 +13,18 @@ public class ConcurrentLongFloatMap extends PrimitiveConcurrentMap { protected final Long2FloatOpenHashMap[] maps; protected final float defaultValue; + /** + * Constructs a new ConcurrentLongFloatMap with the specified number of buckets and configuration parameters. + * + *

This constructor partitions the map into multiple buckets to improve concurrency. Each bucket is + * initialized as a Long2FloatOpenHashMap with the specified initial capacity and load factor. The provided + * default value is used as the fallback when a key is not present in the map.

+ * + * @param numBuckets the number of buckets for partitioning the map + * @param initialCapacity the initial capacity for each bucket + * @param loadFactor the load factor for resizing the bucket maps + * @param defaultValue the default value returned for absent keys + */ public ConcurrentLongFloatMap ( int numBuckets, int initialCapacity, @@ -26,13 +38,33 @@ public ConcurrentLongFloatMap ( maps[i] = new Long2FloatOpenHashMap(initialCapacity, loadFactor); } - public float getDefaultValue (){ return defaultValue; } - + /** + * Returns the default value used when a key is not present in the map. + * + * @return the default float value for absent keys + */ +public float getDefaultValue (){ return defaultValue; } + + /** + * Returns the internal bucket map corresponding to the specified index. + * + * @param index the index of the bucket in the internal maps array + * @return the map associated with the given bucket index + */ @Override protected Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains a mapping for the specified key. + * + *

This method calculates the appropriate bucket for the key, acquires a read lock on that bucket, + * and then verifies if the key exists in the corresponding sub-map in a thread-safe manner. + * + * @param key the key to check for presence in the map + * @return {@code true} if the key exists in the map; {@code false} otherwise + */ public boolean containsKey(long key) { int bucket = getBucket(key); @@ -45,6 +77,15 @@ public boolean containsKey(long key) { } } + /** + * Retrieves the float value associated with the specified key. + * + *

This method identifies the corresponding bucket for the key, locks it for thread-safe access, and + * returns the associated value if present. If the key is not found, it returns the default value. + * + * @param key the key whose associated value is to be returned + * @return the value associated with the key, or the default value if the key is absent + */ public float get(long key) { int bucket = getBucket(key); @@ -57,6 +98,16 @@ public float get(long key) { } } + /** + * Inserts or updates the float value associated with the specified key in a thread-safe manner. + * + *

This method acquires a write lock on the bucket determined by the key, updates the mapping, + * and returns the previous value associated with the key, or the default value if the key was absent.

+ * + * @param key the key for which the value is to be inserted or updated + * @param value the new float value to associate with the key + * @return the previous value mapped to the key, or the default value if no mapping existed + */ public float put(long key, float value) { int bucket = getBucket(key); @@ -69,6 +120,15 @@ public float put(long key, float value) { } } + /** + * Removes the mapping for the specified key from this map. + * + *

This method locates the bucket corresponding to the key, acquires the write lock to ensure thread safety, + * and removes the associated value. If the key is not present, the default value is returned. + * + * @param key the key whose mapping is to be removed + * @return the previous value associated with the key, or the default value if no mapping existed + */ public float remove(long key) { int bucket = getBucket(key); @@ -81,6 +141,17 @@ public float remove(long key) { } } + /** + * Conditionally removes the mapping for the specified key if it is currently associated with the given value. + * + *

The method acquires a write lock on the bucket corresponding to the key to ensure a thread-safe removal. + * If the key is mapped to the provided value, the mapping is removed and the method returns true; + * otherwise, the map remains unchanged and the method returns false.

+ * + * @param key the key whose mapping is to be conditionally removed + * @param value the value expected to be associated with the key + * @return true if the mapping existed and was removed, false otherwise + */ public boolean remove(long key, float value) { int bucket = getBucket(key); @@ -93,6 +164,17 @@ public boolean remove(long key, float value) { } } + /** + * Atomically computes and returns the value associated with the given key if absent. + * + *

If the key is not already present in the map, the provided mapping function is applied + * to compute a new value, which is then stored and returned. If the key is already mapped, + * its existing value is returned.

+ * + * @param key the key for which a value is to be computed if absent + * @param mappingFunction the function to compute a value for the given key if absent + * @return the current value associated with the key, either existing or computed + */ public float computeIfAbsent(long key, Long2FloatFunction mappingFunction) { int bucket = getBucket(key); @@ -105,6 +187,19 @@ public float computeIfAbsent(long key, Long2FloatFunction mappingFunction) { } } + /** + * Computes a new value for the specified key if it is present in the map. + * + *

This method acquires a write lock on the bucket corresponding to the key, ensuring thread-safe updates. + * If the key exists, the provided {@code mappingFunction} is applied to the current key-value pair. If the + * function returns a non-null value, the map is updated with this new value; if it returns {@code null}, the key + * is removed from the map.

+ * + * @param key the key for which the value is to be computed if present + * @param mappingFunction a function that takes the key and its current value and returns a new value (or {@code null} + * to remove the entry) + * @return the new value associated with the key, or the default value if the key is not present or has been removed + */ public float computeIfPresent(int key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -117,6 +212,16 @@ public float computeIfPresent(int key, BiFunction mappingFun } } + /** + * Creates a new builder for constructing instances of ConcurrentLongFloatMap. + * + *

The returned builder supports configuration of map parameters such as the number of buckets, + * initial capacity, load factor, and default value. Depending on the configured map mode, the builder + * constructs either a busy-waiting variant (ConcurrentBusyWaitingLongFloatMap) or a blocking variant + * (ConcurrentLongFloatMap). If no default value is provided, it defaults to 0.

+ * + * @return a builder for configuring and creating ConcurrentLongFloatMap instances + */ public static PrimitiveMapBuilder newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongIntMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongIntMap.java index 31ec48b..d0181c6 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongIntMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongIntMap.java @@ -13,6 +13,17 @@ public class ConcurrentLongIntMap extends PrimitiveConcurrentMap { protected final Long2IntOpenHashMap[] maps; protected final int defaultValue; + /** + * Constructs a ConcurrentLongIntMap with the specified configuration. + * + *

This constructor partitions the map into a fixed number of buckets, where each bucket is a Long2IntOpenHashMap + * initialized with the given capacity and load factor. The provided default value is used to represent absent keys.

+ * + * @param numBuckets the number of buckets to partition the map for concurrent access + * @param initialCapacity the initial capacity for each underlying hash map + * @param loadFactor the load factor used to determine resizing thresholds for each bucket + * @param defaultValue the default value returned when a key is not present in the map + */ public ConcurrentLongIntMap ( int numBuckets, int initialCapacity, @@ -26,11 +37,29 @@ public ConcurrentLongIntMap ( maps[i] = new Long2IntOpenHashMap(initialCapacity, loadFactor); } + /** + * Returns the mapping function for the bucket at the specified index. + * + *

This method provides access to the underlying map for a given bucket, allowing retrieval + * of integer values associated with long keys.

+ * + * @param index the index of the bucket whose mapping function is to be returned + * @return a function mapping long keys to their corresponding integer values in the specified bucket + */ @Override protected Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains the specified key. + * + *

This method determines the appropriate bucket for the given key, acquires a read lock to ensure thread safety, + * and verifies if the key exists in that bucket.

+ * + * @param key the key to be checked for presence in the map + * @return {@code true} if the key exists in the map, {@code false} otherwise + */ public boolean containsKey(long key) { int bucket = getBucket(key); @@ -43,6 +72,16 @@ public boolean containsKey(long key) { } } + /** + * Retrieves the value associated with the specified key in a thread-safe manner. + *

+ * This method determines the appropriate bucket for the key, acquires a read lock on that bucket, + * and then returns the corresponding integer value. If the key is not present in the map, the default value is returned. + *

+ * + * @param key the key whose associated value is to be retrieved + * @return the integer value mapped to the key, or the default value if the key does not exist + */ public int get(long key) { int bucket = getBucket(key); @@ -55,6 +94,16 @@ public int get(long key) { } } + /** + * Inserts or updates the value for the specified key and returns the previous value. + * + *

This method acquires the write lock for the bucket corresponding to the key to ensure thread safety. + * If the key was already present, the method returns the previous value; otherwise, it returns the default value. + * + * @param key the key for the value to be inserted or updated + * @param value the value to be associated with the key + * @return the previous value associated with the key, or the default value if the key was not present + */ public int put(long key, int value) { int bucket = getBucket(key); @@ -67,8 +116,22 @@ public int put(long key, int value) { } } - public int getDefaultValue (){ return defaultValue; } - + /** + * Retrieves the default integer value used when a key is not found in the map. + * + * @return the default value configured for missing keys. + */ +public int getDefaultValue (){ return defaultValue; } + + /** + * Removes the mapping for the specified key from the map. + * + *

This method determines the bucket corresponding to the given key, acquires an exclusive write lock on that bucket, + * and removes the mapping if it exists. It returns the value that was associated with the key, or the default value if no mapping was found.

+ * + * @param key the key whose mapping is to be removed + * @return the previous value associated with the key, or the default value if the key was not present + */ public int remove(long key) { int bucket = getBucket(key); @@ -81,6 +144,16 @@ public int remove(long key) { } } + /** + * Conditionally removes the mapping for a key if it is currently associated with the specified value. + * + *

This method acquires a write lock on the bucket corresponding to the key to ensure thread safety. + * It only removes the entry if the current mapping matches the given value.

+ * + * @param key the key whose mapping is to be removed + * @param value the expected value associated with the key + * @return {@code true} if the mapping was removed, {@code false} otherwise + */ public boolean remove(long key, int value) { int bucket = getBucket(key); @@ -93,6 +166,17 @@ public boolean remove(long key, int value) { } } + /** + * Atomically computes and associates a value for the specified key if it is absent. + *

+ * If the key is not already mapped, this method applies the provided mapping function to + * compute a new value, inserts it into the map, and returns the computed value. If the key + * is already mapped, the existing value is returned. + * + * @param key the key for which the value is to be computed + * @param mappingFunction the function used to compute a value from the key if absent + * @return the current (existing or computed) value associated with the key + */ public int computeIfAbsent(long key, Long2IntFunction mappingFunction) { int bucket = getBucket(key); @@ -105,6 +189,19 @@ public int computeIfAbsent(long key, Long2IntFunction mappingFunction) { } } + /** + * Computes a new value for the specified key if it is currently mapped to a value. + * + *

This method determines the appropriate bucket for the given key and acquires its write lock + * to ensure thread safety. It then applies the provided mapping function to the key and its existing + * value. If the mapping function returns a non-null result, the key is updated with the new value; + * if it returns {@code null}, the key is removed from the map.

+ * + * @param key the key whose mapping is to be computed + * @param mappingFunction a function that takes the key and its current value to compute a new value; + * a {@code null} return value indicates removal of the key + * @return the new value associated with the key, or the default value if the key was absent or removed + */ public int computeIfPresent(long key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -117,6 +214,16 @@ public int computeIfPresent(long key, BiFunction mapping } } + /** + * Returns a new builder for constructing {@code ConcurrentLongIntMap} instances. + * + *

This builder facilitates configuration of parameters such as bucket count, initial capacity, load factor, and + * default value. The {@code build()} method creates a new map instance based on the builder’s map mode: it returns a + * {@code ConcurrentBusyWaitingLongIntMap} for busy waiting mode or a {@code ConcurrentLongIntMap} for blocking mode. + * If no default value is provided, it defaults to 0.

+ * + * @return a builder for instantiating {@code ConcurrentLongIntMap} instances + */ public static PrimitiveMapBuilder newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongLongMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongLongMap.java index afbfd9d..7b36c9b 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongLongMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongLongMap.java @@ -13,6 +13,17 @@ public class ConcurrentLongLongMap extends PrimitiveConcurrentMap { protected final Long2LongOpenHashMap[] maps; protected final long defaultValue; + /** + * Constructs a new ConcurrentLongLongMap with the specified number of buckets, initial capacity, load factor, and default value. + * + *

Each bucket is backed by a Long2LongOpenHashMap created with the provided initial capacity and load factor. + * The default value is returned when a key is not present in the map. + * + * @param numBuckets the number of buckets used to partition the map + * @param initialCapacity the initial capacity for each bucket's hash map + * @param loadFactor the load factor for each bucket's hash map + * @param defaultValue the value returned if a key is not found in the map + */ public ConcurrentLongLongMap( int numBuckets, int initialCapacity, @@ -26,11 +37,25 @@ public ConcurrentLongLongMap( maps[i] = new Long2LongOpenHashMap(initialCapacity, loadFactor); } + /** + * Retrieves the map corresponding to the specified bucket index. + * + * @param index the index of the bucket to access + * @return the map function representing the bucket at the given index + */ @Override protected final Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains the specified key. + * + *

This method performs a thread-safe lookup by acquiring a read lock on the bucket corresponding to the given key. + * + * @param key the key to check + * @return {@code true} if the key is present, {@code false} otherwise + */ public boolean containsKey(long key) { int bucket = getBucket(key); @@ -43,6 +68,15 @@ public boolean containsKey(long key) { } } + /** + * Retrieves the value associated with the specified key. + * + *

This method determines the appropriate bucket for the given key, acquires a read lock for thread safety, + * and returns the corresponding value. If the key is not present in the map, the default value is returned. + * + * @param key the key whose associated value is to be returned + * @return the value associated with the specified key, or the default value if the key is absent + */ public long get (long key) { int bucket = getBucket(key); @@ -55,6 +89,16 @@ public long get (long key) { } } + /** + * Inserts or updates the mapping for the specified key with the given value in a thread-safe manner. + * + *

This method identifies the target bucket based on the key, acquires its write lock, and then performs the update. + * It returns the previous value associated with the key, or the map's default value if no mapping existed.

+ * + * @param key the key to be inserted or updated in the map + * @param value the new value to associate with the key + * @return the previous value associated with the key, or the default value if no prior mapping existed + */ public long put(long key, long value) { int bucket = getBucket(key); @@ -67,8 +111,21 @@ public long put(long key, long value) { } } - public long getDefaultValue (){ return defaultValue; } - + /** + * Returns the default value used in the map when a key is not present. + * + * @return the default value associated with the map + */ +public long getDefaultValue (){ return defaultValue; } + + /** + * Removes the mapping for the specified key from this map and returns the previously associated value. + * + *

This method acquires a write lock on the bucket corresponding to the key to ensure thread-safe removal.

+ * + * @param key the key whose mapping is to be removed + * @return the value previously associated with the key, or the map's default value if no mapping was found + */ public long remove(long key) { int bucket = getBucket(key); @@ -81,6 +138,15 @@ public long remove(long key) { } } + /** + * Removes the entry for the specified key only if it is currently associated with the given value. + * + *

This method checks the mapping of the provided key and removes it if the associated value matches the specified value, ensuring thread-safe removal.

+ * + * @param key the key whose mapping is to be conditionally removed + * @param value the value expected to be associated with the key for successful removal + * @return {@code true} if the mapping was removed, {@code false} otherwise + */ public boolean remove(long key, long value) { int bucket = getBucket(key); @@ -93,6 +159,17 @@ public boolean remove(long key, long value) { } } + /** + * Computes and associates a value with the specified key if it is not already present. + * + *

This method retrieves the appropriate bucket for the given key and locks it for exclusive write access. + * If the key is absent, it computes the value using the provided mapping function, stores the computed value, + * and returns it. If the key is already mapped, the current value is returned. + * + * @param key the key for which the value is to be computed if absent + * @param mappingFunction the function to compute a value for the key if absent + * @return the existing or computed value associated with the key + */ public long computeIfAbsent(long key, Long2LongFunction mappingFunction) { int bucket = getBucket(key); @@ -105,6 +182,17 @@ public long computeIfAbsent(long key, Long2LongFunction mappingFunction) { } } + /** + * Atomically updates the value for the specified key if it is present. + * + *

If the key exists, the provided remapping function is applied to its current value to compute a new + * value, which is then stored and returned. If the key is not present, the mapping function is not invoked + * and the map’s default value is returned. + * + * @param key the key for which the value should be updated if present + * @param mappingFunction the function that computes a new value given the key and its current value + * @return the new value associated with the key if present, or the default value otherwise + */ public long computeIfPresent(long key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -117,6 +205,16 @@ public long computeIfPresent(long key, BiFunction mappingFunct } } + /** + * Creates a new builder for constructing {@link ConcurrentLongLongMap} instances. + * + *

The returned builder allows configuration of parameters such as bucket count, + * initial capacity, load factor, and default value. Depending on the map mode set in the builder, + * the {@code build()} method will instantiate either a {@link ConcurrentBusyWaitingLongLongMap} + * (for busy waiting) or a {@link ConcurrentLongLongMap} (for blocking) with the specified configuration. + * + * @return a {@link PrimitiveMapBuilder} configured for building {@link ConcurrentLongLongMap} instances + */ public static PrimitiveMapBuilder newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongObjectMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongObjectMap.java index 9f5180a..6808918 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongObjectMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/longkey/ConcurrentLongObjectMap.java @@ -13,6 +13,18 @@ public class ConcurrentLongObjectMap extends PrimitiveConcurrentMap { protected final Long2ObjectOpenHashMap[] maps; protected final V defaultValue; + /** + * Constructs a new ConcurrentLongObjectMap with the specified bucket configuration and default value. + * + *

This constructor initializes the map by creating the specified number of internal buckets, + * each as a Long2ObjectOpenHashMap configured with the given initial capacity and load factor. + * The provided default value is returned when a key is not mapped to any value.

+ * + * @param numBuckets the number of buckets used to segment the map for concurrent access + * @param initialCapacity the initial capacity for each internal hash map bucket + * @param loadFactor the load factor that determines the resizing threshold for each bucket + * @param defaultValue the default value to return for keys that are not present in the map + */ @SuppressWarnings("unchecked") public ConcurrentLongObjectMap ( int numBuckets, @@ -27,11 +39,30 @@ public ConcurrentLongObjectMap ( maps[i] = new Long2ObjectOpenHashMap<>(initialCapacity, loadFactor); } + /** + * Returns the mapping function for the bucket at the specified index. + * + *

This method provides access to the internal map responsible for managing key-value pairs + * for a given bucket within the concurrent map. The returned function serves as the bucket's + * lookup mechanism for long keys. + * + * @param index the index of the bucket + * @return the mapping function associated with the specified bucket index + */ @Override protected final Function mapAt (int index) { return maps[index]; } + /** + * Checks whether the map contains the specified key. + * + *

This method performs a thread-safe lookup by acquiring a read lock on the bucket corresponding + * to the provided key. + * + * @param key the key to check for presence in the map + * @return {@code true} if the key exists in the map; {@code false} otherwise + */ public boolean containsKey(long key) { int bucket = getBucket(key); @@ -44,6 +75,14 @@ public boolean containsKey(long key) { } } + /** + * Retrieves the value associated with the specified key, or returns the default value if the key is not present. + * + *

This method provides thread-safe access by employing a read lock on the bucket corresponding to the key. + * + * @param key the key whose associated value is to be returned + * @return the value mapped to the key, or the map's default value if the key is absent + */ public V get (long key) { int bucket = getBucket(key); @@ -56,6 +95,16 @@ public V get (long key) { } } + /** + * Inserts or updates the mapping for the specified key with the given value. + * + *

This operation is thread-safe, as it acquires the write lock on the relevant bucket + * before updating the map.

+ * + * @param key the key to insert or update + * @param value the value to be associated with the key + * @return the previous value associated with the key, or {@code null} if there was no mapping + */ public V put (long key, V value) { int bucket = getBucket(key); @@ -68,8 +117,22 @@ public V put (long key, V value) { } } - public V getDefaultValue (){ return defaultValue; } - + /** + * Returns the default value assigned to keys that are not present in the map. + * + * @return the default value + */ +public V getDefaultValue (){ return defaultValue; } + + /** + * Removes the mapping for the specified key from the map. + *

+ * This operation is thread-safe, acquiring a write lock on the corresponding bucket. + *

+ * + * @param key the key whose mapping is to be removed + * @return the previous value associated with the key, or {@code null} if there was no mapping + */ public V remove (long key) { int bucket = getBucket(key); @@ -82,6 +145,16 @@ public V remove (long key) { } } + /** + * Removes the entry for the specified key only if it is currently mapped to the given value. + * + *

This method acquires a write lock on the corresponding bucket to ensure thread safety, and it removes the entry + * only when the current mapped value exactly matches the provided value.

+ * + * @param key the key whose mapping is to be conditionally removed + * @param value the value expected to be associated with the key; removal occurs only if this value matches the current mapping + * @return {@code true} if the mapping was removed, or {@code false} if the key was absent or its value did not match + */ public boolean remove(long key, V value) { int bucket = getBucket(key); @@ -94,6 +167,17 @@ public boolean remove(long key, V value) { } } + /** + * Computes a value for the specified key if it is not already present. + *

+ * If the key is absent, the provided mapping function is applied to compute a value, + * which is then stored and returned. If the key already exists, its current value is returned. + * This operation is performed under a write lock to ensure thread safety. + * + * @param key the key for which a value is to be computed if absent + * @param mappingFunction the function to compute a value for the key + * @return the current (existing or computed) value associated with the key + */ public V computeIfAbsent (long key, Long2ObjectFunction mappingFunction) { int bucket = getBucket(key); @@ -106,6 +190,18 @@ public V computeIfAbsent (long key, Long2ObjectFunction mappingFunction) { } } + /** + * If a mapping for the specified key exists, computes a new mapping using the provided + * function and updates the entry with the new value. + * + *

The operation is performed under a write lock for thread safety. If the mapping + * function returns {@code null}, the mapping is removed. + * + * @param key the key for which the mapping is to be computed + * @param mappingFunction a function that accepts the current key and value, and returns + * a new value (or {@code null} to remove the mapping) + * @return the new value associated with the key, or {@code null} if the entry was removed + */ public V computeIfPresent (long key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -118,6 +214,16 @@ public V computeIfPresent (long key, BiFunction mappingFunction) { } } + /** + * Creates a new builder for constructing a concurrent long-to-object map. + * + *

This builder enables configuration of the map's parameters. When the {@code build()} method + * is invoked, the builder creates an instance of either a busy waiting or a blocking + * concurrent map implementation based on the configured map mode.

+ * + * @param the type of values maintained by the map + * @return a builder for constructing a concurrent long-to-object map + */ public static PrimitiveMapBuilder,V> newBuilder () { return new PrimitiveMapBuilder<>(){ @Override diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentBusyWaitingObjectLongMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentBusyWaitingObjectLongMap.java index 7813157..9435f49 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentBusyWaitingObjectLongMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentBusyWaitingObjectLongMap.java @@ -6,10 +6,32 @@ import java.util.function.BiFunction; public class ConcurrentBusyWaitingObjectLongMap extends ConcurrentObjectLongMap { + /** + * Constructs a new ConcurrentBusyWaitingObjectLongMap with the specified configuration. + * + *

This constructor initializes the map with a fixed number of buckets for concurrent access, + * an initial capacity, a load factor to determine resizing thresholds, and a default value to return + * when a key is not present. + * + * @param numBuckets the number of buckets used for partitioning the map + * @param initialCapacity the initial capacity of the map + * @param loadFactor the load factor threshold for resizing the map + * @param defaultValue the default value to return for absent keys + */ public ConcurrentBusyWaitingObjectLongMap (int numBuckets, int initialCapacity, float loadFactor, long defaultValue) { super(numBuckets, initialCapacity, loadFactor, defaultValue); } + /** + * Checks if the map contains the specified key. + * + *

This method identifies the bucket corresponding to the given key and continuously + * attempts to acquire its read lock using busy waiting. Once the lock is acquired, it + * checks whether the underlying map for that bucket contains the key. + * + * @param key the key to check for presence in the map + * @return {@code true} if the key is present, {@code false} otherwise + */ @Override public boolean containsKey (K key) { int bucket = getBucket(key); @@ -28,6 +50,17 @@ public boolean containsKey (K key) { } } + /** + * Retrieves the value associated with the specified key. + * + *

+ * This method attempts to acquire a read lock on the bucket corresponding to the key using busy waiting. + * If the key is not found, the default value is returned. + *

+ * + * @param key the key whose associated value is to be returned + * @return the value associated with the key, or the default value if the key is not present + */ @Override public long get (K key) { int bucket = getBucket(key); @@ -46,6 +79,17 @@ public long get (K key) { } } + /** + * Inserts or updates the specified key with the given value. + * + *

This method uses busy waiting to acquire a write lock on the bucket corresponding to the key, + * ensuring thread-safe update operations. Once the lock is obtained, the value for the key is updated, + * and the previous value (or the default value if no mapping existed) is returned. + * + * @param key the key to insert or update + * @param value the value to associate with the key + * @return the previous value associated with the key, or the default value if none was present + */ @Override public long put (K key, long value) { int bucket = getBucket(key); @@ -64,6 +108,16 @@ public long put (K key, long value) { } } + /** + * Removes the entry for the specified key from the map and returns the associated value. + * + *

This method repeatedly attempts to acquire the write lock for the bucket corresponding + * to the given key using busy waiting. Once the lock is acquired, it removes the key's entry + * from the underlying map. + * + * @param key the key for which the mapping is to be removed + * @return the value previously associated with the specified key, or the default value if no mapping existed + */ @Override public long remove (K key) { int bucket = getBucket(key); @@ -82,6 +136,17 @@ public long remove (K key) { } } + /** + * Removes the mapping for the specified key only if it is currently associated with the given value. + * + *

This method busy-waits to acquire a write lock on the bucket corresponding to the key. + * Once the lock is obtained, it conditionally removes the entry from the underlying map. + *

+ * + * @param key the key whose mapping is to be considered for removal + * @param value the expected value associated with the key for removal to occur + * @return {@code true} if the mapping was successfully removed, {@code false} otherwise + */ @Override public boolean remove (K key, long value) { int bucket = getBucket(key); @@ -100,6 +165,16 @@ public boolean remove (K key, long value) { } } + /** + * Computes and returns the value associated with the specified key, computing it with the provided mapping function if absent. + *

+ * This method busy-waits until a write lock for the key’s bucket is acquired. If the key is not present, the mapping function is + * applied to compute its value, which is then stored and returned. + * + * @param key the key for which the value is to be computed if absent + * @param mappingFunction the function to compute the value if the key is not already associated with one + * @return the existing or newly computed value associated with the key + */ @Override public long computeIfAbsent (K key, Object2LongFunction mappingFunction) { int bucket = getBucket(key); @@ -118,6 +193,19 @@ public long computeIfAbsent (K key, Object2LongFunction mappingFunction) { } } + /** + * Computes and updates the value for the specified key if it is present. + * + *

+ * This method busy-waits to acquire a write lock on the bucket associated with the key to ensure thread-safe updates. + * If the key is present, the provided mapping function is applied to compute a new value, which then replaces the existing value. + * If the key is not present, the map returns its default value. + *

+ * + * @param key the key to update, if present in the map + * @param mappingFunction a function that computes a new value from the key and its current value + * @return the new value associated with the key if it was present; otherwise, the default value + */ @Override public long computeIfPresent (K key, BiFunction mappingFunction) { int bucket = getBucket(key); diff --git a/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentObjectLongMap.java b/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentObjectLongMap.java index f20120e..c835ca4 100644 --- a/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentObjectLongMap.java +++ b/src/main/java/com/trivago/fastutilconcurrentwrapper/objkey/ConcurrentObjectLongMap.java @@ -13,6 +13,18 @@ public class ConcurrentObjectLongMap extends PrimitiveConcurrentMap { protected final Object2LongOpenHashMap[] maps; protected final long defaultValue; + /** + * Initializes a new ConcurrentObjectLongMap with the specified parameters. + * + *

This constructor creates a concurrent map that divides its data into a set number of buckets, + * each backed by an Object2LongOpenHashMap. The specified initial capacity and load factor configure + * each bucket's underlying map, while the default value is returned for keys that are not present.

+ * + * @param numBuckets the number of buckets to partition the map into + * @param initialCapacity the initial capacity for each bucket's map + * @param loadFactor the load factor for each bucket's map + * @param defaultValue the default value returned for keys that do not exist in the map + */ @SuppressWarnings("unchecked") public ConcurrentObjectLongMap ( int numBuckets, @@ -27,11 +39,26 @@ public ConcurrentObjectLongMap ( maps[i] = new Object2LongOpenHashMap<>(initialCapacity, loadFactor); } + /** + * Retrieves the bucket-specific map function at the given index. + * + * @param index the index of the bucket to access + * @return the function mapping keys of type {@code K} to their corresponding long values in the bucket + */ @Override protected final Function mapAt (int index) { return maps[index]; } + /** + * Checks if the map contains a mapping for the specified key. + * + *

This method acquires the read lock on the corresponding bucket to ensure thread-safe access when determining + * whether the key is present in the map.

+ * + * @param key the key whose presence is to be tested + * @return {@code true} if a mapping for the specified key exists, {@code false} otherwise + */ public boolean containsKey(K key) { int bucket = getBucket(key); @@ -44,6 +71,15 @@ public boolean containsKey(K key) { } } + /** + * Retrieves the value associated with the specified key from the map. + * + *

If the key is not present, the default value is returned. This method ensures thread-safe access by acquiring + * the read lock on the bucket corresponding to the key. + * + * @param key the key whose associated value is to be returned + * @return the value associated with the key, or the default value if no mapping exists + */ public long get (K key) { int bucket = getBucket(key); @@ -56,6 +92,18 @@ public long get (K key) { } } + /** + * Associates the specified long value with the specified key in the map. + * + *

+ * Acquires a write lock on the bucket corresponding to the key to ensure thread safety and returns + * the previous value associated with the key, or the default value if no prior mapping existed. + *

+ * + * @param key the key to be associated with the given value + * @param value the value to associate with the key + * @return the previous value associated with the key, or the default value if there was no mapping + */ public long put (K key, long value) { int bucket = getBucket(key); @@ -68,8 +116,23 @@ public long put (K key, long value) { } } - public long getDefaultValue (){ return defaultValue; } - + /** + * Returns the default value used for keys that are not present in the map. + * + * This value is set during the construction of the map and is returned whenever a queried key does not exist. + * + * @return the default value + */ +public long getDefaultValue (){ return defaultValue; } + + /** + * Removes the mapping for the specified key from this map. + * + *

This method acquires a write lock on the bucket corresponding to the key to ensure thread-safe removal. + * + * @param key the key whose mapping is to be removed + * @return the value previously associated with the key, or the default value if the key was not present + */ public long remove (K key) { int bucket = getBucket(key); @@ -82,6 +145,17 @@ public long remove (K key) { } } + /** + * Removes the mapping for the specified key only if it is currently associated with the provided value. + * + *

This method acquires a write lock on the bucket containing the key to ensure thread safety. + * If the current value mapped to the key matches the given value, the entry is removed and {@code true} + * is returned; otherwise, the map remains unchanged and {@code false} is returned. + * + * @param key the key whose mapping is to be conditionally removed + * @param value the expected value associated with the key + * @return {@code true} if the key-value pair was successfully removed, otherwise {@code false} + */ public boolean remove (K key, long value) { int bucket = getBucket(key); @@ -94,6 +168,17 @@ public boolean remove (K key, long value) { } } + /** + * Computes a value for the specified key if it is not already associated with one. + * + *

This method acquires a write lock on the corresponding bucket to ensure thread safety. + * If no value exists for the key, the provided mapping function is used to compute and store a new value. + * The current (existing or computed) value is then returned.

+ * + * @param key the key for which a value should be computed if absent + * @param mappingFunction the function that computes a value for the key if it is not present + * @return the current value associated with the specified key, either preexisting or computed + */ public long computeIfAbsent (K key, Object2LongFunction mappingFunction) { int bucket = getBucket(key); @@ -106,6 +191,17 @@ public long computeIfAbsent (K key, Object2LongFunction mappingFunction) { } } + /** + * Computes a new value for the specified key if it is already present in the map. + * + *

If the key exists, the provided mapping function is applied to the key and its current value to compute a new value, + * which then replaces the old value. This method acquires a write lock on the corresponding bucket to ensure thread safety. + * If the key is not present, the mapping function is not invoked and the map remains unchanged.

+ * + * @param key the key for which to compute a new value if present + * @param mappingFunction a function that takes the key and its current value, and computes a new value + * @return the updated value associated with the key after computation, or the default value if the key is not present + */ public long computeIfPresent (K key, BiFunction mappingFunction) { int bucket = getBucket(key); @@ -118,6 +214,16 @@ public long computeIfPresent (K key, BiFunction mappingFunction) { } } + /** + * Returns a new builder for configuring and constructing instances of {@link ConcurrentObjectLongMap}. + * + *

The returned builder supports different concurrency modes. When the map mode is set to + * {@code BUSY_WAITING}, the builder produces an instance of {@link ConcurrentBusyWaitingObjectLongMap}; + * when set to {@code BLOCKING}, it produces a standard {@link ConcurrentObjectLongMap}.

+ * + * @param the type of keys maintained by the map + * @return a new {@link PrimitiveMapBuilder} for building a {@link ConcurrentObjectLongMap} + */ public static PrimitiveMapBuilder,Long> newBuilder () { return new PrimitiveMapBuilder<>(){ @Override