java - 比较两张 map

标签 java dictionary

我有两张 map 声明为 Map<String, Object> . Object这里可能是另一个 Map<String, Object> (等等)。我想在不知道深度的情况下检查两张 map 是否完全相同。我可以比较 toString() 的输出,而不是使用递归在每张 map 上调用?或者有没有更简单的方法来比较 map ?

最佳答案

快速解答

您应该使用 equals 方法,因为这是为了执行您想要的比较。 toString() 本身就像 equals 一样使用迭代器,但它是一种效率较低的方法。此外,正如@Teepeemm 指出的那样, toString 受元素顺序(基本上是迭代器返回顺序)的影响,因此不能保证为 2 个不同的 map 提供相同的输出(特别是如果我们比较两个不同的 map ) .

注意/警告:您的问题和我的回答假定实现 map 接口(interface)的类尊重预期的 toStringequals 行为。默认的 java 类会这样做,但需要检查自定义映射类以验证预期的行为。

见:http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

boolean equals(Object o)

Compares the specified object with this map for equality. Returns true if the given object is also a map and the two maps represent the same mappings. More formally, two maps m1 and m2 represent the same mappings if m1.entrySet().equals(m2.entrySet()). This ensures that the equals method works properly across different implementations of the Map interface.

Java 源码中的实现 (java.util.AbstractMap)

此外,java 本身负责遍历所有元素并进行比较,因此您不必这样做。看看 AbstractMap 的实现,它被 HashMap 等类使用:

 // Comparison and hashing

    /**
     * Compares the specified object with this map for equality.  Returns
     * <tt>true</tt> if the given object is also a map and the two maps
     * represent the same mappings.  More formally, two maps <tt>m1</tt> and
     * <tt>m2</tt> represent the same mappings if
     * <tt>m1.entrySet().equals(m2.entrySet())</tt>.  This ensures that the
     * <tt>equals</tt> method works properly across different implementations
     * of the <tt>Map</tt> interface.
     *
     * <p>This implementation first checks if the specified object is this map;
     * if so it returns <tt>true</tt>.  Then, it checks if the specified
     * object is a map whose size is identical to the size of this map; if
     * not, it returns <tt>false</tt>.  If so, it iterates over this map's
     * <tt>entrySet</tt> collection, and checks that the specified map
     * contains each mapping that this map contains.  If the specified map
     * fails to contain such a mapping, <tt>false</tt> is returned.  If the
     * iteration completes, <tt>true</tt> is returned.
     *
     * @param o object to be compared for equality with this map
     * @return <tt>true</tt> if the specified object is equal to this map
     */
    public boolean equals(Object o) {
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<K,V> m = (Map<K,V>) o;
        if (m.size() != size())
            return false;

        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {
                    if (!(m.get(key)==null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }

        return true;
    }

比较两种不同类型的 map

toString 在比较 TreeMapHashMap 时惨遭失败,尽管 equals 确实比较内容正确。

代码:

public static void main(String args[]) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("2", "whatever2");
map.put("1", "whatever1");
TreeMap<String, Object> map2 = new TreeMap<String, Object>();
map2.put("2", "whatever2");
map2.put("1", "whatever1");

System.out.println("Are maps equal (using equals):" + map.equals(map2));
System.out.println("Are maps equal (using toString().equals()):"
        + map.toString().equals(map2.toString()));

System.out.println("Map1:"+map.toString());
System.out.println("Map2:"+map2.toString());
}

输出:

Are maps equal (using equals):true
Are maps equal (using toString().equals()):false
Map1:{2=whatever2, 1=whatever1}
Map2:{1=whatever1, 2=whatever2}

关于java - 比较两张 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24814577/

相关文章:

java - SwingWorker 和 SwingUtilities.invokeLater 的区别

java - 通过指定键和值类型扩展映射

python - 为什么我不能向字典添加更多键? - Python

javascript - 从特定飞行计划航路点获取 GPS 坐标

python - 无需循环即可替换 Pandas 列中的多个值

java - MySQL 上的 Hibernate 乐观锁异常

java - 调整 JFrame 大小后组件重新定位,并通过拖动鼠标手动调整右上角大小

java - Postgres : Query in Idle Transaction State

java - 如何在 cucumber 与 Selenium 的步骤中进行断言

python - 将 SeqIO 字典写入 Fasta 文件