## Introduction

There would have been scenarios where you would want to find all the differences between two map instances. In this post, we will explore what finding difference between two maps means and how using the Google Guava’s Maps#difference method we can do this.

## Finding difference between two maps

Let us say we have two maps, as shown below.

Map<String, Integer> left = Map.of( "a", 1, "b", 2, "c", 3); Map<String, Integer> right = Map.of( "b", 2, "c", 33, "d", 4);

Note: The Map.of static method was added in Java 9. See the Convenience Factory Methods for Collections post to learn more about it.

Here, we want to find all the differences between the two maps (*left* and *right*). We can classify the differences into four categories.

- The map entries present only in the left map (whose keys aren’t present in the right map)
- The map entries present only in the right map (whose keys aren’t present in the left map)
- The map entries present in both the maps, i.e., each of the entries’ keys and the values are the same between the two maps. This is the
of the two maps.**intersection** - The entries differing between the two maps. These are entries with keys in both the maps, but with different values.

In our example,

- The entry
`{a=1}`

is present only in the left map. - The entry
`{d=4}`

is present only in the right map. - The entry
`{b=2}`

is present in both the maps. - The entry with key
`c`

differs between both the maps. In the left map, the value is`3`

, while the right map has value mapped to key`c`

as`33`

.

There is no need to write a utility from scratch to find and return all these categories of differences. We can make use of Google Guava’s MapDifference for this.

We can get all the above explained categories of differences between two maps by calling the static utility method called **difference()** on the Maps utility class. Let us now explore the **Maps#difference** method in Google Guava.

## Google Guava MapDifference interface

When we call the **Maps#difference** utility method, it returns an instance of **MapDifference**. But before we dive into the **Maps#difference** method, let us first look at the **MapDifference** interface.

The MapDifference interface is declared as,

interface MapDifference<K extends @Nullable Object,V extends @Nullable Object>

It is a *generic interface* with two type parameters, **K** and **V**, which correspond to the types of the keys and values in the map, respectively. In short, it represents the differences between two maps.

### MapDifference interface methods

The MapDifference interface has the following methods. These correspond to the various categories of differences we saw earlier.

**areEqual():**This will return*true*if there are no differences between the two maps.**entriesOnlyOnLeft():**This will return a`Map<K, V>`

which has all the entries from the left map whose keys aren’t present in the right map. The returned map is*unmodifiable*.**entriesOnlyOnRight():**This will return a`Map<K, V>`

which has all the entries from the right map whose keys aren’t present in the left map. Again, the returned map is*unmodifiable*.**entriesInCommon():**This returns an*unmodifiable map*(`Map<K, V`

) which contains the entries which are present in both the maps.**entriesDiffering():**This returns an*unmodifiable map*containing keys which are present in both maps, but with difference values. Calling this, it returns a`Map<K, ValueDifference<V>>`

.

The **ValueDifference** is an interface (a package-private interface) as shown below. It has two methods to get the left and the right value.

