Introduce MapAdaptor.initialSnapshot() 67/22667/2
authorRobert Varga <rovarga@cisco.com>
Mon, 15 Jun 2015 22:28:54 +0000 (00:28 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 16 Jun 2015 07:51:10 +0000 (07:51 +0000)
In some circumstances we have an idea about how many entries will there
be in a map. This could cost us perform one additional copy, so expose a
method to create the appropriate map, behaving just as the one returned
by takeSnapshot(Collections.emptyMap()).

Also use ImmutableMaps for empty map, as it being immutable is recognized
by Guava, leading to quick reuse.

Change-Id: I40925e5d643c074277e9d11365a3b10fb9f22c1d
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit 92fc5cc4436a65c3a63e1fc7afbff2ac42a70880)

common/util/src/main/java/org/opendaylight/yangtools/util/MapAdaptor.java
common/util/src/main/java/org/opendaylight/yangtools/util/ReadWriteTrieMap.java
common/util/src/test/java/org/opendaylight/yangtools/util/MapAdaptorTest.java

index bea7630330c3a0ae89af54d141931ebd9868b8f6..48241cd5a638322dec8013aa54e32bca9be3de6b 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.yangtools.util;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 import com.romix.scala.collection.concurrent.TrieMap;
 import java.util.Collections;
 import java.util.HashMap;
@@ -85,6 +87,22 @@ public final class MapAdaptor {
         return new MapAdaptor(useSingleton, copyMaxItems, persistMinItems);
     }
 
+    /**
+     * Creates an initial snapshot. The backing map is selected according to
+     * the expected size.
+     *
+     * @param expectedSize Expected map size
+     * @return An empty mutable map.
+     */
+    public <K, V> Map<K, V> initialSnapshot(final int expectedSize) {
+        Preconditions.checkArgument(expectedSize >= 0);
+        if (expectedSize > persistMinItems) {
+            return new ReadWriteTrieMap<>();
+        }
+
+        return Maps.newHashMapWithExpectedSize(expectedSize);
+    }
+
     /**
      * Input is treated is supposed to be left unmodified, result must be mutable.
      *
@@ -124,7 +142,7 @@ public final class MapAdaptor {
          */
         if (size == 0) {
             LOG.trace("Reducing input {} to an empty map", input);
-            return Collections.emptyMap();
+            return ImmutableMap.of();
         }
 
         /*
index 039e7340a5a7a2260c999b1626d92a2dae1b4037..99cb628f89d86e78c9aba68e5139b3b36d8af719 100644 (file)
@@ -7,17 +7,15 @@
  */
 package org.opendaylight.yangtools.util;
 
+import com.google.common.base.Preconditions;
+import com.romix.scala.collection.concurrent.TrieMap;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-import com.romix.scala.collection.concurrent.TrieMap;
-
 /**
  * A TrieMap facade tracking modifications. Since we change structures based on
  * their size, and determining the size of a TrieMap is expensive, we make sure
@@ -34,6 +32,11 @@ final class ReadWriteTrieMap<K, V> implements Map<K, V> {
     private final TrieMap<K, V> delegate;
     private int size;
 
+    ReadWriteTrieMap() {
+        this.delegate = new TrieMap<K, V>();
+        this.size = 0;
+    }
+
     ReadWriteTrieMap(final TrieMap<K, V> delegate, final int size) {
         this.delegate = Preconditions.checkNotNull(delegate);
         this.size = size;
index e4ae622121118a1cc28cb9e2ffe7f4ce1c7390d4..ec3b982dc823d3885be81e8048664033fe0b0495 100644 (file)
@@ -11,12 +11,11 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-
+import com.google.common.collect.ImmutableMap;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.TreeMap;
-
 import org.junit.Before;
 import org.junit.Test;
 
@@ -38,10 +37,10 @@ public class MapAdaptorTest {
         assertTrue(snap instanceof HashMap);
 
         final Map<?, ?> opt1 = adaptor.optimize(input);
-        assertSame(Collections.EMPTY_MAP, opt1);
+        assertSame(ImmutableMap.of(), opt1);
 
         final Map<?, ?> opt2 = adaptor.optimize(snap);
-        assertSame(Collections.EMPTY_MAP, opt2);
+        assertSame(ImmutableMap.of(), opt2);
     }
 
     @Test