Array Operations – Collections: Part II
Array Operations
The following operations convert collections to arrays. See also array operations on array lists (§12.6, p. 658).
Object[] toArray()
<T> T[] toArray(T[] a)
The first toArray() method returns an array of type Object filled with all the elements of the collection. The second method is a generic method that stores the elements of a collection in an array of type T. The default method uses the generator function to allocate the returned array.
If the given array is big enough, the elements are stored in this array. If there is room to spare in the array; that is, the length of the array is greater than the number of elements in the collection—the spare room is filled with null values before the array is returned. If the array is too small, a new array of type T and appropriate size is created. If T is not a supertype of the runtime type of every element in the collection, an ArrayStoreException is thrown.
default <T> T[] toArray(IntFunction<T[]> generator)
Allows creation of an array of a particular runtime type given by the parameterization of the type parameter T[], using the specified generator function (§13.8, p. 717) to allocate the array of the desired type and the specified length. The default implementation calls the generator function with 0 and then passes the resulting array of length 0 to the toArray(T[]) generic method.
Example 15.2 illustrates converting a set to an array. At (1), the call to the non-generic toArray() method returns an array of type Object. Since an array of type Object is not a subtype of an array of type String, the compiler reports an error at (2).
At (3), the call to the generic toArray() method returns an array of size 3 and type Object[], but element type String, when the method was passed a zero-length array of type Object. In other words, the method created a suitable-size array of type Object, since the array passed in the argument was too small. This array was filled with the elements of the set, which are strings. Although the array returned is of type Object, the objects stored in it are of type String. The output from the program confirms these observations.
At (4), the call to the generic toArray() method returns an array of size 3 and type String[], having element type String, when the method was passed a zero-length array of type String. Now the method creates a new suitable-size array of type String and fills it with the elements of the set, which are strings. The output from the program shows that the array passed in the argument is not the same as the array returned by the method call.
At (5), the call to the generic toArray() method returns the same array it was passed in the argument, since it is of appropriate size and type. In other words, the array passed in the argument is filled with the elements of the list, and returned. This is corroborated by the output from the program.
At (6), the actual type parameter is Integer. The generic toArray() method throws an ArrayStoreException because String objects in the set denoted by strSet cannot be stored in an array of type Integer.
Lastly, Example 15.2 illustrates converting a set to an array using the default toArray(IntFunction<T[]>) generic method, which is a convenience method that actually leverages the toArray(T[]) generic method.
IntFunction<String[]> createStrArray = nn -> new String[nn]; // (7)
String[] strArray5 = strSet.toArray(createStrArray); // (8a)
String[] strArray6 = strSet.toArray(String[]::new); // (8b)
String[] strArray7 = strSet.toArray(createStrArray.apply(0)); // (8c)
The lambda expression at (7) creates an array of length nn and of type String[]. This lambda expression is passed to the toArray(IntFunction<String[]>) method at (8a). Equivalently, we can pass a method reference to the method, as shown at (8b). Of course, the lambda expression at (7) only creates an array when the apply() method of the IntFunction<T[]> interface is called with a value for the length of the array. The default behavior of the toArray(IntFunction<T[]>) generic method is illustrated at (8c): The apply() method of the IntFunction<String[]> interface is explicitly called with the value 0 to create a zero-length String array which is then passed as a parameter to the toArray(String[]) method.
Example 15.2 Converting Collections to Arrays
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.function.IntFunction;
public class CollectionToArray {
public static void main(String[] args) {
Collection<String> strSet = new HashSet<>();
strSet.add(“2021”); strSet.add(“2022”); strSet.add(“2023”);
int n = strSet.size();
Object[] objects = strSet.toArray(); // (1)
// String[] string = strSet.toArray(); // (2) Compile-time error!
Object[] objArray = strSet.toArray(new Object[0]); // (3)
System.out.println(“Array size: ” + objArray.length);
System.out.println(“Array type: ” + objArray.getClass().getName());
System.out.println(“Actual element type: ” +
objArray[0].getClass().getName());
String[] strArray1 = new String[0];
String[] strArray2 = strSet.toArray(strArray1); // (4)
System.out.println(“strArray1 == strArray2: ” + (strArray1 == strArray2));
String[] strArray3 = new String[n];
String[] strArray4 = strSet.toArray(strArray3); // (5)
System.out.println(“strArray3 == strArray4: ” + (strArray3 == strArray4));
// Integer[] intArray = strSet.toArray(new Integer[n]); // (6) Runtime error!
IntFunction<String[]> createStrArray = nn -> new String[nn]; // (7)
String[] strArray5 = strSet.toArray(createStrArray); // (8a)
String[] strArray6 = strSet.toArray(String[]::new); // (8b)
String[] strArray7 = strSet.toArray(createStrArray.apply(0)); // (8c)
System.out.println(“strArray5: ” + Arrays.toString(strArray5));
System.out.println(“strArray6: ” + Arrays.toString(strArray6));
System.out.println(“strArray7: ” + Arrays.toString(strArray7));
}
}
Output from the program:
Array size: 3
Array type: [Ljava.lang.Object;
Actual element type: java.lang.String
strArray1 == strArray2: false
strArray3 == strArray4: true
strArray5: [2023, 2022, 2021]
strArray6: [2023, 2022, 2021]
strArray7: [2023, 2022, 2021]