interface ValueDifference<V extends @Nullable Object> { V leftValue(); V rightValue(); //equals and hashCode omitted }

## Maps#difference method in Google Guava

Let us now look at three overloaded **Maps#difference** method in the Google Guava utility class Maps.

The first version of the **difference** method we will see takes two Map instances (left and right) and computes the difference between them. It returns the difference as a `MapDifference<K, V>`

. This difference is an immutable snapshot and hence it will not be updated even if the map contents are updated later on.

The method signature is shown below.

public static <K extends @Nullable Object, V extends @Nullable Object> MapDifference<K, V> difference( Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) { ... }

### Finding difference between two maps using Maps#difference

Let us use the same example used earlier and find the difference between two maps using the Google Guava **Maps#difference** method.

Map<String, Integer> left = Map.of( "a", 1, "b", 2, "c", 3); Map<String, Integer>right = Map.of( "b", 2, "c", 33, "d", 4); MapDifference<String, Integer> diff = Maps.difference(left, right); System.out.println(diff.areEqual()); //false System.out.println(diff.entriesOnlyOnLeft()); //{a=1} System.out.println(diff.entriesOnlyOnRight()); //{d=4} System.out.println(diff.entriesInCommon()); //{b=2} System.out.println(diff.entriesDiffering()); //{c=(3, 33)}

- Calling the
**areEqual()**method returns*false*as the two maps are not “equal”. - The entry
`{a=1}`

is the only entry present in the left map. - The entry
`{d=4}`

is the only entry present in the right map. - There is only one common entry (same key and same value) (
`{b=2}`

). - Finally, there is one differing entry corresponding to the key
`c`

. In the left map, the value is`3,`

and in the right map, the value is`33`

.

The **toString*** *implementation of the **ValueDifference** interface returns a string by joining the left and the right values with a comma (,).

public String toString() { return "(" + left + ", " + right + ")"; }

The **MapDifference** implementation also has a useful *toString* representation, which includes all the categories of the differences.

Printing the **MapDifference** instance as below we get,

System.out.println(diff);

not equal: only on left={a=1}: only on right={d=4}: value differences={c=(3, 33)}

It starts the *toString* representation, by stating if the maps are equal or not. Then, it includes all the categories of the differences viz.,

- Entries present only on the left map.
- Entries present only on the right map.
- The differing entries.

It doesn’t include the common entries in the toString output.

It wouldn’t show a category if it is empty. For example, shown below, we have two maps with only differing entries. In this case, the *toString* of the *MapDifference* doesn’t include *only on left* and *only on right* categories.

Map<String, Integer> left = Map.of("a", 1); Map<String, Integer> right = Map.of("a", 11); System.out.println(Maps.difference(left, right)); //not equal: value differences={a=(1, 11)}

### Difference between two equal maps using Maps#difference

Let us look at an example when using the **difference** method with two equal maps.

Map<String, Integer> left = Map.of( "a", 1, "b", 2); Map<String, Integer> right = Map.of( "a", 1, "b", 2); diff = Maps.difference(left, right); System.out.println(diff.areEqual()); //true System.out.println(diff.entriesOnlyOnLeft()); // {} System.out.println(diff.entriesOnlyOnRight()); //{} System.out.println(diff.entriesInCommon()); //{a=1, b=2} System.out.println(diff.entriesDiffering()); //{} System.out.println(diff); //equal

- Calling
**areEqual()**returns true as the maps are equal. - Since the two maps are equal, the methods
*entriesOnlyOnLeft*and*entriesOnlyOnRight*returns empty maps. - The
*entriesInCommon*method returns the entire map content (`{a=1, b=2}`

) - There are no entries which differ between the two maps.

The *toString* of the *MapDifference* prints the string “equal” to indicate that the two maps are equal. Since there are no other categories of differences, nothing else is included in the toString result.

## Google Guava Equivalence

The second overloaded **Maps#difference** method allows us to pass an instance of Equivalence. Thus, let us take a small detour and learn about Equivalence.

An Equivalence is a strategy or a way to determine whether two instances are considered equivalent. It supports two strategies:

- The
**identity equivalence** - The
**equals equivalence**

### Identity and Equals equivalence

The Equivalence abstract class has two static methods viz., **identity()** and **equals()** which return an instance of **Equivalence** that does the equivalence check based on *identity* and *equality,* respectively.

The identity-based equivalence uses *instance identity *to compare values (is uses ==). In other words, two values or instances are *equivalent* if and only if they refer to the same instance (reference based equivalence). It uses **System.identityHashCode** to compute the hash code for an instance.

On the other hand, equivalence based on *equals* uses the object instance’s **equals()** and **hashCode()** to check for equivalence.

Equivalence<Object> identityEquivalence = Equivalence.identity(); String a = "abc"; String b = "abc"; System.out.println(identityEquivalence.equivalent(a, b)); //true System.out.println(identityEquivalence.equivalent(a, a)); //true System.out.println(identityEquivalence.equivalent(a, new String("abc"))); //false

In the above code, we have an instance of equivalence which works based on identity.

The **Equivalence** type has a method called **equivalent**, which takes two objects and returns true if the passed objects are considered equivalent.

We have two strings with the same value (”abc”),

- In the first call, we pass references to the two strings and we get
*true*as the result. This is because, in Java, two string constants with the same value will not create two string values on the heap. - In the second call, we pass the same reference, and it returns
*true***.** - Finally, in the last call, we pass the string reference ‘a’ and a new string with the same value (”abc”). Since these are not identical (the references are different), it returns
*false*as the result.

Let us do the same using *object equivalence. *We get an instance of equivalence which checks for equivalence using **Object#equals** using the **Equivalence#equals** method as shown below.

Since the first three calls passes two strings with the same value, they return back *true* as the result. The last call passes a string with a different value and the equivalence check returns a *false* back.

Equivalence<Object> objectEquivalence = Equivalence.equals(); System.out.println(objectEquivalence.equivalent(a, b)); //true System.out.println(objectEquivalence.equivalent(a, a)); //true System.out.println(objectEquivalence.equivalent(a, new String("abc"))); //true System.out.println(objectEquivalence.equivalent(a, new String("def"))); //false

Let us now look at the other methods in the **Equivalence** class.

### Equivalence#equivalentTo

The **Equivalence#equivalentTo** method takes a target value and returns a Predicate (Google Guava Predicate) that evaluates to *true* if and only if the input is equivalent to passed target value according to this *equivalence relation*.

In the below example, we pass a target value as the string “Java” by calling the **equivalentTo** method on the *identityEquivalence* instance. The returned Predicate will check if the passed input (to the Predicate) is *equivalent* to the target value (”Java”) as per the equivalence (identity equivalence). Hence, passing string literal “Java” to the predicate returns *true, *whereas creating a new string instance with the same value fails the (identity) equivalence check.

Predicate<Object> predicate = identityEquivalence.equivalentTo("Java"); System.out.println(predicate.test("Java")); //true System.out.println(predicate.test(new String("Java"))); //false

If we use an **object equivalence** in the same example, we will get *true* for both the calls and the predicate check will return *false* only when we pass a different string.

Predicate<Object> predicate = objectEquivalence.equivalentTo("Java"); System.out.println(predicate.test("Java")); //true System.out.println(predicate.test(new String("Java"))); //true System.out.println(predicate.test("C++")); //false

### Equivalence#onResultOf

The **onResultOf** takes a Function to convert from type **F** to type **T** and returns a new equivalence relation for the type **F** (**Equivalence<F>**). Remember, the formal type parameter of the **Equivalence** class is **T**. Hence, this method is used to convert a value of type **F** to type **T** and then evaluates equivalence. The result is that we have an **Equivalence** working on type **F**.

The method signature is shown below.

public final <F> Equivalence<F> onResultOf( Function<? super F, ? extends @Nullable T> function) { ... }

Returns a new equivalence relation for F, which evaluates equivalence by first applying function to the argument, then evaluating using the (*this*) equivalence.

For a pair of non-null objects *x* and *y*, `equivalence.onResultOf(function).equivalent(a, b)`

is *true* if and only if `equivalence.equivalent(function.apply(a), function.apply(b))`

is *true*.

Let us look at a couple of examples.

In the below code, we have a function to convert a string to an integer which represents the length of the string.

Next, we start from `Equivalence.equals()`

(which returns a `Equivalence<Object>`

) and call the onResultOf on it passing the function. This gives us a `Equivalence<String>`

.

Function<String, Integer> stringToItsLengthFunction = String::length; Equivalence<String> stringEquivalenceByLength = Equivalence.equals() .onResultOf(stringToItsLengthFunction); //FunctionalEquivalence

Now, when we call the **equivalent** method on the stringEquivalenceByLength instance passing two strings, it will use the passed function to convert both the strings to Integers and use the underlying **Equivalence **instance to check for equivalence (which is `Equivalence.equals()`

here).

In the below example, we pass two different strings of the same length. Since the function converts the string to an Integer and the equivalence check is based on that result, it gives back *true* as the result (*3.equals(3)* is *true*).

As the second call shows, using `Equivalence.equals()`

on the two strings we used will obviously return a false.

System.out.println(stringEquivalenceByLength.equivalent("abc", "def")); //true System.out.println(Equivalence.equals() .equivalent("abc", "def")); //false

Let us continue the chain and create another transformation. Below, we have a new function to convert an Integer to a String. Then we call the **onResultOf** on the earlier created Equivalence instance (*stringEquivalenceByLength*) to get an `Equivalence<Integer>`

.

What happens when we pass two Integers to the **equivalent** method is as follows:

- First, it uses the
*integerToString*function to convert both the Integer arguments to Strings. - Next, it checks equivalence using
*stringEquivalenceByLength*instance. This in-turn will work as seen earlier.- It first uses the
*stringToItsLengthFunction*function to map the string to its length (Integer). - Finally, it uses the underlying equivalence instance which is
`Equivalence.equals`

to check for equivalence.

- It first uses the

Function<Integer, String> integerToString = String::valueOf; Equivalence<Integer> integerEquivalenceByLength = stringEquivalenceByLength .onResultOf(integerToString); System.out.println(integerEquivalenceByLength.equivalent(1, 2)); //true System.out.println(integerEquivalenceByLength.equivalent(11, 2)); //false

In the first call, the integers 1 and 2, get transformed to strings “1” and “2”. Then, they get transformed to their lengths, which gives us 1 and 1 (two Integers). When using the **Equivalence.equals**, we get *true *as the result.

In the second call, the Integer → String → Integer transformation chain will map (11, 2) → (”11”, “2”) → (2, 1). Hence, the equals based equivalence check will return *false* as 2 is not equal to 1.

### Equivalence#wrap

The wrap method takes some object and wraps it and returns `Equivalence.Wrapper`

. Wrapper is a static nested class which overrides the *equals()* and *hashCode()* by delegating to the Equivalence (the Equivalence instance of which we call the **wrap()** method).

In other words, for two instances *a* and *b, *`wrap(a).equals(wrap(b))`

is *true *if and only if `equivalent(a, b)`

is *true*.

Let us use the Equivalence<String> which tests equivalence using the string lengths. After we wrap the two strings in **Wrapper**, calling *equals() *will delegate the call to the underlying Equivalence (`stringEquivalenceByLength.equivalent(a, b)`

).

Function<String, Integer> stringToItsLengthFunction = String::length; Equivalence<String> stringEquivalenceByLength = Equivalence.equals() .onResultOf(stringToItsLengthFunction); String a = "abcd"; String b = "efgh"; Equivalence.Wrapper<String> wrapper1 = stringEquivalenceByLength.wrap(a); Equivalence.Wrapper<String> wrapper2 = stringEquivalenceByLength.wrap(b); System.out.println(wrapper1.equals(wrapper2)); //true //same as System.out.println(stringEquivalenceByLength.equivalent(a, b)); //true

When passing two strings of different length, it returns a false.

System.out.println(stringEquivalenceByLength.wrap("ab") .equals(stringEquivalenceByLength.wrap("c"))); //false

## Equivalence#pairwise

When calling the **pairwise()** method on an Equivalence instance, it returns an equivalence over iterables based on the equivalence of their elements.

Its method signature is as follows, where **T** is the type parameter of the Equivalence and it returns a `Equivalence<Iterable<S>>`

where **S** is a subtype of **T**.

public final <S extends @Nullable T> Equivalence<Iterable<S>> pairwise() { ... }

Two iterables are considered equivalent if they both contain the same number of elements, and each pair of corresponding elements is equivalent according to this equivalence instance.

Let’s say we have two List<String> and we call **pairwise() **on **Equivalence.equals()**. Thus, it iterates over both the lists (element by element) and passes them to the **equivalent()** method of the **Equivalence** (equals Equivalence).

List<String> l1 = List.of("a", "b", "c"); List<String> l2 = List.of("a", "b", "c"); Equivalence<Iterable<String>> iterableEquivalence = Equivalence.equals() .pairwise(); System.out.println(iterableEquivalence.equivalent(l1, l2)); //true

## Maps#difference using an equivalence

Let us now use Maps#difference by passing an instance of Equivalence as the third argument, which determines how to compare values for equivalence.

Map<String, Integer> left = Map.of( "a", 1, "b", 2, "c", 3); Map<String, Integer> right = Map.of( "b", 2, "c", 9, "d", 4); MapDifference<String, Integer> diff = Maps.difference(left, right); System.out.println(diff);

In the above code, we have two maps and we compute the difference normally. This results in the entry with key `c`

ending up in the *value difference* category.

not equal: only on left={a=1}: only on right={d=4}: value differences={c=(3, 9)}

Let us now use the earlier used equivalence to compare integers based on the number of digits they have (by converting an Integer to a String and checking for its length).

Function<String, Integer> stringToItsLengthFunction = String::length; Function<Integer, String> integerToString = String::valueOf; Equivalence<Integer> integerEquivalenceByLength = Equivalence.equals() .onResultOf(stringToItsLengthFunction) .onResultOf(integerToString); MapDifference<String, Integer> diff = Maps.difference(left, right, integerEquivalenceByLength); System.out.println(diff);

Now, when comparing the values mapped to key `c`

, it compares `3`

with `9`

. Since both have the same length (1) and we used `Equivalence.equals`

as the underlying equivalence instance, they will be considered as equivalent. This gives us the below result.

not equal: only on left={a=1}: only on right={d=4}

## Maps#difference on a SortedMap

The last overloaded Maps#difference method works on a Java SortedMap. It returns a SortedMapDifference. A SortedMapDifference represents the differences between two sorted maps. The difference between a MapDifference and a SortedMapDifference is that the method return a SortedMap as shown below.

public interface SortedMapDifference<K extends @Nullable Object, V extends @Nullable Object> extends MapDifference<K, V> { @Override SortedMap<K, V> entriesOnlyOnLeft(); @Override SortedMap<K, V> entriesOnlyOnRight(); @Override SortedMap<K, V> entriesInCommon(); @Override SortedMap<K, ValueDifference<V>> entriesDiffering(); }

This overloaded **difference()** method computes the difference between two sorted maps using the comparator of the left map (or `Ordering.natural()`

if the left map uses the natural ordering of its elements).

Note from the Javadoc: Since this method uses **TreeMap** instances internally, the keys of the right map must all compare as distinct according to the comparator of the left map.

In the below example, the left map is a TreeMap with `Comparator.reverseOrder`

. It thus orders the keys in reverse order. Hence, the ordering among entries in the result (MapDifference) will use this reverse comparator as shown below (Key `e`

appears before key `d`

).

SortedMap<String, Integer> left = new TreeMap<>(Comparator.reverseOrder()); left.putAll(Map.of( "a", 1, "b", 2, "c", 3)); Map<String, Integer> right = new HashMap<>(Map.of( "b", 2, "c", 9, "d", 4, "e", 5)); System.out.println("Left map: " + left); System.out.println("Right map: " + right); MapDifference<String, Integer> diff = Maps.difference(left, right); System.out.println(diff);

Prints,

Left map: {c=3, b=2, a=1} Right map: {b=2, c=9, d=4, e=5} not equal: only on left={a=1}: only on right={e=5, d=4}: value differences={c=(3, 9)}

## Conclusion

In this post, we explored what finding difference between two maps means. It includes the following categories – finding entries present only in the left/right map, the common entries and the entries with different values. We explored the Google Guava’s **Maps#difference** method to find these. We also learnt about the Google Guava’s **Equivalence** class in detail and used it to when comparing the values from the two maps.

Check out the other google-guava utility classes and feature.