Optimizes AbstractMap#equals and EntrySet#contains

Reduces 2 lookups to 1 lookup in most cases.

Change-Id: If1c80baf00e00145861d9ed6ebf4bd78770614c5
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
index 3e86ee2..b22b121 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractHashMap.java
@@ -42,12 +42,7 @@
     @Override
     public boolean contains(Object o) {
       if (o instanceof Map.Entry) {
-        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
-        Object key = entry.getKey();
-        if (AbstractHashMap.this.containsKey(key)) {
-          Object value = AbstractHashMap.this.get(key);
-          return AbstractHashMap.this.equals(entry.getValue(), value);
-        }
+        return containsEntry((Map.Entry<?, ?>) o);
       }
       return false;
     }
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractMap.java b/user/super/com/google/gwt/emul/java/util/AbstractMap.java
index eae9667..cb57158 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractMap.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractMap.java
@@ -113,6 +113,23 @@
     return false;
   }
 
+  boolean containsEntry(Map.Entry<?, ?> entry) {
+    Object key = entry.getKey();
+    Object value = entry.getValue();
+    Object ourValue = get(key);
+
+    if (!Objects.equals(value, ourValue)) {
+      return false;
+    }
+
+    // Perhaps it was null and we don't contain the key?
+    if (ourValue == null && !containsKey(key)) {
+      return false;
+    }
+
+    return true;
+  }
+
   public abstract Set<Entry<K, V>> entrySet();
 
   @Override
@@ -129,12 +146,7 @@
     }
 
     for (Entry<?, ?> entry : otherMap.entrySet()) {
-      Object otherKey = entry.getKey();
-      Object otherValue = entry.getValue();
-      if (!containsKey(otherKey)) {
-        return false;
-      }
-      if (!Objects.equals(otherValue, get(otherKey))) {
+      if (!containsEntry(entry)) {
         return false;
       }
     }
diff --git a/user/super/com/google/gwt/emul/java/util/EnumMap.java b/user/super/com/google/gwt/emul/java/util/EnumMap.java
index 1ec4b29..6934370 100644
--- a/user/super/com/google/gwt/emul/java/util/EnumMap.java
+++ b/user/super/com/google/gwt/emul/java/util/EnumMap.java
@@ -37,12 +37,7 @@
     @Override
     public boolean contains(Object o) {
       if (o instanceof Map.Entry) {
-        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
-        Object key = entry.getKey();
-        if (EnumMap.this.containsKey(key)) {
-          Object value = EnumMap.this.get(key);
-          return Objects.equals(entry.getValue(), value);
-        }
+        return containsEntry((Map.Entry<?, ?>) o);
       }
       return false;
     }
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 6b7f958..907e8ed 100644
--- a/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
@@ -128,14 +128,8 @@
 
     @Override
     public boolean contains(Object o) {
-      if (!(o instanceof Map.Entry)) {
-        return false;
-      }
-      Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
-      Object key = entry.getKey();
-      if (LinkedHashMap.this.containsKey(key)) {
-        Object value = LinkedHashMap.this.get(key);
-        return Objects.equals(entry.getValue(), value);
+      if (o instanceof Map.Entry) {
+        return containsEntry((Map.Entry<?, ?>) o);
       }
       return false;
     }