Java 11 Developer Certification - Data Manipulation and Transformation in Array
November 09, 2020
What we are covering in this lesson
- Array Data Manipulation methods
- Manipulating array using fixed size list
- Array Data Transformation methods
- List Data Transformation methods
- Two Dimensional Arrays
Array Data Manipulation methods
Some of the methods which help in data manipulation in an array are fill, setAll, sort, parallelPrefix, parallelSetAll, parallelSort
.
All the parallel version of the methods can be used for large set of data, allowing multiple threads to work in parallel.
parallelSetAll and parallelSort
are operationally the same as setAll and sort
, except for they can run multiple threads in parallel.
Lets have a look at these methods using a code example
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.Collections;
public class ArrayDataManipulation {
public static void main(String[] args) {
// Create array of Integer
Integer[] intArray = new Integer[10];
System.out.println("Array values initially: " + Arrays.toString(intArray));
// Fill array with a single value
Arrays.fill(intArray, 5);
System.out.println("Array values after fill: " + Arrays.toString(intArray));
// You can fill a partial range with Arrays.fill overloaded method
int partialFillValue = 9;
Arrays.fill(intArray, 5, 10, partialFillValue);
System.out.println("Array values after partial fill: " + Arrays.toString(intArray));
// setAll was introduced in Java 8, uses lambda expressions
Arrays.setAll(intArray, (index) -> index + 1);
System.out.println("Array values after setAll: " + Arrays.toString(intArray));
// You can sort non primitive data type arrays in reverse this way
Arrays.sort(intArray, Collections.reverseOrder());
System.out.println("Array values after reverse sort: " + Arrays.toString(intArray));
// parallelPrefix supports binary operations.
Arrays.parallelPrefix(intArray, (left, right) -> left + right);
System.out.println("Array values after parallelPrefix: " + Arrays.toString(intArray));
}
}
Output
Array values initially: [null, null, null, null, null, null, null, null, null, null]
Array values after fill: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
Array values after partial fill: [5, 5, 5, 5, 5, 9, 9, 9, 9, 9]
Array values after setAll: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array values after reverse sort: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Array values after parallelPrefix: [10, 19, 27, 34, 40, 45, 49, 52, 54, 55]
We are first creating an array of Integers, and populating it with a single value using Arrays.fill
. Then we are again using it for partial fill.
setAll
was introduced in Java 8 and uses lambda expression, to set the values for each element in array.
Sorting in reverseOrder using Collections.reverseOrder
works only on non-primitive data. And then we have the parallel version implementation.
Manipulating array using fixed size list
There are two methods List.of
and List.copyOf
which we will demonstrate below.
The most important thing about these methods is that these methods is that they return an immutable list, meaning we cannot change the list.
List.of
takes an array and makes it a list. List.copyOf
takes a list and makes another list.
The below code demonstrates the methods on the list interface which can be applied on arrays.
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.List;
public class ListDataManipulation {
public static void main(String[] args) {
// Set up some test data for use in our tests
String[] primaryColors = { "red", "blue", "yellow" };
String[] secondaryColors = { "green", "orange", "purple" };
System.out.println("--- Manipulating array data using a List");
// The Arrays.asList returns a list backed by the array;
List<String> colorList = Arrays.asList(primaryColors);
System.out.println("colorList: " + colorList.toString());
// Use get method to get an element in the array
String firstColor = colorList.get(0);
System.out.println("firstColor is " + firstColor);
// Sort the array via the List reference
colorList.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println("\ncolorList after sort: " + colorList.toString());
System.out.println("primaryColors " + Arrays.toString(primaryColors));
// Set the value of an array element using set method
colorList.set(0, "cyan");
System.out.println("\ncolorList after after changing 1st value : " + colorList.toString());
System.out.println("primaryColors " + Arrays.toString(primaryColors));
// Use replaceAll method to change all values in the array via
// List reference
colorList.replaceAll((s) -> s + "ish");
System.out.println("\ncolorList after replacing all values: " + colorList.toString());
System.out.println("primaryColors " + Arrays.toString(primaryColors));
// And what happens when we change underlying array?
primaryColors[0] = "blueish";
System.out.println("\ncolorList after array changed: " + colorList.toString());
System.out.println("primaryColors " + Arrays.toString(primaryColors));
System.out.println("\n--- List.of and List.copyOf Examples");
// List.of method can take an array and make it a list
List secondColorList = List.of(primaryColors);
// List.copyOf method takes a list and makes another list
List thirdColorList = List.copyOf(Arrays.asList(primaryColors));
System.out.println("\nsecondColorList : " + secondColorList.toString());
System.out.println("thirdColorList : " + thirdColorList.toString());
// Change value on original array
primaryColors[0] = "blue";
System.out.println("\nprimaryColors after making first element blue: " + Arrays.toString(primaryColors));
System.out.println("secondColorList after array changed : " + secondColorList.toString());
System.out.println("thirdColorList after array changed : " + thirdColorList.toString());
// Below code, if uncommented, will throw UnsupportedOperationException (Runtime Exception)
// secondColorList created from List.of method is immutable
/*try {
secondColorList.set(0, "cyan");
} catch (Exception e) {
e.printStackTrace();
}
// thirdColorList created from List.copyOf method is also immutable
try {
thirdColorList.set(0, "cyan");
} catch (Exception e) {
e.printStackTrace();
}*/
}
}
Output
--- Manipulating array data using a List
colorList: [red, blue, yellow]
firstColor is red
colorList after sort: [blue, red, yellow]
primaryColors [blue, red, yellow]
colorList after after changing 1st value : [cyan, red, yellow]
primaryColors [cyan, red, yellow]
colorList after replacing all values: [cyanish, redish, yellowish]
primaryColors [cyanish, redish, yellowish]
colorList after array changed: [blueish, redish, yellowish]
primaryColors [blueish, redish, yellowish]
--- List.of and List.copyOf Examples
secondColorList : [blueish, redish, yellowish]
thirdColorList : [blueish, redish, yellowish]
primaryColors after making first element blue: [blue, redish, yellowish]
secondColorList after array changed : [blue, redish, yellowish]
thirdColorList after array changed : [blue, redish, yellowish]
The last commented part will throw Runtime Exception if uncommented, since the lists returned by List.of
and List.copyOf
are immutable copies of the underlying data.
Array Data Transformation methods
The data transformation methods transform the array list into another type of data.
We use Arrays.copyOf
and Arrays.copyOfRange
methods to achieve this.
Different ways to use these method are demonstrated below.
package maxCode.online.Arrays;
import java.util.Arrays;
public class ArrayTransformation {
public static void main(String[] args) {
System.out.println("-----------Using Arrays.copyOf ----------");
// Create an array of Integer
Integer[] originalArray = new Integer[10];
// Initialize values to 1 - 10
Arrays.setAll(originalArray, (index) -> index + 1);
System.out.println("integerArray values = " + Arrays.toString(originalArray));
// Create Copy of array, same size
Integer[] copiedArray = Arrays.copyOf(originalArray, originalArray.length);
System.out.println("copiedArray values = " + Arrays.toString(copiedArray));
// Create Copy of of an array, trimmed to specified size
Integer[] trimmedArray = Arrays.copyOf(originalArray, 7);
// Copy array to larger array, extra elements get default values
Integer[] widenedArray = Arrays.copyOf(originalArray, 15);
System.out.println("trimmedArray values = " + Arrays.toString(trimmedArray));
System.out.println("widenedArray values = " + Arrays.toString(widenedArray));
// Create Copy of defined portion of Array
Integer[] croppedArray = Arrays.copyOfRange(originalArray, 2, 6);
System.out.println("croppedArray values = " + Arrays.toString(croppedArray));
croppedArray[0] = 5;
System.out.println("croppedArray values after a change = " + Arrays.toString(croppedArray));
}
}
Output
-----------Using Arrays.copyOf ----------
integerArray values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
copiedArray values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
trimmedArray values = [1, 2, 3, 4, 5, 6, 7]
widenedArray values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, null, null, null, null, null]
croppedArray values = [3, 4, 5, 6]
croppedArray values after a change = [5, 4, 5, 6]
List Data Transformation methods
We will look at subList
and toArray
method here.
subList
creates a list from a smaller set of elements.
toArray
transforms a list to an array.
The below code shows the usage of these methods
package maxCode.online.Arrays;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ListTransformation {
public static void main(String[] args) {
// Create a new Integer array
Integer[] integerArray = new Integer[10];
// Set values to 1 - 10
Arrays.setAll(integerArray, (index) -> index + 1);
System.out.println("integerArray values = " +
Arrays.toString(integerArray));
List anotherList = List.of(integerArray);
// Create a subList of a list
List shortList = anotherList.subList(3, 7);
System.out.println("shortList values : " + shortList.toString());
// And now go from list to array...
Integer[] repeatedArray = new Integer[10];
anotherList.toArray(repeatedArray);
System.out.println("array created from toArray method : " +
Arrays.toString(repeatedArray));
System.out.println("------ iterator tests --------");
// Iterator allows forward processing of list elements
System.out.println("loop through anotherList.iterator() values...");
for (Iterator it = anotherList.iterator(); it.hasNext(); ) {
System.out.print(it.next());
}
// ListIterator allows backwards and forwards processing
// of list elements
System.out.println("\nloop through anotherList.listIterator() values...");
ListIterator lit = anotherList.listIterator();
for (int i = 0; lit.hasNext(); i++) {
System.out.print(lit.next());
if (i == 4) {
System.out.println("\nreverse direction");
for (; lit.hasPrevious(); ) {
System.out.print(lit.previous());
}
break;
}
}
}
}
Output:
integerArray values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
shortList values : [4, 5, 6, 7]
array created from toArray method : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
------ iterator tests --------
loop through anotherList.iterator() values...
12345678910
loop through anotherList.listIterator() values...
12345
reverse direction
54321
We have created a new Integer array, set the values, create another list using List.of
, then creating a subList from that list and then converting an array to List using List.toArray
.
The iterator
used after that allows only forward processing of the list elements.
The ListIterator
on the other hand allows backward as well as forward processing of the elements.
We’ve seen here that the java.lang.Arrays
utility class provides many of the methods you would need to manipulate data in an array.
And additionally, you can use some of the list methods, to directly access your array, if you use the Arrays.asList
transformation method.
The alternative to the array is an ArrayList
, which is a collection of data that is resizeable and implements the interfaces List and Collection, to name a couple.
Two Dimensional Arrays
A two dimensional array in java is an array which is referencing other array objects.
Below code creates a two dimensional int array, and also we can see various uses of the two dimensional array.
You can clone a two dimensional array using the clone
method but it only clones the first dimension’s array reference, and so it also called shallow copy.
We can iterate through the array and copy it manually for a deep copy.
All this is demonstrated in the below code.
package maxCode.online.Arrays;
import java.util.Arrays;
public class TwoDimensionalArray {
public static void printArray(String arrayName, int[][] inputArray) {
System.out.println("------------------------------------------");
System.out.println(arrayName + " Reference: " + inputArray);
for (int row = 0; row < inputArray.length; row++) {
printRow(arrayName, inputArray[row], row);
}
}
public static void printRow(String arrayName, int[] inputArray, int row) {
System.out.println(arrayName + " : " + inputArray + " : Row " + (row + 1) + " : "
+ Arrays.toString(inputArray));
}
public static void main(String[] args) {
// Create a 2-d array
int[][] intArray = new int[2][10];
// Let's see what this looks like using the method we created
printArray("intArray", intArray);
// You can also print the 2-d array Using Arrays.deepToString()
System.out.println("Printing a multi-dimensional array using " + "Arrays.deepToString()");
System.out.println(Arrays.deepToString(intArray));
int[][] variableCols = { { 1, 2, 3 }, { 5, 6, 7, 8 }, { 0, 3, 4, 6 }, { 1 } };
printArray("variableCols", variableCols);
// Clone a copy of your 2-d array, but it is a shallow clone.
int[][] clonedArray = variableCols.clone();
printArray("Shallow copy - clonedArray", (int[][]) clonedArray);
// Arrays.copyOf works here, but need to cast back to 2-d array
int[][] copiedCopy = (int[][]) Arrays.copyOf(variableCols, variableCols.length);
printArray("copiedCopy", copiedCopy);
System.out.println("-------------------------------------------");
// Comparing our arrays, row 3....
printRow("variableCols", variableCols[2], 2);
printRow("copiedCopy", ((int[][]) copiedCopy)[2], 2);
printRow("clonedArray", ((int[][]) clonedArray)[2], 2);
System.out.println("-------------------------------------------");
// We can take our shallow copy and make it 'deep' manually.
System.out.println("-----Deep Copy-----");
for (int i = 0; i < clonedArray.length; i++) {
clonedArray[i] = clonedArray[i].clone(); // clone each element
}
// Change data on one of our original data points.
variableCols[2][3] = 10000;
// Comparing our arrays, row 3....
printRow("variableCols", variableCols[2], 2);
printRow("clonedArray", clonedArray[2], 2);
System.out.println("-------------------------------------------");
}
}
Output
------------------------------------------
intArray Reference: [[I@73a8dfcc
intArray : [I@ea30797 : Row 1 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
intArray : [I@7e774085 : Row 2 : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Printing a multi-dimensional array using Arrays.deepToString()
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
------------------------------------------
variableCols Reference: [[I@3f8f9dd6
variableCols : [I@aec6354 : Row 1 : [1, 2, 3]
variableCols : [I@1c655221 : Row 2 : [5, 6, 7, 8]
variableCols : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
variableCols : [I@1b701da1 : Row 4 : [1]
------------------------------------------
Shallow copy - clonedArray Reference: [[I@726f3b58
Shallow copy - clonedArray : [I@aec6354 : Row 1 : [1, 2, 3]
Shallow copy - clonedArray : [I@1c655221 : Row 2 : [5, 6, 7, 8]
Shallow copy - clonedArray : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
Shallow copy - clonedArray : [I@1b701da1 : Row 4 : [1]
------------------------------------------
copiedCopy Reference: [[I@442d9b6e
copiedCopy : [I@aec6354 : Row 1 : [1, 2, 3]
copiedCopy : [I@1c655221 : Row 2 : [5, 6, 7, 8]
copiedCopy : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
copiedCopy : [I@1b701da1 : Row 4 : [1]
-------------------------------------------
variableCols : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
copiedCopy : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
clonedArray : [I@58d25a40 : Row 3 : [0, 3, 4, 6]
-------------------------------------------
-----Deep Copy-----
variableCols : [I@58d25a40 : Row 3 : [0, 3, 4, 10000]
clonedArray : [I@ee7d9f1 : Row 3 : [0, 3, 4, 6]
-------------------------------------------