Java 11 Developer Certification - Array Manipulation
October 30, 2020
What we are covering in this lesson
- Arrays class
- Search and comparision methods
- Data Manipulation methods
- Data Transformation methods
- Array search methods
Arrays class
Javadoc definition of java.util.Arrays class states it contains various methods for manipulating arrays (such as sorting and searching). This class also contains a static factory that allows arrays to be viewed as lists.
Arrays
class has many methods which can help us manipulate data in the array.
Usually when we have to work with arrays, we often end up using some of the methods of Arrays class in order to save time. We will look at some of these methods in this section.
We will have a look at some of the methods which can be used from this Arrays class.
Search and comparision methods
The Arrays class comparision methods are
- compare (introduced in Java 9)
- compareUnsigned (introduced in Java 9)
- deepEquals
- equals
Method for search are
- binarySearch
- matches (introduced in Java 9)
Data Manipulation methods
The method for data manipulation in an array are mentioned below
- deepHashCode
- deepToString
- fill
- hashCode
- parallelPrefix (introduced in Java 8)
- parallelSort (introduced in Java 8)
- parallelSetAll (introduced in Java 8)
- setAll (introduced in Java 8)
- sort
- toString
Data Transformation methods
Below methods are used for data transformation in an array
- asList
- copyOf
- copyOfRange
- spliterator (introduced in Java 8)
- stream (introduced in Java 8)
Arrays.equals
method looks at the elements in the array (and the order as well) to determine if the arrays are equal. Object.equals
method checks the reference and only objects with same reference are considered equal.
The Arrays.compare
method uses prefix
which is the common set of elements starting at element index 0, so if we have teo arrays with same set of elements, comparing them will return a prefix equal to the entire set of elements. In short, the common elements set form the prefix. compare
method also follow the below rules
- If
Arrays.equals
is true, return 0 - If first array passed to parameter is null, return -1, else if second array is null, return 1
- If length of first array is 0, return (0-length of second array)
- If length of second array is 0, return (length of first array-0)
- If one array represents the entire prefix of another, the return value is the difference in length of the array, which will be negative if we compare smaller array to a larger array
- If no prefix is identified, then the first element of each array is compared lexicographically, which will ne negative if first element of first array is smaller than first element of second array
- If a prefix is identified, but neither array represents a full subset of the other, the index where the prefix stops is used to compare the elements at that index
The same can be easily visualized by the below table
Array a | Array b | Arrays.compare(a,b) | Notes |
---|---|---|---|
a = {el1,el2} | b = {el1,el2} | 0 | arrays equal using Arrays.equals(a,b) |
a = null | b = {el1,el2} | -1 | since first array is null |
a = {el1,el2} | b = null | 1 | since second array is null |
a = {} | b = {el1,el2} | a.length-b.length | a.length == 0 |
a = {el1,el2} | b = {} | a.length-b.length | b.length == 0 |
a = {el1,el2} | b = {el1,el2,el3} | a.length-b.length | prefix == {el1,el2} |
a = {el1,el2} | b = {el3,el4} | a[0].compareTo(b[0]) | no prefix identified |
a = {el1,el2,el3} | b = {el1,el2,el4} | a[2].compareTo(b[2]) | prefix is {el1,el2} but its not complete array set so first element difference |
Now lets go through some code to look at some of the methods and their usage.
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.List;
public class ArrayManipulation {
public static void main(String[] args) {
// Set up some array data for comparison.
String[] firstString = {"abc", "def", "ghi", "jkl", "mno",
"pqr", "stu", "vwx", "yz"};
String[] copyOfFirstString = {"abc", "def", "ghi", "jkl", "mno",
"pqr", "stu", "vwx", "yz"};
String[] firstStringUnsorted = {"jkl", "mno", "pqr", "stu", "vwx",
"yz", "abc", "def", "ghi"};
String[] partialFirstString = {"abc", "def", "ghi", "jkl", "mno"};
String firstStringReference[] = firstString;
// Create pass-thru Lists from the arrays to test List equality
List firstList = Arrays.asList(firstString);
List secondList = Arrays.asList(copyOfFirstString);
// First, compare arrays using object.equals
System.out.println("------------- Object.equals ------------");
System.out.println(" (firstString.equals(copyOfFirstString)) = "
+ firstString.equals(copyOfFirstString));
System.out.println(" (firstString.equals(firstStringReference)) = "
+ firstString.equals(firstStringReference));
// Compare arrays using Arrays.equals
System.out.println("\n------------- Arrays.equals ------------");
System.out.println(" (Arrays.equals(firstString,copyOfFirstString)) = "
+ Arrays.equals(firstString, copyOfFirstString));
System.out.println(" (Arrays.equals(firstString,firstStringReference)) = "
+ Arrays.equals(firstString, firstStringReference));
System.out.println(" (Arrays.equals(firstString,firstStringUnsorted)) = "
+ Arrays.equals(firstString, firstStringUnsorted));
// Compare arrays using Arrays.compare
System.out.println("\n------------- Arrays.compare ------------");
System.out.println(" (Arrays.compare(firstString,copyOfFirstString)) = "
+ Arrays.compare(firstString, copyOfFirstString));
System.out.println(" (Arrays.compare(firstString,firstStringReference)) = " +
"" + Arrays.compare(firstString, firstStringReference));
System.out.println(" (Arrays.compare(firstString,firstStringUnsorted)) = "
+ Arrays.compare(firstString, firstStringUnsorted));
System.out.println(" (Arrays.compare(firstStringUnsorted,firstString)) = "
+ Arrays.compare(firstStringUnsorted, firstString));
System.out.println(" (Arrays.compare(firstString,partialFirstString)) = "
+ Arrays.compare(firstString, partialFirstString));
System.out.println(" (Arrays.compare(partialFirstString,firstString)) = "
+ Arrays.compare(partialFirstString, firstString));
// More examples of Arrays.compare
System.out.println("\n------------- More Arrays.compare ------------");
System.out.println(" (Arrays.compare(firstString,firstStringUnsorted)) = "
+ Arrays.compare(firstString, firstStringUnsorted));
// If we compare the first elements, we get the same result as comparing the full arrays...
System.out.println("firstString[0].compareTo(firstStringUnsorted[0] = "
+ firstString[0].compareTo(firstStringUnsorted[0]));
// New String array, only first 3 elements are shared with firstString - the prefix.
String[] notFullyPrefixedString = {"abc", "def", "ghi", "yz", "vwx", "stu"};
System.out.println(" (Arrays.compare(firstString,notFullyPrefixedString)) = "
+ Arrays.compare(firstString, notFullyPrefixedString));
// Verify that above result is same as comparing elements at first non-matching index..
System.out.println("firstString[3].compareTo(notFullyPrefixedString[3] = " +
firstString[3].compareTo(notFullyPrefixedString[3]));
// Comparing subsets of elements in arrays
System.out.println("\n---- Arrays.compare for Element Ranges ----");
// Set up arrays - note that both arrays contain "abc", "def", "ghi"
String[] stringArray = {"abc", "def", "ghi", "jkl", "mno",
"pqr", "stu", "vwx", "yz"};
String[] stringUnsortedArray = {"jkl", "mno", "pqr", "stu",
"vwx", "yz", "abc", "def", "ghi"};
// We are going to compare the 1st 3 elements of the ordered array,
// with the last 3 elements of the unsorted array:
System.out.println(" (Arrays.compare(stringArray, 0, 3, stringUnsortedArray, 6, 9)) = "
+ Arrays.compare(stringArray, 0, 3, stringUnsortedArray, 6, 9));
// Interestingly, you do not have to specify the same number of elements.
System.out.println(" (Arrays.compare(stringArray, 0, 5, stringUnsortedArray, 6, 9)) = "
+ Arrays.compare(stringArray, 0, 5, stringUnsortedArray, 6, 9));
System.out.println("\n------------- List.equals ------------");
System.out.println(" (firstList.equals(secondList)) = "
+ firstList.equals(secondList));
}
}
In the first part, we are setting up some test data, converting array to list and comparing the arrays using Object equals
method. As mentioned earlier, Object equals method returns true only when the references to both the arrays are the same. Arrays with same set of data but different references will not be considered equal. This is why we get the below output for the first part.
------------- Object.equals ------------
(firstString.equals(copyOfFirstString)) = false
(firstString.equals(firstStringReference)) = true
Now in the second part, we use Arrays.equals
method instead of Object equals. It looks at the array elements to determine if the arrays are equal, also checks the order of the elements and so the last output is false.
------------- Arrays.equals ------------
(Arrays.equals(firstString,copyOfFirstString)) = true
(Arrays.equals(firstString,firstStringReference)) = true
(Arrays.equals(firstString,firstStringUnsorted)) = false
Then we have the Arrays.compare method, and we have already covered that before. Look at the table and the output can be easily understood
------------- Arrays.compare ------------
(Arrays.compare(firstString,copyOfFirstString)) = 0
(Arrays.compare(firstString,firstStringReference)) = 0
(Arrays.compare(firstString,firstStringUnsorted)) = -9
(Arrays.compare(firstStringUnsorted,firstString)) = 9
(Arrays.compare(firstString,partialFirstString)) = 4
(Arrays.compare(partialFirstString,firstString)) = -4
------------- More Arrays.compare ------------
(Arrays.compare(firstString,firstStringUnsorted)) = -9
firstString[0].compareTo(firstStringUnsorted[0] = -9
(Arrays.compare(firstString,notFullyPrefixedString)) = -15
firstString[3].compareTo(notFullyPrefixedString[3] = -15
---- Arrays.compare for Element Ranges ----
(Arrays.compare(stringArray, 0, 3, stringUnsortedArray, 6, 9)) = 0
(Arrays.compare(stringArray, 0, 5, stringUnsortedArray, 6, 9)) = 2
Array Seach methods
There are a few methods using which we can search for elements within the array. We will have a look at the widely used Arrays.binarySearch
and a few more with it.
The binarySearch method searches for a matching element and returns an integer indicating the array index where there is a match.
- If no match is found, the method returns a -1.
- When using a binarySearch, your array needs to be sorted.
- You can also perform a binarySearch on a non-sorted array but the results cannot be relied on.
- If your array contains duplicate values there’s no guarantee which index of the duplicated elements will be returned.
So as you can understand, the primary requirement to get correct result in case of binary search is that the array must be in sorted order. Otherwise, output will be provided but that cannot be relied on.
Lets look at a small code to understand the search methods properly.
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.List;
public class ArraySearch {
public static void main(String[] args) {
// Set up some array data we want to compare.
String[] firstString = {
"abc", "def", "ghi", "jkl", "mno",
"pqr", "stu", "vwx", "yz"
};
String[] firstStringUnsortedDuplicates = {
"jkl", "mno", "pqr", "stu", "vwx",
"yz", "jkl", "abc", "def", "ghi"
};
String[] partialFirstString = {"abc", "def", "ghi", "jkl", "mno"};
// Create Lists from the arrays to test List search methods
List firstList = List.of(firstString);
List secondList = Arrays.asList(firstStringUnsortedDuplicates);
System.out.println("---------- Arrays binarySearch ----------");
// binary search on array, look for "jkl" which is in array
String searchString = "jkl";
System.out.println("Arrays.binarySearch(firstString,\"jkl\") = "
+ Arrays.binarySearch(firstString, "jkl"));
// binary search, look for "aaa", which is not in array
System.out.println("Arrays.binarySearch(firstString,\"aaa\") = "
+ Arrays.binarySearch(firstString, "aaa"));
// binary search, look for "jkl" of which there are two elements
System.out.println("Arrays.binarySearch(firstStringUnsortedDuplicates,\"jkl\") = "
+ Arrays.binarySearch(firstStringUnsortedDuplicates, "jkl"));
// binary search on unsorted array, for "abc" which is in array
System.out.println("Arrays.binarySearch(firstStringUnsortedDuplicates,\"abc\") = "
+ Arrays.binarySearch(firstStringUnsortedDuplicates, "abc"));
System.out.println("\n---------- Arrays mismatch ----------");
// mismatch returns the non-matching index where the prefix ends
System.out.println("Arrays.mismatch(firstString,partialFirstString) = "
+ Arrays.mismatch(firstString, partialFirstString));
// Try another example...
System.out.println("Arrays.mismatch(firstStringUnsortedDuplicates," +
" new String[]{\"jkl\",\"mno\"}) = "
+ Arrays.mismatch(firstStringUnsortedDuplicates, new String[]{"jkl", "mno"}));
System.out.println("\n-------------- List methods -------------------");
// Does array contain "def"?
System.out.println("firstList.contains(\"def\") = "
+ firstList.contains("def"));
// Does array contain elements in partialString?
System.out.println("firstList.containsAll(Arrays.asList(partialFirstString)) = "
+ firstList.containsAll(Arrays.asList(partialFirstString)));
// create a second list not in same order
String[] anotherUnsortedSet = {"jkl", "def", "abc", "ghi", "mno"};
System.out.println("firstList.containsAll(Arrays.asList(anotherUnsortedSet)) = "
+ firstList.containsAll(Arrays.asList(anotherUnsortedSet)));
// Use indexOf to get first matching element
System.out.println("secondList.indexOf(\"jkl\") = "
+ secondList.indexOf("jkl"));
// Use lastIndexOf to to get last matching element
System.out.println("secondList.lastIndexOf(\"jkl\") = "
+ secondList.lastIndexOf("jkl"));
}
}
Output
---------- Arrays binarySearch ----------
Arrays.binarySearch(firstString,"jkl") = 3
Arrays.binarySearch(firstString,"aaa") = -1
Arrays.binarySearch(firstStringUnsortedDuplicates,"jkl") = 0
Arrays.binarySearch(firstStringUnsortedDuplicates,"abc") = -1
---------- Arrays mismatch ----------
Arrays.mismatch(firstString,partialFirstString) = 5
Arrays.mismatch(firstStringUnsortedDuplicates, new String[]{"jkl", "mno"}) = 2
-------------- List methods -------------------
firstList.contains("def") = true
firstList.containsAll(Arrays.asList(partialFirstString)) = true
firstList.containsAll(Arrays.asList(anotherUnsortedSet)) = true
secondList.indexOf("jkl") = 0
secondList.lastIndexOf("jkl") = 6
The List.of
method was introduced in Java 9 and the basic difference between Arrays.asList
and List.of
are as below
List.of
returns an immutable list whereasArrays.asList
returns a mutable list. So you cannot do a list.set in the list returned by List.ofArrays.asList
returns a view to the underlying array, so any changes in the array elements will also reflect in the list values. But this is not the case in list returned byList.of
List.of
doesnt allow null values whereas Arrays.asList allows null values.
First we are doing a binary search on the array for “jkl”, then for “aaa” which doesnt exist in the array and hence return value is -1. The next output for search on “jkl” does provide correct result, but as per the javadoc the search on unsorted array is not to be relied on, as is clearly seen in the next output.
Now, as we know about array prefix, Arrays.mismatch
returns the index where the prefix no longer applies. So the output for Arrays.mismatch are straight forward.
And the final set has some List search methods. contains
and containsAll
are used to see if an element or a list of elements is contained in the list.
These methods return true or false and the containsALL method does not require the elements to be in the same order to return true.
The indexOf
and lastIndexOf
returns the first or last index of the element matching in the array.
Thats all in this section. We will look into the Array Search methods in the next section.