Как сравнить две карты по их значениям

Как сравнить две карты по их значениям? У меня есть две карты, содержащие одинаковые значения, и я хочу сравнить их по их значениям. Вот пример:

    Map a = new HashMap();
    a.put("foo", "bar"+"bar");
    a.put("zoo", "bar"+"bar");

    Map b = new HashMap();
    b.put(new String("foo"), "bar"+"bar");
    b.put(new String("zoo"), "bar"+"bar");

    System.out.println("equals: " + a.equals(b));            // obviously false

Как мне изменить код, чтобы получить истину?

Ответ 1

Ваши попытки построить разные строки с использованием конкатенации не удастся, поскольку они выполняются во время компиляции. Обе эти карты имеют одну пару; каждая пара будет иметь "foo" и "barbar" в качестве ключа/значения, используя одну и ту же строковую ссылку.

Предполагая, что вы действительно хотите сравнить наборы значений без ссылки на клавиши, это просто случай:

Set<String> values1 = new HashSet<>(map1.values());
Set<String> values2 = new HashSet<>(map2.values());
boolean equal = values1.equals(values2);

Возможно, что сравнение map1.values() с map2.values() будет работать, но также возможно, что порядок, в котором они будут возвращены, будет использоваться в сравнении равенства, что не то, что вы хотите.

Обратите внимание, что использование набора имеет свои проблемы - потому что вышеприведенный код будет считать карту { "a": "0" , "b": "0" } и { "c": "0" } до быть равным... значения все равно равны.

Если вы можете предоставить более точное определение того, что хотите, нам будет легче убедиться, что мы дадим вам правильный ответ.

Ответ 2

Правильный способ сравнения карт для равенства значений:

  • Убедитесь, что карты имеют одинаковый размер (!)
  • Получить набор ключей с одной карты
  • Для каждого ключа из этого набора, который вы извлекли, убедитесь, что значение, полученное из каждой карты для этого ключа, одинаково (если ключ отсутствует на одной карте, что является полным сбоем равенства)

Другими словами (минус обработка ошибок):

boolean equalMaps(Map<K,V>m1, Map<K,V>m2) {
   if (m1.size() != m2.size())
      return false;
   for (K key: m1.keySet())
      if (!m1.get(key).equals(m2.get(key)))
         return false;
   return true;
}

Ответ 3

Чтобы увидеть, имеют ли две карты одинаковые значения, вы можете сделать следующее:

  • Получить представления Collection<V> values()
  • Обернитесь в List<V>
  • Collections.sort эти списки
  • Проверьте, есть ли два списка equals

Что-то вроде этого работает (хотя его ограничения типов могут быть улучшены):

static <V extends Comparable<V>>
boolean valuesEquals(Map<?,V> map1, Map<?,V> map2) {
    List<V> values1 = new ArrayList<V>(map1.values());
    List<V> values2 = new ArrayList<V>(map2.values());
    Collections.sort(values1);
    Collections.sort(values2);
    return values1.equals(values2);
}

Жгут проводов:

Map<String, String> map1 = new HashMap<String,String>();
map1.put("A", "B");
map1.put("C", "D");

Map<String, String> map2 = new HashMap<String,String>();
map2.put("A", "D");
map2.put("C", "B");

System.out.println(valuesEquals(map1, map2)); // prints "true"

Это O(N log N) из-за Collections.sort.

См. также:


Проверить, являются ли ключи равными, проще, потому что они Set<K>:

map1.keySet().equals(map2.keySet())

См. также:

Ответ 4

Так как вы спросили о готовых Api... хорошо Apache Commons. Библиотека collection имеет класс CollectionUtils, который предоставляет простые в использовании методы для манипулирования/проверки коллекций, такие как пересечение, разность и объединение.

Ответ 5

Все они возвращаются равными. Они arent фактически делают сравнение, которое полезно для сортировки. Это будет больше похоже на компаратор:

private static final Comparator stringFallbackComparator = new Comparator() {
    public int compare(Object o1, Object o2) {
        if (!(o1 instanceof Comparable))
            o1 = o1.toString();
        if (!(o2 instanceof Comparable))
            o2 = o2.toString();
        return ((Comparable)o1).compareTo(o2);
    }
};

public int compare(Map m1, Map m2) {
    TreeSet s1 = new TreeSet(stringFallbackComparator); s1.addAll(m1.keySet());
    TreeSet s2 = new TreeSet(stringFallbackComparator); s2.addAll(m2.keySet());
    Iterator i1 = s1.iterator();
    Iterator i2 = s2.iterator();
    int i;
    while (i1.hasNext() && i2.hasNext())
    {
        Object k1 = i1.next();
        Object k2 = i2.next();
        if (0!=(i=stringFallbackComparator.compare(k1, k2)))
            return i;
        if (0!=(i=stringFallbackComparator.compare(m1.get(k1), m2.get(k2))))
            return i;
    }
    if (i1.hasNext())
        return 1;
    if (i2.hasNext())
        return -1;
    return 0;
}

Ответ 6

Этот вопрос старый, но актуальный.

Если вы хотите сравнить две карты по их значениям, соответствующим их ключам, вы можете сделать следующее:

public static <K, V> boolean mapEquals(Map<K, V> leftMap, Map<K, V> rightMap) {
    if (leftMap == rightMap) return true;
    if (leftMap == null || rightMap == null || leftMap.size() != rightMap.size()) return false;
    for (K key : leftMap.keySet()) {
        V value1 = leftMap.get(key);
        V value2 = rightMap.get(key);
        if (value1 == null && value2 == null)
            continue;
        else if (value1 == null || value2 == null)
            return false;
        if (!value1.equals(value2))
            return false;
    }
    return true;
}

Ответ 7

