test/java/util/Map/BasicSerialization.java

Print this page
rev 6789 : 7143928: Optimize empty HashMap and ArrayList
Reviewed-by: mduigou
Contributed-by: Sergey Linetskiy <sergey.linetskiy@oracle.com>, John Rose <john.rose@oracle.com>, Mike Duigou <mike.duigou@oracle.com>


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 7126277
  27  * @run main Collisions -shortrun
  28  * @run main/othervm -Djdk.map.althashing.threshold=0 Collisions -shortrun
  29  * @summary Ensure Maps behave well with lots of hashCode() collisions.
  30  * @author Mike Duigou
  31  */








  32 import java.util.*;
  33 import java.util.concurrent.ConcurrentHashMap;
  34 import java.util.concurrent.ConcurrentSkipListMap;
  35 
  36 public class Collisions {
  37 
























  38     /**
  39      * Number of elements per map.
  40      */
  41     private static final int TEST_SIZE = 5000;
  42 
  43     final static class HashableInteger implements Comparable<HashableInteger> {
  44 
  45         final int value;
  46         final int hashmask; //yes duplication
  47 
  48         HashableInteger(int value, int hashmask) {
  49             this.value = value;
  50             this.hashmask = hashmask;
  51         }
  52 
  53         @Override
  54         public boolean equals(Object obj) {
  55             if (obj instanceof HashableInteger) {
  56                 HashableInteger other = (HashableInteger) obj;
  57 
  58                 return other.value == value;
  59             }
  60 
  61             return false;
  62         }
  63 
  64         @Override
  65         public int hashCode() {
  66             return value % hashmask;
  67         }
  68 
  69         @Override
  70         public int compareTo(HashableInteger o) {
  71             return value - o.value;
  72         }
  73 
  74         @Override
  75         public String toString() {
  76             return Integer.toString(value);
  77         }
  78     }
  79 
  80     private static Object[][] makeTestData(int size) {
  81         HashableInteger UNIQUE_OBJECTS[] = new HashableInteger[size];
  82         HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[size];
  83         String UNIQUE_STRINGS[] = new String[size];
  84         String COLLIDING_STRINGS[] = new String[size];
  85 
  86         for (int i = 0; i < size; i++) {
  87             UNIQUE_OBJECTS[i] = new HashableInteger(i, Integer.MAX_VALUE);
  88             COLLIDING_OBJECTS[i] = new HashableInteger(i, 10);
  89             UNIQUE_STRINGS[i] = unhash(i);
  90             COLLIDING_STRINGS[i] = (0 == i % 2)
  91                     ? UNIQUE_STRINGS[i / 2]
  92                     : "\u0000\u0000\u0000\u0000\u0000" + COLLIDING_STRINGS[i - 1];
  93         }
  94 
  95      return new Object[][] {
  96             new Object[]{"Unique Objects", UNIQUE_OBJECTS},
  97             new Object[]{"Colliding Objects", COLLIDING_OBJECTS},
  98             new Object[]{"Unique Strings", UNIQUE_STRINGS},
  99             new Object[]{"Colliding Strings", COLLIDING_STRINGS}
 100         };
 101     }
 102 
 103     /**
 104      * Returns a string with a hash equal to the argument.
 105      *
 106      * @return string with a hash equal to the argument.
 107      */
 108     public static String unhash(int target) {
 109         StringBuilder answer = new StringBuilder();
 110         if (target < 0) {
 111             // String with hash of Integer.MIN_VALUE, 0x80000000
 112             answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
 113 
 114             if (target == Integer.MIN_VALUE) {
 115                 return answer.toString();



 116             }
 117             // Find target without sign bit set
 118             target = target & Integer.MAX_VALUE;
 119         }


 120 
 121         unhash0(answer, target);
 122         return answer.toString();
 123     }
 124 
 125     private static void unhash0(StringBuilder partial, int target) {
 126         int div = target / 31;
 127         int rem = target % 31;
 128 
 129         if (div <= Character.MAX_VALUE) {
 130             if (div != 0) {
 131                 partial.append((char) div);
 132             }
 133             partial.append((char) rem);
 134         } else {
 135             unhash0(partial, div);
 136             partial.append((char) rem);
 137         }
 138     }
 139 
 140     private static void realMain(String[] args) throws Throwable {
 141         boolean shortRun = args.length > 0 && args[0].equals("-shortrun");
 142 
 143         Object[][] mapKeys = makeTestData(shortRun ? (TEST_SIZE / 2) : TEST_SIZE);
 144 
 145         // loop through data sets
 146         for (Object[] keys_desc : mapKeys) {
 147             Map<Object, Object>[] maps = (Map<Object, Object>[]) new Map[]{
 148                         new HashMap<>(),
 149                         new Hashtable<>(),
 150                         new IdentityHashMap<>(),
 151                         new LinkedHashMap<>(),
 152                         new TreeMap<>(),
 153                         new WeakHashMap<>(),
 154                         new ConcurrentHashMap<>(),
 155                         new ConcurrentSkipListMap<>()
 156                     };
 157 
 158             // for each map type.
 159             for (Map<Object, Object> map : maps) {
 160                 String desc = (String) keys_desc[0];
 161                 Object[] keys = (Object[]) keys_desc[1];
 162                 try {
 163                     testMap(map, desc, keys);
 164                 } catch(Exception all) {
 165                     unexpected("Failed for " + map.getClass().getName() + " with " + desc, all);
 166                 }
 167             }
 168         }
 169     }
 170 
 171     private static <T> void testMap(Map<T, T> map, String keys_desc, T[] keys) {
 172         System.out.println(map.getClass() + " : " + keys_desc);
 173         System.out.flush();
 174         testInsertion(map, keys_desc, keys);
 175 
 176         if (keys[0] instanceof HashableInteger) {
 177             testIntegerIteration((Map<HashableInteger, HashableInteger>) map, (HashableInteger[]) keys);
 178         } else {
 179             testStringIteration((Map<String, String>) map, (String[]) keys);
 180         }
 181 
 182         testContainsKey(map, keys_desc, keys);
 183 
 184         testRemove(map, keys_desc, keys);
 185 
 186         map.clear();
 187         testInsertion(map, keys_desc, keys);
 188         testKeysIteratorRemove(map, keys_desc, keys);
 189 
 190         map.clear();
 191         testInsertion(map, keys_desc, keys);
 192         testValuesIteratorRemove(map, keys_desc, keys);
 193 
 194         map.clear();
 195         testInsertion(map, keys_desc, keys);
 196         testEntriesIteratorRemove(map, keys_desc, keys);
 197 
 198         check(map.isEmpty());
 199     }
 200 
 201     private static <T> void testInsertion(Map<T, T> map, String keys_desc, T[] keys) {
 202         check("map empty", (map.size() == 0) && map.isEmpty());
 203 
 204         for (int i = 0; i < keys.length; i++) {
 205             check(String.format("insertion: map expected size m%d != i%d", map.size(), i),
 206                     map.size() == i);
 207             check(String.format("insertion: put(%s[%d])", keys_desc, i), null == map.put(keys[i], keys[i]));
 208             check(String.format("insertion: containsKey(%s[%d])", keys_desc, i), map.containsKey(keys[i]));
 209             check(String.format("insertion: containsValue(%s[%d])", keys_desc, i), map.containsValue(keys[i]));
 210         }
 211 
 212         check(String.format("map expected size m%d != k%d", map.size(), keys.length),
 213                 map.size() == keys.length);
 214     }
 215 
 216     private static void testIntegerIteration(Map<HashableInteger, HashableInteger> map, HashableInteger[] keys) {
 217         check(String.format("map expected size m%d != k%d", map.size(), keys.length),
 218                 map.size() == keys.length);
 219 
 220         BitSet all = new BitSet(keys.length);
 221         for (Map.Entry<HashableInteger, HashableInteger> each : map.entrySet()) {
 222             check("Iteration: key already seen", !all.get(each.getKey().value));
 223             all.set(each.getKey().value);
 224         }
 225 
 226         all.flip(0, keys.length);
 227         check("Iteration: some keys not visited", all.isEmpty());
 228 
 229         for (HashableInteger each : map.keySet()) {
 230             check("Iteration: key already seen", !all.get(each.value));
 231             all.set(each.value);
 232         }
 233 
 234         all.flip(0, keys.length);
 235         check("Iteration: some keys not visited", all.isEmpty());
 236 
 237         int count = 0;
 238         for (HashableInteger each : map.values()) {
 239             count++;
 240         }
 241 
 242         check(String.format("Iteration: value count matches size m%d != c%d", map.size(), count),
 243                 map.size() == count);
 244     }
 245 
 246     private static void testStringIteration(Map<String, String> map, String[] keys) {
 247         check(String.format("map expected size m%d != k%d", map.size(), keys.length),
 248                 map.size() == keys.length);
 249 
 250         BitSet all = new BitSet(keys.length);
 251         for (Map.Entry<String, String> each : map.entrySet()) {
 252             String key = each.getKey();
 253             boolean longKey = key.length() > 5;
 254             int index = key.hashCode() + (longKey ? keys.length / 2 : 0);
 255             check("key already seen", !all.get(index));
 256             all.set(index);
 257         }
 258 
 259         all.flip(0, keys.length);
 260         check("some keys not visited", all.isEmpty());
 261 
 262         for (String each : map.keySet()) {
 263             boolean longKey = each.length() > 5;
 264             int index = each.hashCode() + (longKey ? keys.length / 2 : 0);
 265             check("key already seen", !all.get(index));
 266             all.set(index);
 267         }
 268 
 269         all.flip(0, keys.length);
 270         check("some keys not visited", all.isEmpty());
 271 
 272         int count = 0;
 273         for (String each : map.values()) {
 274             count++;
 275         }
 276 
 277         check(String.format("value count matches size m%d != k%d", map.size(), keys.length),
 278                 map.size() == keys.length);
 279     }
 280 
 281     private static <T> void testContainsKey(Map<T, T> map, String keys_desc, T[] keys) {
 282         for (int i = 0; i < keys.length; i++) {
 283             T each = keys[i];
 284             check("containsKey: " + keys_desc + "[" + i + "]" + each, map.containsKey(each));
 285         }
 286     }
 287 
 288     private static <T> void testRemove(Map<T, T> map, String keys_desc, T[] keys) {
 289         check(String.format("remove: map expected size m%d != k%d", map.size(), keys.length),
 290                 map.size() == keys.length);
 291 
 292         for (int i = 0; i < keys.length; i++) {
 293             T each = keys[i];
 294             check("remove: " + keys_desc + "[" + i + "]" + each, null != map.remove(each));
 295         }
 296 
 297         check(String.format("remove: map empty. size=%d", map.size()),
 298                 (map.size() == 0) && map.isEmpty());
 299     }
 300 
 301     private static <T> void testKeysIteratorRemove(Map<T, T> map, String keys_desc, T[] keys) {
 302         check(String.format("remove: map expected size m%d != k%d", map.size(), keys.length),
 303                 map.size() == keys.length);
 304 
 305         Iterator<T> each = map.keySet().iterator();
 306         while (each.hasNext()) {
 307             T t = each.next();
 308             each.remove();
 309             check("not removed: " + each, !map.containsKey(t) );
 310         }
 311 
 312         check(String.format("remove: map empty. size=%d", map.size()),
 313                 (map.size() == 0) && map.isEmpty());
 314     }
 315 
 316     private static <T> void testValuesIteratorRemove(Map<T, T> map, String keys_desc, T[] keys) {
 317         check(String.format("remove: map expected size m%d != k%d", map.size(), keys.length),
 318                 map.size() == keys.length);
 319 
 320         Iterator<T> each = map.values().iterator();
 321         while (each.hasNext()) {
 322             T t = each.next();
 323             each.remove();
 324             check("not removed: " + each, !map.containsValue(t) );
 325         }
 326 
 327         check(String.format("remove: map empty. size=%d", map.size()),
 328                 (map.size() == 0) && map.isEmpty());
 329     }
 330 
 331     private static <T> void testEntriesIteratorRemove(Map<T, T> map, String keys_desc, T[] keys) {
 332         check(String.format("remove: map expected size m%d != k%d", map.size(), keys.length),
 333                 map.size() == keys.length);
 334 
 335         Iterator<Map.Entry<T,T>> each = map.entrySet().iterator();
 336         while (each.hasNext()) {
 337             Map.Entry<T,T> t = each.next();
 338             T key = t.getKey();
 339             T value = t.getValue();
 340             each.remove();
 341             check("not removed: " + each, (map instanceof IdentityHashMap) || !map.entrySet().contains(t) );
 342             check("not removed: " + each, !map.containsKey(key) );
 343             check("not removed: " + each, !map.containsValue(value));
 344         }
 345 
 346         check(String.format("remove: map empty. size=%d", map.size()),
 347                 (map.size() == 0) && map.isEmpty());
 348     }
 349 
 350     //--------------------- Infrastructure ---------------------------
 351     static volatile int passed = 0, failed = 0;
 352 
 353     static void pass() {
 354         passed++;
 355     }
 356 
 357     static void fail() {
 358         failed++;
 359         (new Error("Failure")).printStackTrace(System.err);
 360     }
 361 
 362     static void fail(String msg) {
 363         failed++;
 364         (new Error("Failure: " + msg)).printStackTrace(System.err);
 365     }
 366 
 367     static void abort() {
 368         fail();
 369         System.exit(1);
 370     }
 371 
 372     static void abort(String msg) {
 373         fail(msg);
 374         System.exit(1);
 375     }
 376 
 377     static void unexpected(String msg, Throwable t) {
 378         System.err.println("Unexpected: " + msg);
 379         unexpected(t);
































 380     }
 381 
 382     static void unexpected(Throwable t) {
 383         failed++;
 384         t.printStackTrace(System.err);
 385     }
 386 
 387     static void check(boolean cond) {
 388         if (cond) {
 389             pass();
 390         } else {
 391             fail();
 392         }
 393     }
 394 
 395     static void check(String desc, boolean cond) {
 396         if (cond) {
 397             pass();
 398         } else {
 399             fail(desc);
 400         }
 401     }
 402 
 403     static void equal(Object x, Object y) {
 404         if (Objects.equals(x, y)) {
 405             pass();
 406         } else {
 407             fail(x + " not equal to " + y);


 408         }
 409     }
 410 
 411     public static void main(String[] args) throws Throwable {
 412         Thread.currentThread().setName(Collisions.class.getName());
 413 //        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
 414         try {
 415             realMain(args);
 416         } catch (Throwable t) {
 417             unexpected(t);



























 418         }
 419 
 420         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 421         if (failed > 0) {
 422             throw new Error("Some tests failed");
 423         }
 424     }
 425 }


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 7143928
  27  * @run testng BasicSerialization
  28  * @summary Ensure Maps can be serialized and deserialized.

  29  * @author Mike Duigou
  30  */
  31 import java.io.ByteArrayOutputStream;
  32 import java.io.InputStream;
  33 import java.io.IOException;
  34 import java.io.ObjectInputStream;
  35 import java.io.ObjectOutputStream;
  36 import java.io.ByteArrayInputStream;
  37 import java.lang.reflect.Constructor;
  38 import java.lang.reflect.Method;
  39 import java.util.*;
  40 import java.util.concurrent.ConcurrentHashMap;
  41 import java.util.concurrent.ConcurrentSkipListMap;
  42 
  43 import org.testng.annotations.Test;
  44 import org.testng.annotations.DataProvider;
  45 import static org.testng.Assert.fail;
  46 import static org.testng.Assert.assertEquals;
  47 import static org.testng.Assert.assertTrue;
  48 import static org.testng.Assert.assertFalse;
  49 import static org.testng.Assert.assertSame;
  50 
  51 public class BasicSerialization {
  52 
  53     enum IntegerEnum {
  54 
  55         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
  56         e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
  57         e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
  58         e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
  59         e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
  60         e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
  61         e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
  62         e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
  63         e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
  64         e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
  65         EXTRA_KEY;
  66         public static final int SIZE = values().length;
  67     };
  68     private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
  69     /**
  70      * Realized keys ensure that there is always a hard ref to all test objects.
  71      */
  72     private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];





























































  73     /**
  74      * Realized values ensure that there is always a hard ref to all test
  75      * objects.

  76      */
  77     private static final String[] VALUES = new String[TEST_SIZE];




  78 
  79     static {
  80         IntegerEnum[] keys = IntegerEnum.values();
  81         for (int each = 0; each < TEST_SIZE; each++) {
  82             KEYS[each] = keys[each];
  83             VALUES[each] = keys[each].name();
  84         }


  85     }
  86     private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
  87     private static final String EXTRA_VALUE = IntegerEnum.EXTRA_KEY.name();
  88 
  89     public static <K, V> Map<K, V> mapClone(Map<K, V> map) {
  90         Method cloneMethod;

  91 
  92         try {
  93             cloneMethod = map.getClass().getMethod("clone", new Class[]{});
  94         } catch (NoSuchMethodException | SecurityException all) {
  95             cloneMethod = null;









  96         }
  97 
  98         if (null != cloneMethod) {





















  99             try {
 100                 Map<K, V> result = (Map<K, V>)cloneMethod.invoke(map, new Object[]{});
 101                 return result;
 102             } catch (Exception all) {
 103                 fail("clone() failed " + map.getClass().getSimpleName(), all);
 104                 return null;
 105             }









 106         } else {
 107             Constructor<? extends Map> copyConstructor;
 108             try {
 109                 copyConstructor = (Constructor<? extends Map>)map.getClass().getConstructor(new Class[]{Map.class});














































































































































































 110 
 111                 Map<K, V> result = (Map<K, V>)copyConstructor.newInstance(new Object[]{map});



 112 
 113                 return result;
 114             } catch (Exception all) {
 115                 return serialClone(map);
 116             }




 117         }




 118     }
 119 
 120     @Test(dataProvider = "Map<IntegerEnum,String>")
 121     public void testSerialization(String description, Map<IntegerEnum, String> map) {
 122         Object foo = new Object();
 123 
 124         Map<IntegerEnum, String> clone = mapClone(map);
 125         Map<IntegerEnum, String> serialClone = serialClone(map);
 126 
 127         assertEquals(map, map, description + ":should equal self");
 128         assertEquals(clone, map, description + ":should equal clone");
 129         assertEquals(map, clone, description + ": should equal orginal map");
 130         assertEquals(serialClone, map, description + ": should equal deserialized clone");
 131         assertEquals(map, serialClone, description + ": should equal original map");
 132         assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
 133         assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
 134 
 135         assertFalse(map.containsKey(EXTRA_KEY), description + ":unexpected key");
 136         assertFalse(clone.containsKey(EXTRA_KEY), description + ":unexpected key");
 137         assertFalse(serialClone.containsKey(EXTRA_KEY), description + ":unexpected key");
 138         map.put(EXTRA_KEY, EXTRA_VALUE);
 139         clone.put(EXTRA_KEY, EXTRA_VALUE);
 140         serialClone.put(EXTRA_KEY, EXTRA_VALUE);
 141         assertTrue(map.containsKey(EXTRA_KEY), description + ":missing key");
 142         assertTrue(clone.containsKey(EXTRA_KEY), description + ":missing key");
 143         assertTrue(serialClone.containsKey(EXTRA_KEY), description + ":missing key");
 144         assertSame(map.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
 145         assertSame(clone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
 146         assertSame(serialClone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
 147 
 148         assertEquals(map, map, description + ":should equal self");
 149         assertEquals(clone, map, description + ":should equal clone");
 150         assertEquals(map, clone, description + ": should equal orginal map");
 151         assertEquals(serialClone, map, description + ": should equal deserialized clone");
 152         assertEquals(map, serialClone, description + ": should equal original map");
 153         assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
 154         assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
 155     }
 156 
 157     static byte[] serializedForm(Object obj) {
 158         try {
 159             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 160             new ObjectOutputStream(baos).writeObject(obj);
 161             return baos.toByteArray();
 162         } catch (IOException e) {
 163             fail("Unexpected Exception", e);
 164             return null;


 165         }
 166     }
 167 
 168     static Object readObject(byte[] bytes) throws IOException, ClassNotFoundException {
 169         InputStream is = new ByteArrayInputStream(bytes);
 170         return new ObjectInputStream(is).readObject();



 171     }
 172 
 173     @SuppressWarnings("unchecked")
 174     static <T> T serialClone(T obj) {
 175         try {
 176             return (T)readObject(serializedForm(obj));
 177         } catch (IOException | ClassNotFoundException e) {
 178             fail("Unexpected Exception", e);
 179             return null;
 180         }
 181     }
 182 
 183     @DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
 184     private static Iterator<Object[]> makeMaps() {
 185         return Arrays.asList(
 186             // empty
 187             new Object[]{"HashMap", new HashMap()},
 188             new Object[]{"LinkedHashMap", new LinkedHashMap()},
 189             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(new HashMap(), IntegerEnum.class, String.class)},
 190             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(new HashMap())},
 191             // null hostile
 192             new Object[]{"EnumMap", new EnumMap(IntegerEnum.class)},
 193             new Object[]{"Hashtable", new Hashtable()},
 194             new Object[]{"TreeMap", new TreeMap()},
 195             new Object[]{"ConcurrentHashMap", new ConcurrentHashMap()},
 196             new Object[]{"ConcurrentSkipListMap", new ConcurrentSkipListMap()},
 197             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(new ConcurrentHashMap(), IntegerEnum.class, String.class)},
 198             new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(new EnumMap(IntegerEnum.class))},
 199             // filled
 200             new Object[]{"HashMap", fillMap(new HashMap())},
 201             new Object[]{"LinkedHashMap", fillMap(new LinkedHashMap())},
 202             new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(fillMap(new HashMap()), IntegerEnum.class, String.class)},
 203             new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(fillMap(new HashMap()))},
 204             // null hostile
 205             new Object[]{"EnumMap", fillMap(new EnumMap(IntegerEnum.class))},
 206             new Object[]{"Hashtable", fillMap(new Hashtable())},
 207             new Object[]{"TreeMap", fillMap(new TreeMap())},
 208             new Object[]{"ConcurrentHashMap", fillMap(new ConcurrentHashMap())},
 209             new Object[]{"ConcurrentSkipListMap", fillMap(new ConcurrentSkipListMap())},
 210             new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(fillMap(new ConcurrentHashMap()), IntegerEnum.class, String.class)},
 211             new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(fillMap(new EnumMap(IntegerEnum.class)))}).iterator();
 212     }
 213 
 214     private static Map<IntegerEnum, String> fillMap(Map<IntegerEnum, String> result) {
 215         for (int each = 0; each < TEST_SIZE; each++) {
 216             result.put(KEYS[each], VALUES[each]);
 217         }
 218 
 219         return result;



 220     }
 221 }