Improve correctness of LinkedHashMap and updates the tests.

Patch by: scottb
Review by: bobv


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2932 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
index 820ffa7..250f4fb 100644
--- a/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
@@ -21,8 +21,6 @@
 

 import java.lang.reflect.Field;

 import java.util.LinkedHashMap;

-import java.util.Set;

-import java.util.Map.Entry;

 

 /**

  * Custom field serializer for {@link java.util.LinkedHashMap} for the server

@@ -30,35 +28,27 @@
  */

 public final class LinkedHashMap_CustomFieldSerializer {

 

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   public static void deserialize(SerializationStreamReader streamReader,

       LinkedHashMap instance) throws SerializationException {

-    int size = streamReader.readInt();

-

-    for (int i = 0; i < size; ++i) {

-      Object key = streamReader.readObject();

-      Object value = streamReader.readObject();

-      instance.put(key, value);

-    }

+    Map_CustomFieldSerializerBase.deserialize(streamReader, instance);

   }

 

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   public static LinkedHashMap instantiate(SerializationStreamReader streamReader)

       throws SerializationException {

     boolean accessOrder = streamReader.readBoolean();

     return new LinkedHashMap(16, .75f, accessOrder);

   }

 

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   public static void serialize(SerializationStreamWriter streamWriter,

       LinkedHashMap instance) throws SerializationException {

     streamWriter.writeBoolean(getAccessOrder(instance));

-    int size = instance.size();

-    streamWriter.writeInt(size);

-

-    for (Entry entry : (Set<Entry>) instance.entrySet()) {

-      streamWriter.writeObject(entry.getKey());

-      streamWriter.writeObject(entry.getValue());

-    }

+    Map_CustomFieldSerializerBase.serialize(streamWriter, instance);

   }

 

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   private static boolean getAccessOrder(LinkedHashMap instance)

       throws SerializationException {

     Field accessOrderField;

@@ -76,5 +66,4 @@
       throw new SerializationException("Can't get accessOrder field", e);

     }

   }

-

 }

diff --git a/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java b/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
index 36a50e7..d061f78 100644
--- a/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
@@ -32,7 +32,7 @@
    * list with a head node. This reduces the special cases we have to deal with
    * in the list operations.
    * 
-   * Note that we duplicate the key from the underlying hashmap so we can find
+   * Note that we duplicate the key from the underlying hash map so we can find
    * the eldest entry. The alternative would have been to modify HashMap so more
    * of the code was directly usable here, but this would have added some
    * overhead to HashMap, or to reimplement most of the HashMap code here with
@@ -53,21 +53,21 @@
     }
 
     /**
-     * Add this node after the specified node in the chain.
-     * 
-     * @param node the node to insert after
+     * Add this node to the end of the chain.
      */