Если вы предполагаете, что могут быть двойные значения, единственный способ сделать это - поместить значения в списки, отсортировать их и сравнить списки, а именно:

List<String> values1 = new ArrayList<String>(map1.values());
List<String> values2 = new ArrayList<String>(map2.values());
Collections.sort(values1);
Collections.sort(values2);
boolean mapsHaveEqualValues = values1.equals(values2);

Если значения не могут содержать повторяющиеся значения, вы можете либо сделать это без сортировки с помощью наборов.

Ответ 8

Я не думаю, что есть инструмент "apache-common-like" для сравнения карт, поскольку равенство двух карт очень неоднозначно и зависит от потребностей разработчика и реализации карты...

Например, если вы сравниваете два хэш файла в java: - Вы можете просто сравнить ключ/значения одинаковы - Вы также можете сравнить, если ключи упорядочены одинаково - Вы также можете сравнить, если оставшаяся емкость одинаковая ... Вы можете сравнить много вещей!

Что такой инструмент будет делать при сравнении двух разных реализаций карты, таких как: - Одна карта позволяет использовать нулевые ключи - Другое исключение выполнения броузера на map2.get(null)

Лучше реализовать свое собственное решение в соответствии с тем, что вам действительно нужно сделать, и я думаю, что у вас уже есть ответы выше:)

Ответ 9

Результат равенства в вашем примере, очевидно, неверен, потому что вы сравниваете карту a с некоторыми значениями в ней с пустым отображением b (возможно, с ошибкой копирования и вставки). Я рекомендую использовать правильные имена переменных (чтобы можно было избежать подобных ошибок) и использовать также дженерики.

    Map<String, String> first = new HashMap<String, String>();
    first.put("f"+"oo", "bar"+"bar");
    first.put("fo"+"o", "bar"+"bar");

    Map second = new HashMap();
    second.put("f"+"oo", "bar"+"bar");
    second.put("fo"+"o", "bar"+"bar");

    System.out.println("equals: " + first.equals(second));

Конкатенация ваших строк не имеет никакого эффекта, потому что это будет сделано во время компиляции.

Ответ 10

@paweloque Для сравнения двух объектов Map в java вы можете добавить ключи карты в список, и с этими двумя списками вы можете использовать методы keepAll() и removeAll() и добавить их в другой общий список ключей и разные список ключей. Используя ключи общего списка и другого списка, вы можете выполнять итерацию по карте, используя равные вы можете сравнить карты.

Нижеприведенный код даст результат следующим образом: Перед {zoo = barbar, foo = barbar} После {zoo = barbar, foo = barbar} Равный: передбарбара Послебарбасс. Равный: передбарбара Послебарбасс.

package com.demo.compareExample

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;

public class Demo 
{
    public static void main(String[] args) 
    {
        Map<String, String> beforeMap = new HashMap<String, String>();
        beforeMap.put("foo", "bar"+"bar");
        beforeMap.put("zoo", "bar"+"bar");

        Map<String, String> afterMap = new HashMap<String, String>();
        afterMap.put(new String("foo"), "bar"+"bar");
        afterMap.put(new String("zoo"), "bar"+"bar");

        System.out.println("Before "+beforeMap);
        System.out.println("After "+afterMap);

        List<String> beforeList = getAllKeys(beforeMap);

        List<String> afterList = getAllKeys(afterMap);

        List<String> commonList1 = beforeList;
        List<String> commonList2 = afterList;
        List<String> diffList1 = getAllKeys(beforeMap);
        List<String> diffList2 = getAllKeys(afterMap);

        commonList1.retainAll(afterList);
        commonList2.retainAll(beforeList);

        diffList1.removeAll(commonList1);
        diffList2.removeAll(commonList2);

        if(commonList1!=null & commonList2!=null) // athough both the size are same
        {
            for (int i = 0; i < commonList1.size(); i++) 
            {
                if ((beforeMap.get(commonList1.get(i))).equals(afterMap.get(commonList1.get(i)))) 
                {
                    System.out.println("Equal: Before- "+ beforeMap.get(commonList1.get(i))+" After- "+afterMap.get(commonList1.get(i)));
                }
                else
                {
                    System.out.println("Unequal: Before- "+ beforeMap.get(commonList1.get(i))+" After- "+afterMap.get(commonList1.get(i)));
                }
            }
        }
        if (CollectionUtils.isNotEmpty(diffList1)) 
        {
            for (int i = 0; i < diffList1.size(); i++) 
            {
                System.out.println("Values present only in before map: "+beforeMap.get(diffList1.get(i)));
            }
        }
        if (CollectionUtils.isNotEmpty(diffList2)) 
        {
            for (int i = 0; i < diffList2.size(); i++) 
            {
                System.out.println("Values present only in after map: "+afterMap.get(diffList2.get(i)));
            }
        }
    }

    /**getAllKeys API adds the keys of the map to a list */
    private static List<String> getAllKeys(Map<String, String> map1)
    {
        List<String> key = new ArrayList<String>();
        if (map1 != null) 
        {
            Iterator<String> mapIterator = map1.keySet().iterator();
            while (mapIterator.hasNext()) 
            {
                key.add(mapIterator.next());
            }
        }
        return key;
    }
}

код >

Ответ 11

public boolean equalMaps(Map<?, ?> map1, Map<?, ?>map2) {

    if (map1==null || map2==null || map1.size() != map2.size()) {
        return false;
    }

    for (Object key: map1.keySet()) {
        if (!map1.get(key).equals(map2.get(key))) {
            return false;
        }
    }
    return true;
}

Ответ 12

Если вы хотите сравнить два Карты, ниже, код может помочь вам

(new TreeMap<String, Object>(map1).toString().hashCode()) == new TreeMap<String, Object>(map2).toString().hashCode()