102. Comparing two arrays lexicographically

Starting with JDK 9, we can compare two arrays lexicographically via the Arrays.compare() methods. Since there is no need to reinvent the wheel, just upgrade to JDK 9 and let's dive into it.

A lexicographic comparison of two arrays may return the following:

  • 0, if the given arrays are equal and contain the same elements in the same order
  • A value less than 0 if the first array is lexicographically less than the second array
  • A value greater than 0 if the first array is lexicographically greater than the second array

If the first array length is less than the second array length, then the first array is lexicographically less than the second array. If the arrays have the same length, contain primitives, and share a common prefix, then the lexicographic comparison is the result of comparing two elements, precisely as Integer.compare(int, int), Boolean.compare(boolean, boolean), Byte.compare(byte, byte), and so on. If the arrays contain Object, then the lexicographic comparison is relying on the given Comparator or on the Comparable implementation.

First, let's consider the following arrays of primitives:

int[] integers1 = {3, 4, 5, 6, 1, 5};
int[] integers2 = {3, 4, 5, 6, 1, 5};
int[] integers3 = {3, 4, 5, 6, 1, 3};

Now, integers1 is lexicographically equal to integers2 because they are equal and contain the same elements in the same order, int compare(int[] a, int[] b):

int i12 = Arrays.compare(integers1, integers2); // 0

However, integers1 is lexicographically greater than integers3, since they share the same prefix (3, 4, 5, 6, 1), but for the last element, Integer.compare(5,3) returns a value greater than 0 since 5 is greater than 3:

int i13 = Arrays.compare(integers1, integers3); // 1

A lexicographical comparison can be accomplished on different ranges of the arrays. For example, the following example compares integers1 and integers3 in the range [3, 6) via the int compare(int[] a, int aFromIndex, int aToIndex, int[] b, int bFromIndex, int bToIndex) method:

int is13 = Arrays.compare(integers1, 3, 6, integers3, 3, 6); // 1

For arrays of Object, the Arrays class also provides a set of dedicated compare() methods. Remember the Melon class? Well, in order to compare two arrays of Melon without an explicit Comparator, we need to implement the Comparable interface and implement the compareTo() method. Let's assume that we are relying on melon weights as follows:

public class Melon implements Comparable {

private final String type;
private final int weight;

@Override
public int compareTo(Object o) {
Melon m = (Melon) o;

return Integer.compare(this.getWeight(), m.getWeight());
}

// constructor, getters, equals() and hashCode() omitted for brevity
}
Note that the lexicographic comparison of arrays of Object doesn't rely on equals(). It requires an explicit Comparator or Comparable elements.

Let's assume the following arrays of Melon:

Melon[] melons1 = {new Melon("Horned", 1500), new Melon("Gac", 1000)};
Melon[] melons2 = {new Melon("Horned", 1500), new Melon("Gac", 1000)};
Melon[] melons3 = {new Melon("Hami", 1600), new Melon("Gac", 800)};

And, let's compare lexicographically melons1 with melons2 via <T extends Comparable<? super T>> int compare(T[] a, T[] b):

int m12 = Arrays.compare(melons1, melons2); // 0

Since melons1 and melons2 are identical, the result is 0.

Now, let's do the same thing with melons1 and melons3. This time, the result will be negative, which means that melons1 is lexicographically less than melons3. This is true since, at index 0, the Horned melon has a weight of 1,500 g, which is less than the weight of the Hami melon, which is 1,600 g:

int m13 = Arrays.compare(melons1, melons3); // -1

We can perform the comparison in different ranges of the arrays via the <T extends Comparable<? super T>> int compare(T[] a, int aFromIndex, int aToIndex, T[] b, int bFromIndex, int bToIndex) method. For example, in the common range [1, 2), melons1 is lexicographically greater than melons2, since the weight of Gac is 1,000g in melons1 and 800g in melons3:

int ms13 = Arrays.compare(melons1, 1, 2, melons3, 1, 2); // 1

If we don't want to rely on Comparable elements (implement Comparable), we can pass in a Comparator via the <T> int compare(T[] a, T[] b, Comparator<? super T> cmp) method:

Comparator<Melon> byType = Comparator.comparing(Melon::getType);
int mt13 = Arrays.compare(melons1, melons3, byType); // 14

Using ranges is also possible by means of <T> int compare(T[] a, int aFromIndex, int aToIndex, T[] b, int bFromIndex, int bToIndex, Comparator<? super T> cmp):

int mrt13 = Arrays.compare(melons1, 1, 2, melons3, 1, 2, byType); // 0
If the arrays of numbers should be treated unsigned, then rely on the bunch of Arrays.compareUnsigned​() methods, which are available for byte, short, int, and long.

To compare two strings lexicographically, rely on String.compareTo() and int compareTo(String anotherString).
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.197.136