-    public void addAfter(ChainEntry node) {
-      update(node, node.next);
-    }
+    public void addToEnd() {
+      ChainEntry tail = head.prev;
 
-    /**
-     * Add this node before the specified node in the chain.
-     * 
-     * @param node the node to insert before
-     */
-    public void addBefore(ChainEntry node) {
-      update(node.prev, node);
+      // Chain is valid.
+      assert (head != null && tail != null);
+
+      // This entry is not in the list.
+      assert (next == null) && (prev == null);
+
+      // Update me.
+      prev = tail;
+      next = head;
+      tail.next = head.prev = this;
     }
 
     /**
@@ -76,36 +76,20 @@
     public void remove() {
       next.prev = prev;
       prev.next = next;
-      next = null;
-      prev = null;
-    }
-
-    private void update(ChainEntry prev, ChainEntry next) {
-      // This entry is not in the list.
-      assert (this.next == null) && (this.prev == null);
-
-      // Will not break the chain.
-      assert (prev != null && next != null);
-
-      // Update me.
-      this.prev = prev;
-      this.next = next;
-      next.prev = this;
-      prev.next = this;
+      next = prev = null;
     }
   }
 
   private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
 
     private final class EntryIterator implements Iterator<Entry<K, V>> {
-      // Current entry.
-      private ChainEntry current;
+      // The last entry that was returned from this iterator.
+      private ChainEntry last;
 
-      // Next entry. Used to allow removal of the current node.
+      // The next entry to return from this iterator.
       private ChainEntry next;
 
       public EntryIterator() {
-        current = head;
         next = head.next;
       }
 
@@ -113,22 +97,22 @@
         return next != head;
       }
 
-      public java.util.Map.Entry<K, V> next() {
-        if (next == null) {
+      public Map.Entry<K, V> next() {
+        if (next == head) {
           throw new NoSuchElementException();
         }
-        current = next;
+        last = next;
         next = next.next;
-        return current;
+        return last;
       }
 
       public void remove() {
-        if (current == null || current == head) {
+        if (last == null) {
           throw new IllegalStateException("No current entry");
         }
-        current.remove();
-        map.remove(current.getKey());
-        current = null;
+        last.remove();
+        map.remove(last.getKey());
+        last = null;
       }
     }
 
@@ -168,48 +152,44 @@
 
   /*
    * The head of the LRU/insert order chain, which is a doubly-linked circular
-   * list.
+   * list. The key and value of head should never be read.
    * 
    * The most recently inserted/accessed node is at the end of the chain, ie.
    * chain.prev.
    */
-  private transient ChainEntry head;
+  private final transient ChainEntry head = new ChainEntry();
 
   /*
    * The hashmap that keeps track of our entries and the chain. Note that we
    * duplicate the key here to eliminate changes to HashMap and minimize the
    * code here, at the expense of additional space.
    */
-  private transient HashMap<K, ChainEntry> map;
+  private final transient HashMap<K, ChainEntry> map = new HashMap<K, ChainEntry>();
 
   {
-    // Head's value should never be accessed.
-    head = new ChainEntry();
+    // Initialize the empty linked list.
     head.prev = head;
     head.next = head;
   }
 
   public LinkedHashMap() {
-    this(11, 0.75f, false);
   }
 
   public LinkedHashMap(int ignored) {
-    this(ignored, 0.75f, false);
+    super(ignored);
   }
 
   public LinkedHashMap(int ignored, float alsoIgnored) {
-    this(ignored, alsoIgnored, false);
+    super(ignored, alsoIgnored);
   }
 
   public LinkedHashMap(int ignored, float alsoIgnored, boolean accessOrder) {
-    super();
+    super(ignored, alsoIgnored);
     this.accessOrder = accessOrder;
-    this.map = new HashMap<K, ChainEntry>(ignored, alsoIgnored);
   }
 
   public LinkedHashMap(Map<? extends K, ? extends V> toBeCopied) {
-    this(toBeCopied.size());
-    putAll(toBeCopied);
+    this.putAll(toBeCopied);
   }
 
   @Override
@@ -245,11 +225,7 @@
   public V get(Object key) {
     ChainEntry entry = map.get(key);
     if (entry != null) {
-      if (accessOrder) {
-        // Move to the tail of the chain on access if requested.
-        entry.remove();
-        entry.addBefore(head);
-      }
+      recordAccess(entry);
       return entry.getValue();
     }
     return null;
@@ -261,7 +237,7 @@
     if (old == null) {
       ChainEntry newEntry = new ChainEntry(key, value);
       map.put(key, newEntry);
-      newEntry.addBefore(head);
+      newEntry.addToEnd();
       ChainEntry eldest = head.next;
       if (removeEldestEntry(eldest)) {
         eldest.remove();
@@ -271,11 +247,7 @@
     } else {
       V oldValue = old.getValue();
       old.setValue(value);
-      // If orders by access, move to end of execution block.
-      if (accessOrder) {
-        old.remove();
-        old.addBefore(head);
-      }
+      recordAccess(old);
       return oldValue;
     }
   }
@@ -295,7 +267,16 @@
     return map.size();
   }
 
-  protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+  @SuppressWarnings("unused")
+  protected boolean removeEldestEntry(Entry<K, V> eldest) {
     return false;
   }
+
+  private void recordAccess(ChainEntry entry) {
+    if (accessOrder) {
+      // Move to the tail of the chain on access.
+      entry.remove();
+      entry.addToEnd();
+    }
+  }
 }
