implements Cloneable {
return eventListener;
}
+ /**
+ * Specifies the value to be put for each key queried in {@link ChronicleMap#get get()} and
+ * {@link ChronicleMap#getUsing(Object, Object) getUsing()} methods, if the key is absent
+ * in the map. Then this default value is returned from query method.
+ *
+ * Setting default value to {@code null} is interpreted as map shouldn't put any default
+ * value for absent keys. This is by default.
+ *
+ *
This configuration overrides any previous
+ * {@link #defaultValueProvider(DefaultValueProvider)} configuration to this
+ * {@code ChronicleMapBuilder}.
+ *
+ * @param defaultValue the default value to be put to the map for absent keys during
+ * {@code get()} and {@code getUsing()} calls and returned from these calls
+ * @return this builder object back
+ */
+ public ChronicleMapBuilder defaultValue(V defaultValue) {
+ this.defaultValue = defaultValue;
+ this.defaultValueProvider = null;
+ return this;
+ }
+
+ /**
+ * Specifies the function to obtain a value for the key during {@link ChronicleMap#get get()}
+ * and {@link ChronicleMap#getUsing(Object, Object) getUsing()} calls, if the key is absent
+ * in the map. If the obtained value is non-null, it is put for the key in the map and then
+ * returned from current {@code get()} or {@code getUsing()} call.
+ *
+ * This configuration overrides any previous {@link #defaultValue(Object)} configuration
+ * to this {@code ChronicleMapBuilder}.
+ *
+ * @param defaultValueProvider the strategy to obtain a default value by the absent key
+ * @return this builder object back
+ */
+ public ChronicleMapBuilder defaultValueProvider(
+ DefaultValueProvider defaultValueProvider) {
+ this.defaultValueProvider = defaultValueProvider;
+ return this;
+ }
+
+ /**
+ * Non-public because should be called only after {@link #preMapConstruction()}
+ */
+ DefaultValueProvider defaultValueProvider() {
+ if (defaultValueProvider != null)
+ return defaultValueProvider;
+ if (defaultValue == null)
+ return NullValueProvider.INSTANCE;
+ Object originalValueWriter = valueBuilder.interop();
+ Provider writerProvider = Provider.of(originalValueWriter.getClass());
+ ThreadLocalCopies copies = writerProvider.getCopies(null);
+ Object valueWriter = writerProvider.get(copies, originalValueWriter);
+ MetaProvider metaWriterProvider = valueBuilder.metaInteropProvider();
+ copies = metaWriterProvider.getCopies(copies);
+ MetaBytesWriter metaValueWriter = metaWriterProvider.get(copies,
+ valueBuilder.metaInterop(), valueWriter, defaultValue);
+ return new ConstantValueProvider(defaultValue, metaValueWriter, valueWriter);
+ }
+
public ChronicleMap create(File file) throws IOException {
for (int i = 0; i < 10; i++) {
if (file.exists() && file.length() > 0) {
@@ -524,6 +588,9 @@ public class ChronicleMapBuilder implements Cloneable {
}
private void preMapConstruction() {
+ keyBuilder.objectSerializer(objectSerializer());
+ valueBuilder.objectSerializer(objectSerializer());
+
int maxSize = entrySize() * figureBufferAllocationFactor();
keyBuilder.maxSize(maxSize);
valueBuilder.maxSize(maxSize);
diff --git a/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java b/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java
new file mode 100644
index 000000000..b6b9ff825
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/ConstantValueProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.map.serialization.BytesReader;
+import net.openhft.chronicle.map.serialization.MetaBytesWriter;
+import net.openhft.lang.io.ByteBufferBytes;
+
+import java.nio.ByteBuffer;
+
+final class ConstantValueProvider implements DefaultValueProvider {
+ private static final long serialVersionUID = 0L;
+
+ private transient V value;
+ private final int size;
+ private final byte[] serializedValueBytes;
+
+ ConstantValueProvider(V value, MetaBytesWriter metaValueWriter, W valueWriter) {
+ this.value = value;
+ size = (int) metaValueWriter.size(valueWriter, value);
+ serializedValueBytes = new byte[size];
+ ByteBufferBytes bytes = new ByteBufferBytes(ByteBuffer.wrap(serializedValueBytes));
+ metaValueWriter.write(valueWriter, bytes, value);
+ }
+
+ boolean wasDeserialized() {
+ return value == null;
+ }
+
+ void initTransients(BytesReader reader) {
+ value = reader.read(new ByteBufferBytes(ByteBuffer.wrap(serializedValueBytes)), size);
+ }
+
+ @Override
+ public V get(K key, V usingValue) {
+ return value;
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java b/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java
new file mode 100644
index 000000000..a179e12ee
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/DefaultValueProvider.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import java.io.Serializable;
+
+/**
+ * Default value computation strategy, used
+ * in {@link ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider)} configuration.
+ *
+ * @param map key class
+ * @param map value class
+ */
+public interface DefaultValueProvider extends Serializable {
+ /**
+ * Returns a value to be put and returned from {@link ChronicleMap#get(Object)} get()} or
+ * {@link ChronicleMap#getUsing(Object, Object)} call for the specified key, if it is absent
+ * in the map.
+ *
+ * If this method returns {@code null}, it isn't put for the key in the map.
+ *
+ * @param key key absent in the map
+ * @param usingValue an object provided as second parameter of current
+ * {@link ChronicleMap#getUsing(Object, Object)} call, or {@code null}, if this method is called
+ * within {@code get()} call. This object might be optionally initialized and returned back
+ * from this method.
+ * @return value to be put for the specified key in the map, or {@code null}, if the key should
+ * remain absent in the map
+ */
+ V get(K key, V usingValue);
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapEventListener.java b/src/main/java/net/openhft/chronicle/map/MapEventListener.java
index 68b4e88a2..8bde8ff79 100644
--- a/src/main/java/net/openhft/chronicle/map/MapEventListener.java
+++ b/src/main/java/net/openhft/chronicle/map/MapEventListener.java
@@ -31,27 +31,15 @@ public abstract class MapEventListener>
private static final long serialVersionUID = 0L;
/**
- * This is called when there was no existing entry for a key.
- * Optionally you can provide a value to add to the map.
+ * This method is called if the key is found in the map during {@link ChronicleMap#get get},
+ * {@link ChronicleMap#getUsing getUsing} or {@link ChronicleMap#acquireUsing acquireUsing}
+ * method call.
*
- * @param map accessed
- * @param keyBytes bytes of the key looked up
- * @param key object used as key
- * @param usingValue value provided to reuse, could be null.
- * @return null if null should be returned, or a value to put in the map and return.
- */
- public V onGetMissing(M map, K key, V usingValue) {
- return null;
- }
-
- /**
- * This method is called if a value is found in the map.
- *
- * @param map accessed
+ * @param map the accessed map
* @param entry bytes of the entry
- * @param metaDataBytes length of meta data for this map.
- * @param key looked up
- * @param value found
+ * @param metaDataBytes length of meta data for this map
+ * @param key the key looked up
+ * @param value the value found for the key
*/
public void onGetFound(M map, Bytes entry, int metaDataBytes, K key, V value) {
// do nothing
diff --git a/src/main/java/net/openhft/chronicle/map/MapEventListeners.java b/src/main/java/net/openhft/chronicle/map/MapEventListeners.java
index e07915ba6..4f23ffa18 100644
--- a/src/main/java/net/openhft/chronicle/map/MapEventListeners.java
+++ b/src/main/java/net/openhft/chronicle/map/MapEventListeners.java
@@ -35,13 +35,6 @@ public final class MapEventListeners {
private static final long serialVersionUID = 0L;
public final Logger LOGGER = LoggerFactory.getLogger(getClass());
- @Override
- public Object onGetMissing(ChronicleMap map,
- Object key, Object usingValue) {
- LOGGER.info("{} missed {}", map.file(), key);
- return null;
- }
-
@Override
public void onGetFound(ChronicleMap map, Bytes entry, int metaDataBytes,
Object key, Object value) {
@@ -84,13 +77,6 @@ public final class MapEventListeners {
private static final long serialVersionUID = 0L;
public final Logger LOGGER = LoggerFactory.getLogger(getClass());
- @Override
- public Object onGetMissing(ChronicleMap map,
- Object key, Object usingValue) {
- LOGGER.info("{} missed {}", map.file(), key);
- return null;
- }
-
@Override
public void onGetFound(ChronicleMap map, Bytes entry, int metaDataBytes,
Object key, Object value) {
diff --git a/src/main/java/net/openhft/chronicle/map/NullValueProvider.java b/src/main/java/net/openhft/chronicle/map/NullValueProvider.java
new file mode 100644
index 000000000..c92ec6948
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/NullValueProvider.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+enum NullValueProvider implements DefaultValueProvider {
+ INSTANCE;
+
+ @Override
+ public Object get(Object key, Object usingValue) {
+ return null;
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
index 5c7df7df2..3ea999fe8 100644
--- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
+++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java
@@ -1299,12 +1299,6 @@ class ReplicatedChronicleMap,
}
}
- @Override
- public V onGetMissing(ChronicleMap map, K key,
- V usingValue) {
- return nextListener.onGetMissing(map, key, usingValue);
- }
-
@Override
public void onGetFound(ChronicleMap map, Bytes entry, int metaDataBytes,
K key, V value) {
diff --git a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java
index ca6743b2f..6728d638f 100644
--- a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java
+++ b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java
@@ -22,17 +22,22 @@ import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.*;
import net.openhft.lang.io.serialization.impl.*;
import net.openhft.lang.model.Byteable;
-import net.openhft.lang.model.DataValueClasses;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Externalizable;
+import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.Modifier;
import static net.openhft.chronicle.map.Objects.hash;
import static net.openhft.chronicle.map.serialization.SizeMarshallers.stopBit;
final class SerializationBuilder implements Cloneable {
+
+ private static boolean concreteClass(Class c) {
+ return !c.isInterface() && !Modifier.isAbstract(c.getModifiers());
+ }
private static boolean marshallerUseFactory(Class c) {
return Byteable.class.isAssignableFrom(c) ||
@@ -51,25 +56,22 @@ final class SerializationBuilder implements Cloneable {
private CopyingInterop copyingInterop = null;
private MetaBytesInterop metaInterop;
private MetaProvider metaInteropProvider;
- private ObjectFactory factory;
+ private ObjectFactory factory;
@SuppressWarnings("unchecked")
SerializationBuilder(Class eClass, Role role) {
this.bufferIdentity = role;
this.eClass = eClass;
- Class classForMarshaller = marshallerUseFactory(eClass) && eClass.isInterface() ?
- DataValueClasses.directClassFor(eClass) : eClass;
- ObjectFactory factory = null;
- if (role == Role.VALUE) {
- factory = marshallerUseFactory(eClass) ?
- new AllocateInstanceObjectFactory(
- eClass.isInterface() ? classForMarshaller : eClass) :
+ ObjectFactory factory = this.factory;
+ if (factory == null && role == Role.VALUE) {
+ factory = concreteClass(eClass) && marshallerUseFactory(eClass) ?
+ new AllocateInstanceObjectFactory(eClass) :
NullObjectFactory.INSTANCE;
}
- if (Byteable.class.isAssignableFrom(eClass)) {
- agileMarshaller(ByteableMarshaller.of((Class) classForMarshaller), factory);
+ if (concreteClass(eClass) && Byteable.class.isAssignableFrom(eClass)) {
+ agileMarshaller(ByteableMarshaller.of((Class) eClass), factory);
} else if (eClass == CharSequence.class || eClass == String.class) {
reader((BytesReader) CharSequenceReader.of(), factory);
writer((BytesWriter) CharSequenceWriter.instance());
@@ -78,8 +80,10 @@ final class SerializationBuilder implements Cloneable {
} else if (eClass == byte[].class) {
reader((BytesReader) ByteArrayMarshaller.INSTANCE, factory);
interop((BytesInterop) ByteArrayMarshaller.INSTANCE);
- } else {
- marshaller(chooseMarshaller(eClass, classForMarshaller), factory);
+ } else if (concreteClass(eClass)) {
+ BytesMarshaller marshaller = chooseMarshaller(eClass, eClass);
+ if (marshaller != null)
+ marshaller(marshaller, factory);
}
}
@@ -93,7 +97,7 @@ final class SerializationBuilder implements Cloneable {
return (BytesMarshaller) IntegerMarshaller.INSTANCE;
if (eClass == Double.class)
return (BytesMarshaller) DoubleMarshaller.INSTANCE;
- return SerializableMarshaller.INSTANCE;
+ return null;
}
private SerializationBuilder copyingInterop(CopyingInterop copyingInterop) {
@@ -148,6 +152,16 @@ final class SerializationBuilder implements Cloneable {
return this;
}
+ public SerializationBuilder objectSerializer(ObjectSerializer serializer) {
+ if (reader == null || interop == null) {
+ ObjectFactory factory = this.factory;
+ if (factory == null)
+ factory = NullObjectFactory.INSTANCE;
+ marshaller(new SerializableMarshaller(serializer), factory);
+ }
+ return this;
+ }
+
public SizeMarshaller sizeMarshaller() {
return sizeMarshaller;
}
@@ -297,24 +311,46 @@ final class SerializationBuilder implements Cloneable {
}
- private enum SerializableMarshaller implements BytesMarshaller {
- INSTANCE;
+ private static class SerializableMarshaller implements BytesMarshaller {
+ private static final long serialVersionUID = 0L;
+
+ private final ObjectSerializer serializer;
+
+ private SerializableMarshaller(ObjectSerializer serializer) {
+ this.serializer = serializer;
+ }
@Override
public void write(Bytes bytes, Object obj) {
- bytes.writeObject(obj);
+ try {
+ serializer.writeSerializable(bytes, obj, null);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
}
@Nullable
@Override
public Object read(Bytes bytes) {
- return bytes.readObject();
+ try {
+ return serializer.readSerializable(bytes, null, null);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
@Nullable
@Override
public Object read(Bytes bytes, @Nullable Object obj) {
- return bytes.readInstance(null, obj);
+ try {
+ return serializer.readSerializable(bytes, null, obj);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
}
}
diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
index 5aaae93ca..ee0f24c31 100644
--- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
+++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java
@@ -72,6 +72,7 @@ class VanillaChronicleMap,
final MVW originalMetaValueWriter;
final MetaProvider metaValueWriterProvider;
final ObjectFactory valueFactory;
+ final DefaultValueProvider defaultValueProvider;
final int metaDataBytes;
// private final int replicas;
@@ -118,6 +119,7 @@ class VanillaChronicleMap,
originalMetaValueWriter = (MVW) valueBuilder.metaInterop();
metaValueWriterProvider = (MetaProvider) valueBuilder.metaInteropProvider();
valueFactory = valueBuilder.factory();
+ defaultValueProvider = builder.defaultValueProvider();
lockTimeOutNS = builder.lockTimeOut(TimeUnit.NANOSECONDS);
@@ -163,6 +165,16 @@ class VanillaChronicleMap,
valueReaderProvider = Provider.of((Class) originalValueReader.getClass());
valueWriterProvider = Provider.of((Class) originalValueWriter.getClass());
+ if (defaultValueProvider instanceof ConstantValueProvider) {
+ ConstantValueProvider constantValueProvider =
+ (ConstantValueProvider) defaultValueProvider;
+ if (constantValueProvider.wasDeserialized()) {
+ ThreadLocalCopies copies = valueReaderProvider.getCopies(null);
+ BytesReader valueReader = valueReaderProvider.get(copies, originalValueReader);
+ constantValueProvider.initTransients(valueReader);
+ }
+ }
+
@SuppressWarnings("unchecked")
Segment[] ss = (Segment[]) Array.newInstance(segmentType(), actualSegments);
this.segments = ss;
@@ -765,7 +777,7 @@ class VanillaChronicleMap,
} else {
if (usingValue instanceof Byteable)
((Byteable) usingValue).bytes(null, 0);
- return notifyMissed(key, usingValue);
+ return defaultValueProvider.get(key, usingValue);
}
}
@@ -1070,13 +1082,6 @@ class VanillaChronicleMap,
}
}
- V notifyMissed(K key, V usingValue) {
- if (eventListener() != MapEventListeners.NOP) {
- return eventListener().onGetMissing(VanillaChronicleMap.this, key, usingValue);
- }
- return null;
- }
-
void notifyRemoved(long offset, K key, V value, final int pos) {
if (eventListener() != MapEventListeners.NOP) {
tmpBytes.storePositionAndSize(bytes, offset, entrySize);
diff --git a/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java b/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java
new file mode 100644
index 000000000..53b9697ac
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/DefaultValueTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.lang.model.DataValueClasses;
+import net.openhft.lang.values.IntValue;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+
+public class DefaultValueTest {
+
+ @Test
+ public void test() throws IllegalAccessException, InstantiationException, IOException {
+ File file = Builder.getPersistenceFile();
+ try {
+
+ ArrayList defaultValue = new ArrayList();
+ defaultValue.add(42);
+ try (ChronicleMap> map = ChronicleMapBuilder
+ .of(String.class, (Class>) ((Class) List.class))
+ .defaultValue(defaultValue)
+ .create(file)) {
+
+ assertEquals(defaultValue, map.get("a"));
+ assertEquals(1, map.size());
+
+ map.put("b", Arrays.asList(1, 2));
+ assertEquals(Arrays.asList(1, 2), map.get("b"));
+ }
+
+ try (ChronicleMap> map = ChronicleMapBuilder
+ .of(String.class, (Class>) ((Class) List.class)).create(file)) {
+ assertEquals(defaultValue, map.get("c"));
+ }
+ } finally {
+ file.delete();
+ }
+ }
+}
diff --git a/src/test/java/net/openhft/chronicle/map/example/WordCount.java b/src/test/java/net/openhft/chronicle/map/example/WordCount.java
new file mode 100644
index 000000000..f0af6d943
--- /dev/null
+++ b/src/test/java/net/openhft/chronicle/map/example/WordCount.java
@@ -0,0 +1,46 @@
+package net.openhft.chronicle.map.example;
+
+import net.openhft.chronicle.map.ChronicleMap;
+import net.openhft.chronicle.map.ChronicleMapBuilder;
+import net.openhft.lang.model.Byteable;
+import net.openhft.lang.values.IntValue;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WordCount {
+
+ static String[] words;
+ static int expectedSize;
+ static {
+ try {
+ // english version of war and peace -> ascii
+ String fullText =
+ new String(Files.readAllBytes(Paths.get("war_and_peace.txt")), UTF_8);
+ words = fullText.split("\\s+");
+ expectedSize = (int) Arrays.stream(words).distinct().count();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static interface ByteableIntValue extends IntValue, Byteable {}
+
+ public int chronicleMap() throws IOException {
+ ChronicleMap map =
+ ChronicleMapBuilder.of(String.class, ByteableIntValue.class)
+ .entrySize(16)
+ .actualSegments(1)
+ .entries(expectedSize)
+ .create();
+ ByteableIntValue v = map.acquireUsing("a", null);
+ for (String word : words) {
+ map.acquireUsing(word, v).addValue(1);
+ }
+ return map.acquireUsing("a", v).getValue();
+ }
+}
\ No newline at end of file