1. Overview
In this tutorial, we’ll take a look at the different ways in which we can extend a Java array.
Since arrays are a contiguous block of memory, the answer may not be readily apparent, but let’s unpack that now.
2. Using Arrays.copyOf
First, let’s look at Arrays.copyOf. We’ll copy the array and add a new element to the copy:
public Integer[] addElementUsingArraysCopyOf(Integer[] srcArray, int elementToAdd) { Integer[] destArray = Arrays.copyOf(srcArray, srcArray.length + 1); destArray[destArray.length - 1] = elementToAdd; return destArray; }
The way Arrays.copyOf works is that it takes the srcArray and copies the number of elements specified in the length argument to a new array which it internally creates. The size of the new array is the argument that we provide.
One thing to notice is that when the length argument is greater than the size of the source array, Arrays.copyOf will fill the extra elements in the destination array with null.
Depending on the datatype, the behavior of the filling will be different. For example, if we use primitive data types in place of Integer then the extra elements are filled with the zeros. In the case of char, Arrays.copyOf will fill extra elements with null and in case of boolean, with false.
3. Using ArrayList
The next way we’ll look at is using ArrayList.
We’ll first convert the array to an ArrayList and then add the element. Then we’ll convert the ArrayList back to an array:
public Integer[] addElementUsingArrayList(Integer[] srcArray, int elementToAdd) { Integer[] destArray = new Integer[srcArray.length + 1]; ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(srcArray)); arrayList.add(elementToAdd); return arrayList.toArray(destArray); }
Note that we’ve passed the srcArray by converting it to a Collection. The srcArray will populate the underlying array in the ArrayList.
Also, another thing to note is that we’ve passed the destination array as an argument to toArray. This method will copy the underlying array to the destArray.
4. Using System.arraycopy
Finally, we’ll take a look at System.arraycopy, which quite similar to Arrays.copyOf:
public Integer[] addElementUsingSystemArrayCopy(Integer[] srcArray, int elementToAdd) { Integer[] destArray = new Integer[srcArray.length + 1]; System.arraycopy(srcArray, 0, destArray, 0, srcArray.length); destArray[destArray.length - 1] = elementToAdd; return destArray; }
One interesting fact is that Arrays.copyOf internally uses this method.
Here we can notice that we copy the elements from the srcArray to destArray and then add the new element to the destArray.
5. Performance
One thing common in all the solutions is that we have to create a new array one way or another. The reason for it lies in how arrays are allocated in memory. An array holds a contiguous block of memory for super-fast lookup, which is why we cannot simply resize it.
This, of course, has a performance impact, especially for large arrays. This is why ArrayList over-allocates, effectively reducing the number of times the JVM needs to reallocate memory.
But, if we are doing a lot of inserts, an array might not be the right data structure, and we should consider a LinkedList.
6. Conclusion
In this article, we have explored the different ways of adding elements to the end of an array.
The entire code is available over on GitHub.