Java 11 Developer Certification - Array Special Concepts
November 17, 2020
What we are covering in this lesson
- Unboxing in array
- List - Special Concepts
- Methods to create copy of an array
Unboxing in array
Arrays are fuzzy about their datatypes.
We can rely on Java to autobox to and unbox from wrappers for us in many instances, this is not true for arrays.
So the statements Long[] longArr = new int[2]
or Integer[] intArr = new int[2]
will throw compiler error for Incompatible Types
.
Also, the java.util.Arrays static methods that compare arrays, will not accept two arrays of different types even if they’re types that are normally widened or autoboxed on an individual level.
So Arrays.equals(int[], Integer[])
or Arrays.compare(int[], Integer[])
will throw compiler error. This also applied for Arrays.mismatch
.
package maxCode.online.Arrays;
import java.util.Arrays;
public class ArrayExtras {
public static void main(String[] args) {
int a = 0, b = 0;
// You can assign an int variable to a long
long myLong = a;
System.out.println("myLong = " + myLong);
// These are valid
long[] longArray = { 0, 1, 2, 3, 4 };
long[] myLongArray = new long[2];
myLongArray[0] = a;
myLongArray[1] = b;
System.out.println("longArray = " + Arrays.toString(longArray));
System.out.println("myLongArray = " + Arrays.toString(myLongArray));
// And you know you can do this. Java autoboxes
Integer aInteger = a;
System.out.println("aInteger = " + aInteger);
Integer[] integerArray = { 0, 1, 2, 3, 4 };
System.out.println("integerArray = " + Arrays.toString(integerArray));
Integer[] myIntegerArray = new Integer[2];
// You can mix and match Integer, int here
myIntegerArray[0] = aInteger;
myIntegerArray[1] = b;
System.out.println("myIntegerArray = " + Arrays.toString(myIntegerArray));
System.out.println("\n---- Test methods with common super class");
Number[] myNumberArray = { 0, 1, 2, 4, 5 };
System.out.println("Arrays.mismatch(myNumberArray, integerArray) = "
+ Arrays.mismatch(myNumberArray, integerArray));
System.out.println("Arrays.equals(myNumberArray, integerArray) = " + Arrays.equals(myNumberArray, integerArray));
// int compare = Arrays.compare(myNumberArray, integerArray);
}
}
Output
myLong = 0
longArray = [0, 1, 2, 3, 4]
myLongArray = [0, 0]
aInteger = 0
integerArray = [0, 1, 2, 3, 4]
myIntegerArray = [0, 0]
---- Test methods with common super class
Arrays.mismatch(myNumberArray, integerArray) = 3
Arrays.equals(myNumberArray, integerArray) = false
The last part of the code compiles successfully since Integer extends Number
.
The commented code at the end will throw compiler error if uncommented, reason being when comparing different typed arrays, they need to implement the Comparable interface and be cast to a Comparable array and the compareTo method must compare a super class shared by both.
So specifically, the area here is that java.lang.Number doesn’t implement Comparable.
List - Special Concepts
Most important thing to note here is that List.of
and List.copyOf
returns a immutable list objects.
In the below code, firstList will create a mutable list of firstString array elements but secondList will create a list of list, and the difference is class names as seen in the output.
The method list.of
can take an array of elements and create a list out of it or it can take a variable argument list of objects (a.k.a. varags).
Since we didn’t pass an array to it in the code, it assumed a variable argument list of objects and created an array of one element the first and only element being the list we passed as the argument.
The method list.sublist
got very similar features to the Arrays.asList
method, such that the return list
is backed by the original list. So non-structural changes to the return list are reflected in the original list. And this can be seen in the sublist output.
If in case we replace Arrays.asList(firstString).subList(0, 5)
with firstString.subList(0, 5)
, then the code will throw UnsupportedOperationException
, since we are trying to sort an immutable list and that is not permitted.
Then we have the toArray
example, which returns the same reference and hence the equality returns true.
It can also be called without having to assign it to another variable.
One important thing to note here is that if we pass the length arrayLength
as something less than the number of parameters in the list, then on using toArray
, the values do not get populated. So if we pass 3
as arrayLength
, the values in aArray
and bArray
will be null
.
If you always want an array that represents the elements exactly in the list, you can pass a 0
length array, as we have done in the below code for arrayRepresentation
array.
Also, we can call toArray
without any parameter, it will return an array of object.
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ArraysAndLists {
public static void main(String[] args) {
String[] firstString = { "abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz" };
List firstList = List.copyOf(Arrays.asList(firstString));
List secondList = List.of(firstList);
System.out.println("firstList = " + firstList.toString());
System.out.println("secondList = " + secondList.toString());
Object o = firstList.get(0);
System.out.println(o.getClass().getName());
o = secondList.get(0);
System.out.println(o.getClass().getName());
System.out.println("\n-------- subList example ---------");
List subList = Arrays.asList(firstString).subList(0, 5);
System.out.println("subList = " + subList.toString());
// Sort the sublist
subList.sort(Collections.reverseOrder());
System.out.println("subList after reverse = " + subList.toString());
System.out.println("firstString array = " + Arrays.toString(firstString));
System.out.println("firstList = " + firstList.toString());
// Now let's look at toArray
System.out.println("\n-------- toArray examples ---------");
int arrayLength = firstList.size(); // arrayLength changes results
// Set up a new array which we will pass to toArray
String[] aArray = new String[arrayLength];
// Calling toArray without assigning returned array to a variable
firstList.toArray(aArray);
System.out.println("aArray array = " + Arrays.toString(aArray));
// Set up another new array which we will pass to toArray
String[] bArray = new String[arrayLength];
// Calling toArray assigning returned array to a variable;
String[] nextArray = (String[]) firstList.toArray(bArray);
System.out.println("bArray array = " + Arrays.toString(bArray));
System.out.println("nextArray array = " + Arrays.toString(nextArray));
System.out.println("nextArray.equals(bArray) = " + nextArray.equals(bArray));
System.out.println("\n------- Final toArray examples --------");
// If you always want an array that represents the elements
// exactly in the list, you can pass a 0 length array
String[] arrayRepresentation = (String[]) firstList.toArray(new String[0]);
System.out.println("arrayRepresentation array = " + Arrays.toString(arrayRepresentation));
// You can call toArray with no parameter, it returns an array of Object
Object[] objectArray = firstList.toArray();
System.out.println("objectArray array = " + Arrays.toString(objectArray));
String[] newRepresentation = (String[]) objectArray;
System.out.println("newRepresentation array = " + Arrays.toString(newRepresentation));
}
}
Output
firstList = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]
secondList = [[abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]]
java.lang.String
java.util.ImmutableCollections$ListN
-------- subList example ---------
subList = [abc, def, ghi, jkl, mno]
subList after reverse = [mno, jkl, ghi, def, abc]
firstString array = [mno, jkl, ghi, def, abc, pqr, stu, vwx, yz]
firstList = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]
-------- toArray examples ---------
aArray array = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]
bArray array = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]
nextArray array = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz]
nextArray.equals(bArray) = true
------- Final toArray examples --------
arrayRepresentation array = [mno, jkl, ghi, def, abc, pqr, stu, vwx, yz]
objectArray array = [mno, jkl, ghi, def, abc, pqr, stu, vwx, yz]
newRepresentation array = [mno, jkl, ghi, def, abc, pqr, stu, vwx, yz]
Methods to create copy of an array
There are overall 5 methods which we will cover in this topic. Let see them one by one, assuming we have a String array like below
String[] stringArray = {"abc", "def", "ghi"}
clone method
- inherited from
Object
class - Creates a new array reference but the elements are not cloned (shallow copy)
- Array created is mutable
String[] clonedArray = stringArray.clone();
Arrays.copyOf method
- static method in
java.lang.Arrays
- Creates a new array reference but the elements are not cloned (shallow copy)
- Array created is mutable
- Can be used to create array which is truncated from original
-
Can also be used to create array larger than original, additional elements get default values
String[] copyOf1 = Arrays.copyOf(stringArray, stringArray.length); String[] copyOf2 = Arrays.copyOf(stringArray, 2); //smaller array String[] copyOf3 = Arrays.copyOf(stringArray, 10); //larger array
Arrays.copyOfRange method
- static method in
java.lang.Arrays
- Creates a new array reference from the selected range but the elements are not cloned (shallow copy)
- Array created is mutable
String[] copyRange1 = Arrays.copyOfRange(stringArray, 0, 1);
List.copyOf method
- static method in List
- Creates a new List using shallow copy
- Makes immutable copy of list
- Resulting array from toArray is not immutable
List<String> listCopy = List.copyOf(Arrays.asList(stringArray)); //immutable copy of list
String[] newArr = listCopy.toArray(new String[0]); //mutable array
System.arraycopy
- static method on System
- Populates an array reference with a copy of the array passed to it
- Creates mutable array
- shallow copy
String[] systemClonedArray = new String[stringArray.length];
System.arraycopy(stringArray, 0, systemClonedArray, 0, stringArray.length);