diff --git a/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java b/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
index a930bda..f242d28 100644
--- a/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
+++ b/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
@@ -18,26 +18,21 @@
 import com.google.gwt.user.client.rpc.SerializationException;

 import com.google.gwt.user.client.rpc.SerializationStreamReader;

 import com.google.gwt.user.client.rpc.SerializationStreamWriter;

+import com.google.gwt.user.client.rpc.core.java.util.Map_CustomFieldSerializerBase;

 

 import java.util.LinkedHashMap;

 import java.util.Set;

 import java.util.Map.Entry;

 

 /**

- * Custom field serializer for {@link java.util.LinkedHashMap}, which is the

- * same as {@link java.util.HashMap}.

+ * Custom field serializer for {@link java.util.LinkedHashMap}, which uses

+ * JSNI.

  */

 public final class LinkedHashMap_CustomFieldSerializer {

 

   public static void deserialize(SerializationStreamReader streamReader,

       LinkedHashMap instance) throws SerializationException {

-    int size = streamReader.readInt();

-

-    for (int i = 0; i < size; ++i) {

-      Object key = streamReader.readObject();

-      Object value = streamReader.readObject();

-      instance.put(key, value);

-    }

+    Map_CustomFieldSerializerBase.deserialize(streamReader, instance);

   }

 

   public static LinkedHashMap instantiate(SerializationStreamReader streamReader)

@@ -49,13 +44,7 @@
   public static void serialize(SerializationStreamWriter streamWriter,

       LinkedHashMap instance) throws SerializationException {

     streamWriter.writeBoolean(getAccessOrder(instance));

-    int size = instance.size();

-    streamWriter.writeInt(size);

-    

-    for (Entry entry : (Set<Entry>) instance.entrySet()) {

-      streamWriter.writeObject(entry.getKey());

-      streamWriter.writeObject(entry.getValue());

-    }

+    Map_CustomFieldSerializerBase.serialize(streamWriter, instance);

   }

 

   private static native boolean getAccessOrder(LinkedHashMap instance) /*-{

diff --git a/user/test/com/google/gwt/emultest/EmulSuite.java b/user/test/com/google/gwt/emultest/EmulSuite.java
index 6e412d3..6d37d9e 100644
--- a/user/test/com/google/gwt/emultest/EmulSuite.java
+++ b/user/test/com/google/gwt/emultest/EmulSuite.java
@@ -42,6 +42,7 @@
 import com.google.gwt.emultest.java.util.HashMapTest;
 import com.google.gwt.emultest.java.util.HashSetTest;
 import com.google.gwt.emultest.java.util.IdentityHashMapTest;
+import com.google.gwt.emultest.java.util.LinkedHashMapTest;
 import com.google.gwt.emultest.java.util.LinkedListTest;
 import com.google.gwt.emultest.java.util.PriorityQueueTest;
 import com.google.gwt.emultest.java.util.StackTest;
@@ -84,6 +85,7 @@
     suite.addTestSuite(HashMapTest.class);
     suite.addTestSuite(HashSetTest.class);
     suite.addTestSuite(IdentityHashMapTest.class);
+    suite.addTestSuite(LinkedHashMapTest.class);
     suite.addTestSuite(LinkedListTest.class);
     suite.addTestSuite(PriorityQueueTest.class);
     suite.addTestSuite(StackTest.class);
diff --git a/user/test/com/google/gwt/emultest/java/util/HashMapTest.java b/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
index 1a68faa..9234393 100644
--- a/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
@@ -21,12 +21,14 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.Map.Entry;
 
 /**
  * Tests <code>HashMap</code>.
  */
+@SuppressWarnings("unchecked")
 public class HashMapTest extends TestMap {
   private static final int CAPACITY_16 = 16;
   private static final int CAPACITY_NEG_ONE_HALF = -1;
@@ -85,6 +87,16 @@
   private static final String VALUE_TEST_REMOVE = KEY_TEST_REMOVE + " - value";
   private static final String VALUE_VAL = "value";
 
+  private static void assertEmptyIterator(Iterator it) {
+    assertNotNull(it);
+    assertFalse(it.hasNext());
+    try {
+      it.next();
+      fail("Expected NoSuchElementException");
+    } catch (NoSuchElementException expected) {
+    }
+  }
+
   /**
    * Check the state of a newly constructed, empty HashMap.
    * 
@@ -106,8 +118,7 @@
     assertTrue(hashMap.entrySet().isEmpty());
     assertTrue(hashMap.entrySet().size() == 0);
 
-    assertNotNull(hashMap.entrySet().iterator());
-    assertFalse(hashMap.entrySet().iterator().hasNext());
+    assertEmptyIterator(hashMap.entrySet().iterator());
   }
 
   public String getModuleName() {
@@ -232,6 +243,7 @@
     Map.Entry entry = (Map.Entry) itSet.next();
     assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);
     assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_1);
+    assertEmptyIterator(itSet);
 
     // Check that entries in the entrySet are update correctly on overwrites
     hashMap.put(KEY_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_2);
@@ -241,6 +253,7 @@
     entry = (Map.Entry) itSet.next();
     assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);
     assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_2);
+    assertEmptyIterator(itSet);
 
     // Check that entries are updated on removes
     hashMap.remove(KEY_TEST_ENTRY_SET);
diff --git a/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java
index cf6a5e3..bb08a8b 100644
--- a/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java
@@ -32,9 +32,9 @@
 public class LinkedHashMapTest extends TestMap {

   // should be a method-level class, however to avoid serialization warning made

   // static instead.

-  static class TestRemoveEldestMap extends LinkedHashMap {

+  static class TestRemoveEldestMap<K, V> extends LinkedHashMap<K, V> {

 

-    public String expectedKey;

+    public K expectedKey;

     public boolean removeEldest;

 

     public TestRemoveEldestMap() {

@@ -46,7 +46,7 @@
     }

 

     @Override

-    public boolean removeEldestEntry(Map.Entry entry) {

+    public boolean removeEldestEntry(Map.Entry<K, V> entry) {

       if (removeEldest) {

         assertEquals(expectedKey, entry.getKey());

         return true;

@@ -119,6 +119,7 @@
    * 

    * @param hashMap

    */

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   private static void checkEmptyLinkedHashMapAssumptions(LinkedHashMap hashMap) {

     assertNotNull(hashMap);

     assertTrue(hashMap.isEmpty());

@@ -210,7 +211,7 @@
    * Test method for 'java.util.LinkedHashMap.containsKey(Object)'

    */

   public void testContainsKey() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, Integer> hashMap = new LinkedHashMap<String, Integer>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     assertFalse(hashMap.containsKey(KEY_TEST_CONTAINS_KEY));

@@ -227,7 +228,7 @@
    * Test method for 'java.util.LinkedHashMap.containsValue(Object)'

    */

   public void testContainsValue() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, Integer> hashMap = new LinkedHashMap<String, Integer>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     assertFalse("check contains of empty map",

@@ -247,18 +248,18 @@
    * Test method for 'java.util.LinkedHashMap.entrySet()'

    */

   public void testEntrySet() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

-    Set entrySet = hashMap.entrySet();

+    Set<Entry<String, String>> entrySet = hashMap.entrySet();

     assertNotNull(entrySet);

 

     // Check that the entry set looks right

     hashMap.put(KEY_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_1);

     entrySet = hashMap.entrySet();

     assertEquals(entrySet.size(), SIZE_ONE);

-    Iterator itSet = entrySet.iterator();

-    Map.Entry entry = (Map.Entry) itSet.next();

+    Iterator<Entry<String, String>> itSet = entrySet.iterator();

+    Map.Entry<String, String> entry = itSet.next();

     assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);

     assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_1);

 

@@ -267,7 +268,7 @@
     entrySet = hashMap.entrySet();

     assertEquals(entrySet.size(), SIZE_ONE);

     itSet = entrySet.iterator();

-    entry = (Map.Entry) itSet.next();

+    entry = itSet.next();

     assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);

     assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_2);

 

