Use inheritance for collections classes
diff --git a/src/main/java/org/testng/collections/ListMultiMap.java b/src/main/java/org/testng/collections/ListMultiMap.java
index 88d27e6..5750c84 100644
--- a/src/main/java/org/testng/collections/ListMultiMap.java
+++ b/src/main/java/org/testng/collections/ListMultiMap.java
@@ -1,115 +1,16 @@
 package org.testng.collections;
 
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
 
 /**
  * A container to hold lists indexed by a key.
  */
-public class ListMultiMap<K, V> {
-  private final Map<K, List<V>> m_objects = Maps.newHashMap();
-
-  public boolean put(K key, V method) {
-    boolean setExists = true;
-    List<V> l = m_objects.get(key);
-    if (l == null) {
-      setExists = false;
-      l = Lists.newArrayList();
-      m_objects.put(key, l);
-    }
-    return l.add(method) && setExists;
-  }
-
-  public List<V> get(K key) {
-    return m_objects.get(key);
-  }
-
-  @Deprecated
-  public List<K> getKeys() {
-    return new ArrayList<>(m_objects.keySet());
-  }
-
-  public Set<K> keySet() {
-    return new HashSet(m_objects.keySet());
-  }
-
-  public boolean containsKey(K k) {
-    return m_objects.containsKey(k);
-  }
+public class ListMultiMap<K, V> extends MultiMap<K, V, List<V>> {
 
   @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    Set<K> indices = keySet();
-    for (K i : indices) {
-      result.append("\n    ").append(i).append(" <-- ");
-      for (Object o : m_objects.get(i)) {
-        result.append(o).append(" ");
-      }
-    }
-    return result.toString();
-  }
-
-  public boolean isEmpty() {
-    return m_objects.size() == 0;
-  }
-
-  @Deprecated
-  public int getSize() {
-    return size();
-  }
-
-  public int size() {
-    return m_objects.size();
-  }
-
-  @Deprecated
-  public List<V> remove(K key) {
-    return removeAll(key);
-  }
-
-  public boolean remove(K key, V value) {
-    List<V> values = get(key);
-    if (values == null) {
-      return false;
-    }
-    return values.remove(value);
-  }
-
-  public List<V> removeAll(K key) {
-    return m_objects.remove(key);
-  }
-
-  @Deprecated
-  public Set<Entry<K, List<V>>> getEntrySet() {
-    return entrySet();
-  }
-
-  public Set<Entry<K, List<V>>> entrySet() {
-    return m_objects.entrySet();
-  }
-
-  @Deprecated
-  public Collection<List<V>> getValues() {
-    return values();
-  }
-
-  public Collection<List<V>> values() {
-    return m_objects.values();
-  }
-
-  public boolean putAll(K k, Collection<? extends V> values) {
-    boolean result = false;
-    for (V v : values) {
-      result = put(k, v) || result;
-    }
-    return result;
+  protected List<V> createValue() {
+    return Lists.newArrayList();
   }
 
   @Deprecated
diff --git a/src/main/java/org/testng/collections/MultiMap.java b/src/main/java/org/testng/collections/MultiMap.java
new file mode 100644
index 0000000..c606645
--- /dev/null
+++ b/src/main/java/org/testng/collections/MultiMap.java
@@ -0,0 +1,111 @@
+package org.testng.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class MultiMap<K, V, C extends Collection<V>> {
+  protected final Map<K, C> m_objects = Maps.newHashMap();
+
+  protected abstract C createValue();
+
+  public boolean put(K key, V method) {
+    boolean setExists = true;
+    C l = m_objects.get(key);
+    if (l == null) {
+      setExists = false;
+      l = createValue();
+      m_objects.put(key, l);
+    }
+    return l.add(method) && setExists;
+  }
+
+  public C get(K key) {
+    return m_objects.get(key);
+  }
+
+  @Deprecated
+  public List<K> getKeys() {
+    return new ArrayList<>(keySet());
+  }
+
+  public Set<K> keySet() {
+    return new HashSet(m_objects.keySet());
+  }
+
+  public boolean containsKey(K k) {
+    return m_objects.containsKey(k);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    Set<K> indices = keySet();
+    for (K i : indices) {
+      result.append("\n    ").append(i).append(" <-- ");
+      for (Object o : m_objects.get(i)) {
+        result.append(o).append(" ");
+      }
+    }
+    return result.toString();
+  }
+
+  public boolean isEmpty() {
+    return m_objects.size() == 0;
+  }
+
+  @Deprecated
+  public int getSize() {
+    return size();
+  }
+
+  public int size() {
+    return m_objects.size();
+  }
+
+  @Deprecated
+  public C remove(K key) {
+    return removeAll(key);
+  }
+
+  public boolean remove(K key, V value) {
+    C values = get(key);
+    if (values == null) {
+      return false;
+    }
+    return values.remove(value);
+  }
+
+  public C removeAll(K key) {
+    return m_objects.remove(key);
+  }
+
+  @Deprecated
+  public Set<Map.Entry<K, C>> getEntrySet() {
+    return entrySet();
+  }
+
+  public Set<Map.Entry<K, C>> entrySet() {
+    return m_objects.entrySet();
+  }
+
+  @Deprecated
+  public Collection<C> getValues() {
+    return values();
+  }
+
+  public Collection<C> values() {
+    return m_objects.values();
+  }
+
+  public boolean putAll(K k, Collection<? extends V> values) {
+    boolean result = false;
+    for (V v : values) {
+      result = put(k, v) || result;
+    }
+    return result;
+  }
+}
diff --git a/src/main/java/org/testng/collections/SetMultiMap.java b/src/main/java/org/testng/collections/SetMultiMap.java
index 9576bd1..f85ba25 100644
--- a/src/main/java/org/testng/collections/SetMultiMap.java
+++ b/src/main/java/org/testng/collections/SetMultiMap.java
@@ -1,111 +1,14 @@
 package org.testng.collections;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 
 /**
  * A container to hold sets indexed by a key.
  */
-public class SetMultiMap<K, V> {
-  private final Map<K, Set<V>> m_objects = Maps.newHashMap();
-
-  public boolean put(K key, V method) {
-    boolean setExists = true;
-    Set<V> l = m_objects.get(key);
-    if (l == null) {
-      setExists = false;
-      l = Sets.newHashSet();
-      m_objects.put(key, l);
-    }
-    return l.add(method) && setExists;
-  }
-
-  public Set<V> get(K key) {
-    return m_objects.get(key);
-  }
-
-  @Deprecated
-  public Set<K> getKeys() {
-    return keySet();
-  }
-
-  public Set<K> keySet() {
-    return new HashSet(m_objects.keySet());
-  }
-
-  public boolean containsKey(K k) {
-    return m_objects.containsKey(k);
-  }
+public class SetMultiMap<K, V> extends MultiMap<K, V, Set<V>> {
 
   @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    Set<K> indices = keySet();
-    for (K i : indices) {
-      result.append("\n    ").append(i).append(" <-- ");
-      for (Object o : m_objects.get(i)) {
-        result.append(o).append(" ");
-      }
-    }
-    return result.toString();
-  }
-
-  public boolean isEmpty() {
-    return m_objects.size() == 0;
-  }
-
-  @Deprecated
-  public int getSize() {
-    return size();
-  }
-
-  public int size() {
-    return m_objects.size();
-  }
-
-  @Deprecated
-  public Set<V> remove(K key) {
-    return removeAll(key);
-  }
-
-  public boolean remove(K key, V value) {
-    Set<V> values = get(key);
-    if (values == null) {
-      return false;
-    }
-    return values.remove(value);
-  }
-
-  public Set<V> removeAll(K key) {
-    return m_objects.remove(key);
-  }
-
-  @Deprecated
-  public Set<Entry<K, Set<V>>> getEntrySet() {
-    return entrySet();
-  }
-
-  public Set<Entry<K, Set<V>>> entrySet() {
-    return m_objects.entrySet();
-  }
-
-  @Deprecated
-  public Collection<Set<V>> getValues() {
-    return values();
-  }
-
-  public Collection<Set<V>> values() {
-    return m_objects.values();
-  }
-
-  public boolean putAll(K k, Collection<? extends V> values) {
-    boolean result = false;
-    for (V v : values) {
-      result = put(k, v) || result;
-    }
-    return result;
+  protected Set<V> createValue() {
+    return Sets.newHashSet();
   }
 }