diff --git a/nb-virtdata/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/Map.java b/nb-virtdata/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/Map.java index fc1a83ebe..87dc19420 100644 --- a/nb-virtdata/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/Map.java +++ b/nb-virtdata/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/Map.java @@ -18,6 +18,7 @@ package io.nosqlbench.virtdata.library.basics.shared.from_long.to_collection; import io.nosqlbench.virtdata.api.annotations.*; +import java.util.Arrays; import java.util.HashMap; import java.util.function.LongFunction; import java.util.function.LongToIntFunction; @@ -61,12 +62,23 @@ public class Map implements LongFunction> { "create a map of size 2, with a specific function for each key and each value"}) @SafeVarargs public Map(LongFunction... objfuncs) { - this.mode = Mode.Tuples; if ((objfuncs.length%2)!=0) { - throw new RuntimeException("An even number of functions must be provided."); + Object testValue = objfuncs[0].apply(0L); + if (testValue instanceof Number n) { + LongFunction[] finalObjfuncs = objfuncs; + this.sizeFunc= l -> ((Number) finalObjfuncs[0].apply(l)).intValue(); + objfuncs = Arrays.copyOfRange(objfuncs, 1, objfuncs.length); + this.mode=Mode.VarSized; + } else { + throw new RuntimeException("An even number of functions must be provided, unless " + + "the first one produces a numeric value."); + } + } else { + this.mode = Mode.Tuples; + int size = objfuncs.length/2; + sizeFunc=(l) -> size; } int size = objfuncs.length / 2; - sizeFunc=(l) -> size; keyFuncs = new LongFunction[size]; valueFuncs = new LongFunction[size]; for (int i = 0; i < size; i++) { diff --git a/nb-virtdata/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/MapTest.java b/nb-virtdata/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/MapTest.java index 472d1c807..d3c6c3cd8 100644 --- a/nb-virtdata/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/MapTest.java +++ b/nb-virtdata/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_collection/MapTest.java @@ -16,9 +16,14 @@ package io.nosqlbench.virtdata.library.basics.shared.from_long.to_collection; +import org.joda.time.DateTime; import org.junit.jupiter.api.Test; +import java.time.Instant; +import java.util.function.LongFunction; + import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class MapTest { @@ -32,26 +37,47 @@ public class MapTest { @Test public void testStringMap() { - StringMap sm = new StringMap((s)->2,(k)->k,(v)->v); + StringMap sm = new StringMap((s) -> 2, (k) -> k, (v) -> v); java.util.Map m2 = sm.apply(11L); - assertThat(m2).containsOnlyKeys("11","12"); - assertThat(m2).containsValues("11","12"); + assertThat(m2).containsOnlyKeys("11", "12"); + assertThat(m2).containsValues("11", "12"); } @Test public void testMapTuple() { - Map mf = new Map(s1 -> (int) s1, k2 -> (int) k2, s2 -> (int) s2, k2 -> (int)k2); + Map mf = new Map(s1 -> (int) s1, k2 -> (int) k2, s2 -> (int) s2, k2 -> (int) k2); java.util.Map mt = mf.apply(37L); - assertThat(mt).containsOnlyKeys(37,38); - assertThat(mt).containsValues(37,38); + assertThat(mt).containsOnlyKeys(37, 38); + assertThat(mt).containsValues(37, 38); } @Test public void testStringMapTuple() { - StringMap mf = new StringMap(s1 -> (int) s1, k2 -> (int) k2, s2 -> (int) s2, k2 -> (int)k2); + StringMap mf = + new StringMap(s1 -> (int) s1, k2 -> (int) k2, s2 -> (int) s2, k2 -> (int) k2); java.util.Map mt = mf.apply(37L); - assertThat(mt).containsOnlyKeys("37","38"); - assertThat(mt).containsValues("37","38"); + assertThat(mt).containsOnlyKeys("37", "38"); + assertThat(mt).containsValues("37", "38"); + } + + @Test + public void testLongFunctionsOnlyWithOddArity() { + LongFunction sizeFunc = l -> (double) (l % 5); + LongFunction keyfunc = String::valueOf; + LongFunction valueFunc = String::valueOf; + Map map = new Map(sizeFunc, keyfunc, valueFunc); + java.util.Map apply = map.apply(3L); + assertThat(apply).isEqualTo(java.util.Map.of("3", "3", "4", "4", "5", "5")); + } + + @Test + public void testLongFunctionsOnlyWithInvalidSizer() { + LongFunction sizeFunc = l -> Instant.ofEpochMilli(1L); + LongFunction keyfunc = String::valueOf; + LongFunction valueFunc = String::valueOf; + assertThatThrownBy(() -> new Map(sizeFunc, keyfunc, valueFunc)).hasMessageContaining("An " + + + "even number of functions must be provided, unless the first one produces a numeric value"); } }