@@ -284,8 +285,8 @@
     hashMap.put("A", "B");

     LinkedHashMap<String, String> dummy = new LinkedHashMap<String, String>();

     dummy.put("A", "b");

-    Entry bogus = (Entry) dummy.entrySet().iterator().next();

-    Set entrySet = hashMap.entrySet();

+    Entry<String, String> bogus = dummy.entrySet().iterator().next();

+    Set<Entry<String, String>> entrySet = hashMap.entrySet();

     boolean removed = entrySet.remove(bogus);

     assertEquals(removed, false);

     assertEquals(hashMap.get("A"), "B");

@@ -317,7 +318,7 @@
    * Test method for 'java.util.LinkedHashMap.get(Object)'.

    */

   public void testGet() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     assertNull(hashMap.get(KEY_TEST_GET));

@@ -336,7 +337,7 @@
    * Test method for 'java.util.AbstractMap.hashCode()'.

    */

   public void testHashCode() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     // Check that hashCode changes

@@ -399,7 +400,7 @@
     LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

-    Set keySet = hashMap.keySet();

+    Set<String> keySet = hashMap.keySet();

     System.err.println("keySet:" + keySet);

     assertNotNull(keySet);

     assertTrue(keySet.isEmpty());

@@ -416,7 +417,7 @@
    * Test method for 'java.util.LinkedHashMap.LinkedHashMap()'.

    */

   public void testLinkedHashMap() {

-    LinkedHashMap hashMap = new LinkedHashMap();

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();

     checkEmptyLinkedHashMapAssumptions(hashMap);

   }

 

