简体   繁体   中英

How do I confirm that two ImmutableMaps have the exact same (key,value) pairs in them?

I need to do this for a unit test. The method being tested returns an ImmutbaleMap and I need to be able to compare it with one that I already have. One way is to get key sets for both(keySets()), run through them and compare the values returned from both maps for those keys. However that to me seems a little inefficient. Is there a better/preferred way to do this ?

If both the keys and the values implement equals() correctly, you can simply use Map.equals() :

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.

If they don't, I doubt you'll find a one-liner that works out of the box. I expect you'd have to implement the comparison yourself. It's not hard to do:

  • If the symmetric difference between the two key sets is not empty, you're done.
  • Otherwise, iterate over one map, looking up the same key in the other and comparing the values (using whatever comparison method is appropriate).

This can be easily encapsulated into a helper function, perhaps parameterised by the value comparator.

Complement to @NPE's answer...

Since your values do not implement .equals() / .hashCode() correctly, a simple equals on maps will not work; but you use Guava; theefore you have the option of implementing an Equivalence .

This means, if the class of your values is Foo :

  • you'll need to implement an Equivalence<Foo> :
  • your map will have to be a Map<X, Equivalence.Wrapper<Foo>> .

With this, you'll be able to use Map 's .equals() .

You'll have to add values using Equivalence's .wrap() method. See here for an example of an Equivalence implementation.

Another choice would be to use plain Map, write impmementation of Equivalence and use following difference method from Maps class

MapDifference<K,V> difference(Map<? extends K,? extends V> left,
                                           Map<? extends K,? extends V> right,
                                           Equivalence<? super V> valueEquivalence)

I would prefer this way as it will not alter the Map types (won't do it just to calculate difference or to check equality).

Why should map1.entrySet().equals(map2.entrySet()) not work? The EntrySet.equals() method refers to the Map.contains() method which should work for your values whether they implement equals() or not (in this case you probably have an IdentityHashMap underlying).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM