diff --git a/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java b/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
index 8af75e0d..4344ca59 100644
--- a/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
+++ b/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java
@@ -3,6 +3,7 @@ package com.typesafe.config.impl;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -569,6 +570,58 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
         return sb.toString();
     }
 
+    private static boolean mapEquals(Map<String, ConfigValue> a,
+            Map<String, ConfigValue> b) {
+        Set<String> aKeys = a.keySet();
+        Set<String> bKeys = b.keySet();
+
+        if (!aKeys.equals(bKeys))
+            return false;
+
+        for (String key : aKeys) {
+            if (!a.get(key).equals(b.get(key)))
+                return false;
+        }
+        return true;
+    }
+
+    private static int mapHash(Map<String, ConfigValue> m) {
+        // the keys have to be sorted, otherwise we could be equal
+        // to another map but have a different hashcode.
+        List<String> keys = new ArrayList<String>();
+        keys.addAll(m.keySet());
+        Collections.sort(keys);
+
+        int valuesHash = 0;
+        for (String k : keys) {
+            valuesHash += m.get(k).hashCode();
+        }
+        return 41 * (41 + keys.hashCode()) + valuesHash;
+    }
+
+    @Override
+    protected boolean canEqual(Object other) {
+        return other instanceof ConfigObject;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        // note that "origin" is deliberately NOT part of equality
+        if (other instanceof ConfigObject) {
+            // optimization to avoid unwrapped() for two ConfigObject,
+            // which is what AbstractConfigValue does.
+            return canEqual(other) && mapEquals(this, ((ConfigObject) other));
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        // note that "origin" is deliberately NOT part of equality
+        return mapHash(this);
+    }
+
     private static UnsupportedOperationException weAreImmutable(String method) {
         return new UnsupportedOperationException(
                 "ConfigObject is immutable, you can't call Map.'" + method
diff --git a/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java b/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java
index 9ba462ff..1c2a0ba2 100644
--- a/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java
+++ b/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java
@@ -1,17 +1,14 @@
 package com.typesafe.config.impl;
 
 import java.util.AbstractMap;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import com.typesafe.config.ConfigException;
-import com.typesafe.config.ConfigObject;
 import com.typesafe.config.ConfigOrigin;
 import com.typesafe.config.ConfigValue;
 
@@ -83,62 +80,6 @@ final class SimpleConfigObject extends AbstractConfigObject {
         return value.keySet();
     }
 
-    private static boolean mapEquals(Map<String, AbstractConfigValue> a,
-            Map<String, AbstractConfigValue> b) {
-        Set<String> aKeys = a.keySet();
-        Set<String> bKeys = b.keySet();
-
-        if (!aKeys.equals(bKeys))
-            return false;
-
-        for (String key : aKeys) {
-            if (!a.get(key).equals(b.get(key)))
-                return false;
-        }
-        return true;
-    }
-
-    private static int mapHash(Map<String, AbstractConfigValue> m) {
-        // the keys have to be sorted, otherwise we could be equal
-        // to another map but have a different hashcode.
-        List<String> keys = new ArrayList<String>();
-        keys.addAll(m.keySet());
-        Collections.sort(keys);
-
-        int valuesHash = 0;
-        for (String k : keys) {
-            valuesHash += m.get(k).hashCode();
-        }
-        return 41 * (41 + keys.hashCode()) + valuesHash;
-    }
-
-    @Override
-    protected boolean canEqual(Object other) {
-        return other instanceof ConfigObject;
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        // note that "origin" is deliberately NOT part of equality
-        if (other instanceof SimpleConfigObject) {
-            // optimization to avoid unwrapped() for two SimpleConfigObject
-            // note: if this included "transformer" then we could never be
-            // equal to a non-SimpleConfigObject ConfigObject.
-            return canEqual(other)
-                    && mapEquals(value, ((SimpleConfigObject) other).value);
-        } else if (other instanceof ConfigObject) {
-            return super.equals(other);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        // note that "origin" is deliberately NOT part of equality
-        return mapHash(this.value);
-    }
-
     @Override
     public boolean containsValue(Object v) {
         return value.containsValue(v);
diff --git a/src/test/scala/com/typesafe/config/impl/ConfigValueTest.scala b/src/test/scala/com/typesafe/config/impl/ConfigValueTest.scala
index df5dbeaf..fd347705 100644
--- a/src/test/scala/com/typesafe/config/impl/ConfigValueTest.scala
+++ b/src/test/scala/com/typesafe/config/impl/ConfigValueTest.scala
@@ -60,13 +60,25 @@ class ConfigValueTest extends TestUtils {
         val aMap = configMap("a" -> 1, "b" -> 2, "c" -> 3)
         val sameAsAMap = configMap("a" -> 1, "b" -> 2, "c" -> 3)
         val bMap = configMap("a" -> 3, "b" -> 4, "c" -> 5)
+        // different keys is a different case in the equals implementation
+        val cMap = configMap("x" -> 3, "y" -> 4, "z" -> 5)
         val a = new SimpleConfigObject(fakeOrigin(), aMap)
         val sameAsA = new SimpleConfigObject(fakeOrigin(), sameAsAMap)
         val b = new SimpleConfigObject(fakeOrigin(), bMap)
+        val c = new SimpleConfigObject(fakeOrigin(), cMap)
 
         checkEqualObjects(a, a)
         checkEqualObjects(a, sameAsA)
+        checkEqualObjects(b, b)
+        checkEqualObjects(c, c)
         checkNotEqualObjects(a, b)
+        checkNotEqualObjects(a, c)
+        checkNotEqualObjects(b, c)
+
+        val root = a.asRoot()
+        checkEqualObjects(a, root)
+        checkNotEqualObjects(root, b)
+        checkNotEqualObjects(root, c)
     }
 
     @Test