@@ -424,13 +425,13 @@
    * Test method for 'java.util.LinkedHashMap.LinkedHashMap(int)'

    */

   public void testLinkedHashMapInt() {

-    LinkedHashMap hashMap = new LinkedHashMap(CAPACITY_16);

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>(CAPACITY_16);

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     // TODO(mmendez): how do we verify capacity?

     boolean failed = true;

     try {

-      new LinkedHashMap(-SIZE_ONE);

+      new LinkedHashMap<String, String>(-SIZE_ONE);

     } catch (Throwable ex) {

       if (ex instanceof IllegalArgumentException) {

         failed = false;

@@ -441,7 +442,7 @@
       fail("Failure testing new LinkedHashMap(-1)");

     }

 

-    LinkedHashMap zeroSizedLinkedHashMap = new LinkedHashMap(0);

+    LinkedHashMap<String, String> zeroSizedLinkedHashMap = new LinkedHashMap<String, String>(0);

     assertNotNull(zeroSizedLinkedHashMap);

   }

 

@@ -450,7 +451,8 @@
    */

   public void testLinkedHashMapIntFloat() {

 

-    LinkedHashMap hashMap = new LinkedHashMap(CAPACITY_16, LOAD_FACTOR_ONE_HALF);

+    LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>(CAPACITY_16,

+        LOAD_FACTOR_ONE_HALF);

     checkEmptyLinkedHashMapAssumptions(hashMap);

 

     // TODO(mmendez): how do we verify capacity and load factor?

@@ -458,7 +460,7 @@
     // Test new LinkedHashMap(-1, 0.0F)

     boolean failed = true;

     try {

-      new LinkedHashMap(CAPACITY_NEG_ONE_HALF, LOAD_FACTOR_ZERO);

+      new LinkedHashMap<String, String>(CAPACITY_NEG_ONE_HALF, LOAD_FACTOR_ZERO);

     } catch (Throwable ex) {

       if (ex instanceof IllegalArgumentException) {

         failed = false;

@@ -472,7 +474,7 @@
     // Test new LinkedHashMap(0, -1.0F)

     failed = true;

     try {

-      new LinkedHashMap(CAPACITY_ZERO, LOAD_FACTOR_NEG_ONE);

+      new LinkedHashMap<String, String>(CAPACITY_ZERO, LOAD_FACTOR_NEG_ONE);

     } catch (Throwable ex) {

       if (ex instanceof IllegalArgumentException) {

         failed = false;

@@ -484,7 +486,7 @@
     }

 

     // Test new LinkedHashMap(0,0F);

-    hashMap = new LinkedHashMap(CAPACITY_ZERO, LOAD_FACTOR_ONE_TENTH);

+    hashMap = new LinkedHashMap<String, String>(CAPACITY_ZERO, LOAD_FACTOR_ONE_TENTH);

     assertNotNull(hashMap);

   }

 

@@ -492,7 +494,7 @@
    * Test method for 'java.util.LinkedHashMap.LinkedHashMap(Map)'

    */

   public void testLinkedHashMapMap() {

-    LinkedHashMap srcMap = new LinkedHashMap();

+    LinkedHashMap<Integer, Integer> srcMap = new LinkedHashMap<Integer, Integer>();

     assertNotNull(srcMap);

     checkEmptyLinkedHashMapAssumptions(srcMap);

 

@@ -500,16 +502,16 @@
     srcMap.put(INTEGER_2, INTEGER_22);

     srcMap.put(INTEGER_3, INTEGER_33);

 

-    LinkedHashMap hashMap = cloneLinkedHashMap(srcMap);

+    LinkedHashMap<Integer, Integer> hashMap = cloneLinkedHashMap(srcMap);

     assertFalse(hashMap.isEmpty());

     assertTrue(hashMap.size() == SIZE_THREE);

 

-    Collection valColl = hashMap.values();

+    Collection<Integer> valColl = hashMap.values();

     assertTrue(valColl.contains(INTEGER_11));

     assertTrue(valColl.contains(INTEGER_22));

     assertTrue(valColl.contains(INTEGER_33));

 

-    Collection keyColl = hashMap.keySet();

+    Collection<Integer> keyColl = hashMap.keySet();

     assertTrue(keyColl.contains(INTEGER_1));

     assertTrue(keyColl.contains(INTEGER_2));

     assertTrue(keyColl.contains(INTEGER_3));

@@ -631,7 +633,7 @@
   }

 

   public void testRemoveEldest() {

-    TestRemoveEldestMap m = new TestRemoveEldestMap(false);

+    TestRemoveEldestMap<String, String> m = new TestRemoveEldestMap<String, String>(false);

     m.put("A", "A");

     m.put("B", "B");

     m.put("C", "C");

@@ -642,18 +644,15 @@
     m.expectedKey = "A";

     m.put("E", "E");

     m.put("B", "New-B");

-    Iterator<Map.Entry> entries = m.entrySet().iterator();

-    Map.Entry first = entries.next();

+    Iterator<Map.Entry<String, String>> entries = m.entrySet().iterator();

+    Map.Entry<String, String> first = entries.next();

     assertEquals("B", first.getKey());

     assertEquals("New-B", first.getValue());

     assertEquals(4, m.size());

   }

 

   public void testRemoveEldestMapLRU() {

-    TestRemoveEldestMap m;

-    Iterator<Map.Entry> entries;

-    Map.Entry first;

-    m = new TestRemoveEldestMap(true);

+    TestRemoveEldestMap<String, String> m = new TestRemoveEldestMap<String, String>(true);

     m.put("A", "A");

     m.put("B", "B");

     m.put("C", "C");

@@ -665,8 +664,8 @@
     m.put("E", "E");

 

     m.put("C", "New-C");

-    entries = m.entrySet().iterator();

-    first = entries.next();

+    Iterator<Map.Entry<String, String>> entries = m.entrySet().iterator();

+    Map.Entry<String, String> first = entries.next();

     assertEquals("A", first.getKey());

     assertEquals("D", entries.next().getKey());

     assertEquals("E", entries.next().getKey());

@@ -701,7 +700,7 @@
     hashMap.put(KEY_1, VALUE_1);

     hashMap.put(KEY_2, VALUE_2);

     hashMap.put(KEY_3, VALUE_3);

-    LinkedHashMap srcMap = cloneLinkedHashMap(hashMap);

+    LinkedHashMap<String, String> srcMap = cloneLinkedHashMap(hashMap);

     hashMap.putAll(srcMap);

     assertEquals(hashMap.size(), SIZE_THREE);

 

@@ -741,6 +740,7 @@
     assertEquals(val, VALUE_VAL);

   }

 

+  @SuppressWarnings("unchecked") // raw Map/LinkedHashMap

   @Override

   protected Map makeEmptyMap() {

     return new LinkedHashMap();

@@ -755,6 +755,7 @@
    * @param hashMap the LinkedHashMap to be copied

    * @return the copy

    */

+  @SuppressWarnings("unchecked") // raw LinkedHashMap

   private LinkedHashMap cloneLinkedHashMap(LinkedHashMap hashMap) {

     if (GWT.isScript()) {

       return new LinkedHashMap(hashMap);