Chapter 6: Arrays
Array Basics
-
An array is used to store a collection of data, but it often more useful to think of an array as a collection of variables of the same type.
-
Instead of declaring individual variables, such as num0, num1, …, and num99, you declare one array variable such as num and use num[0] , num[1], …, num[99] to represent individual variables.
Declaring Array Variables
-
To use an array in a program, you must declare a variable to reference the array, and you must specify the type of array the variables can reference.
-
Here is the syntax for declaring an array variable:
dataType[ ] arrayRefVar; double[ ] myList; //preferred style
dataType arrayRefVar[ ]; double myList[ ]; //not preferred style
Creating Arrays
-
Declaration of an array variable doesn’t allocate any space in memory for the array.
-
Only a storage location for the reference to an array is created.
-
If a variable doesn’t reference to an array, the value of the variable is null.
-
You cannot assign elements to an array unless it has already been created.
-
After an array variable is declared, you can create an array by using the new operator with the following syntax:
arrayRefVar = new dataType[arraySize];
-
This statement does two things:
-
It creates an array using new dataType[arraySize];
-
It assigns the reference of the newly created array to the variable arrayRefVar.
-
Declaring an array variable, creating an array, and assigning the reference of the array to the variable can be combined in one statement, as follows:
dataType[]arrayRefVar = new dataType[arraySize]; or
dataType arrayRefVar [] = new dataType[arraySize];
double[] myList = new double[10];
-
This statement declares an array variable, myList, creates an array of ten elements of double type, and assigns its reference to myList.
-
Figure below illustrates an array with sample element values.
-
The array myList has ten elements of double type and int indices from 0 to 9.
Note:
-
An array variable that appears to hold an array actually contains a reference to that array.
-
Strictly speaking, an array variable and an array are different, but most of the time the distinction between them can be ignored.
-
Thus, it is alright to say, for simplicity, that myList is an array, instead of stating, at greater length, that myList is a variable that contains a reference to an array of ten double elements.
-
When the distinction makes a subtle difference, the longer phrase should be used.
Array Size and Default values
-
When space for an array is allocated, the array size must be given, to specify the number of elements that can be stored in it.
-
The size of an array cannot be changed after the array is created.
-
Size can be obtained using arrayRefVar.length myList.length is 10.
-
When an array is created, its elements are assigned the default value of 0 for the numeric primitive data types, ‘\u000’ for char types, and false for Boolean types.
Array Indexed Variables
-
The array elements are accessed through the index.
-
Array indices are 0-based, they start from 0 to arrayRefVar.length-1.
-
Each element in the array is represented using the following syntax:
arrayRefVar[index];
-
The element myList[9] represents the last element in the array. Indices are from 0 to 9.
-
After an array is created, an indexed variable can be used in the same way as a regular variable. For example:
myList[2] = myList[0] + myList[1];//adds the values of the 1st and 2nd
elements into the 3rd one
-
The following loop assigns 0 to myList[0] 1 to myList[1] .. and 9 to myList[9]:
for (int i = 0; i < myList.length; i++)
myList[i] = i;
Array Initializers
-
Java has a shorthand notation, known as the array initializer that combines declaring an array, creating an array and initializing in one statement:
double[] myList = {1.9, 2.9, 3.4, 3.5};
-
This shorthand notation is equivalent to the following statements:
double[] myList = new double[4];
myList[0] = 1.9;
myList[1] = 2.9;
myList[2] = 3.4;
myList[3] = 3.5;
Caution
-
The new operator is not used in the array initializer syntax.
-
Using an array initializer, you have to declare, create, and initialize the array all in one statement.
-
Splitting it would cause a syntax error. For example, the following is wrong:
double[] myList;
myList = {1.9, 2.9, 3.4, 3.5};
Processing Arrays
-
When processing array elements, you will often use a for loop. Here are the reasons why:
-
All of the elements in an array are of the same type. They are evenly processed in the same fashion by repeatedly using a loop.
-
Since the size of the array is known, it is natural to use a for loop.
-
Here are some examples of processing arrays:
-
Initializing arrays with random values 0.0 – 99.0
for (int i = 0; i < myList.length; i++)
myList[i] = Math.random() * 100;
-
Printing arrays by using a loop like the one shown below
for (int i = 0; i < myList.length; i++)
System.out.print(myList[i] + “ “);
Tip: for an array of the char[] type, it can be printed using one print statement.
char[] city = {‘D’, ‘a’, ‘l’, ‘l’, ‘a’, ‘s’};
System.out.println(city); displays Dallas
-
Summing array elements by using variable named total to store the sum. Initially total is 0. Add each element in the array to total, using a loop like this:
double total = 0;
for (int i = 0; i < myList.length; i++)
total += myList[i];
-
Finding the largest element, use a variable named max to store the largest element. To find the largest element in the array myList, compare each element in myList with max, and update max if the element is greater than max.
double max = myList[0];
for (int i = 0; i < myList.length; i++) {
if (myList[i] > max)
max = myList[i];
}
-
Finding the smallest index of the largest element, used to locate the largest element in an array. If an array has more than one largest element, find the smallest index of such an element. Suppose the array myList is {1, 5, 3, 4, 5, 5}. The largest element is 5, and the smallest index for 5 is 1. Use a variable named max to store the largest element and a variable named indexOfMax is 0. Compare each element in myList with max, and update max and indexOfMax if the element is greater than max.
double max = myList[0];
int indexOfMax = 0;
for (int i = 0; i < myList.length; i++) {
if (myList[i] > max) {
max = myList[i];
indexOfMax = i;
}
}
foreach Loops
-
A foreach loop is an enhanced for loop, which enables you to traverse the complete array sequentially without using an index variable.
-
The following code displays all the elements in the array myList:
for (double element: myList) {
System.out.println(element);
}
-
You can read the code as “for each element in myList do the following.”
-
Note that the variable, element, must be declared the same type as the element in myList.
-
You still have to use an index variable if you wish to traverse the array in a different order or change the elements in the array.
Example: Testing Arrays
-
The following program finds the largest number and counts its occurrences.
// TestArray.java: Count the occurrences of the largest number
import javax.swing.JOptionPane;
public class TestArray {
/** Main method */
public static void main(String[] args) {
final int TOTAL_NUMBERS = 6;
int[] numbers = new int[TOTAL_NUMBERS];
// Read all numbers
for (int i = 0; i < numbers.length; i++) {
String numString = JOptionPane.showInputDialog(
"Enter a number:");
// Convert string into integer
numbers[i] = Integer.parseInt(numString);
}
// Find the largest
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (max < numbers[i])
max = numbers[i];
}
// Find the occurrence of the largest number
int count = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == max) count++;
}
// Prepare the result
String output = "The array is ";
for (int i = 0; i < numbers.length; i++) {
output += numbers[i] + " ";
}
output += "\nThe largest number is " + max;
output += "\nThe occurrence count of the largest number "
+ "is " + count;
// Display the result
JOptionPane.showMessageDialog(null, output);
}
}
-
The program declares and creates an array of six integers. It finds the largest number in the array, and displays the result.
-
To display the array, you need to display each element in the array using a loop.
-
Without using the numbers array, you would have to declare a variable for each number entered, b/c all the numbers are compared to the largest number to count its occurrences after it is found.
Caution
-
Accessing an array out of bound is a common programming error that throws a runtime error ArraIndexOutOfBoundsException. To avoid it, make sure that you don’t use an index beyond arrayRefVar.length-1.
-
Programmers often mistakenly reference the first element in an array with index 1, so that the index of the 10th element becomes 10. This is called the off-by-one-error.
Example: Assigning Grades
-
Objective: read student scores, get the best score, and then assign grades based on the following scheme:
-
Grade is A if score is >= best – 10;
-
Grade is B if score is >= best – 20;
-
Grade is C if score is >= best – 30;
-
Grade is D if score is >= best – 40;
-
Grade is F otherwise.
-
The program prompts the user to enter the total number of students, then prompts the user to enter all of the scores, and concludes by displaying the grades.
// AssignGrade.java: Assign grade
import javax.swing.JOptionPane;
public class AssignGrade {
/** Main method */
public static void main(String[] args) {
// Get number of students
String numOfStudentsString = JOptionPane.showInputDialog(
"Please enter number of students: ");
// Convert string into integer
int numOfStudents = Integer.parseInt(numOfStudentsString);
int[] scores = new int[numOfStudents]; // Array scores
int best = 0; // The best score
char grade; // The grade
// Read scores and find the best score
for (int i = 0; i < scores.length; i++) {
String scoreString = JOptionPane.showInputDialog(
"Please enter a score:");
// Convert string into integer
scores[i] = Integer.parseInt(scoreString);
if (scores[i] > best)
best = scores[i];
}
// Declare and initialize output string
String output = "";
// Assign and display grades
for (int i = 0; i < scores.length; i++) {
if (scores[i] >= best - 10)
grade = 'A';
else if (scores[i] >= best - 20)
grade = 'B';
else if (scores[i] >= best - 30)
grade = 'C';
else if (scores[i] >= best - 40)
grade = 'D';
else
grade = 'F';
output += "Student " + i + " score is " +
scores[i] + " and grade is " + grade + "\n";
}
// Display the result
JOptionPane.showMessageDialog(null, output);
}
}
-
The program declares scores as an array of int type in order to store the students’ scores after the user enters the number of students into numOfStudents.
-
The size of the array is set at runtime; it cannot be changed once the array is created.
Copying Arrays
-
Often, in a program, you need to duplicate an array or a part of an array. In such cases you could attempt to use the assignment statement (=), as follows:
list2 = list1;
-
This statement does not copy the contents of the array referenced by list1 to list2, but merely copies the reference value from list1 to list2. After this statement, list1 and list2 reference to the same array, as shown below.
-
Before the assignment statement, list1 and list2 point to separate memory locations.
-
After the assignment, the reference of the list1 array is passed to list2.
The array previously referenced by list2 is no longer referenced; it becomes garbage, which will be automatically collected by the Java Virtual Machine. -
You can use assignment statements to copy primitive data type variables, but not arrays.
-
Assigning one array variable to another variable actually copies one reference to another and makes both variables point to the same memory location.
-
There are three ways to copy arrays:
-
Use a loop to copy individual elements.
-
Use the static arraycopy method in the System class.
-
Use the clone method to copy arrays. “Introduced in chapter 9.”
-
You can write a loop to copy every element from the source array to the corresponding element in the largest array.
-
The following code, for instance, copies sourceArray to targetArray using a for loop:
int[] sourceArray = {2, 3, 1, 5, 10};
int[] targetArray = new int[sourceArray.length];
for (int i = 0; i < sourceArrays.length; i++)
targetArray[i] = sourceArray[i];
-
Another approach is to use arraycopy method in the java.lang.System class to copy arrays instead of using a loop. The syntax for arraycopy is shown below:
arraycopy(sourceArray, src_pos, targetArray, tar_pos, length);
-
The parameters src_pos and targetArray indicate the starting positions in sourceArray and targetArray, respectively.
-
The number of elements copied from sourceArray to targetArray is indicated by length.
-
For example, you can rewrite the loop using the following statement:
System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);
-
The arraycopy does not allocate memory space for the target array. The target array must have already been created with its memory space allocated.
-
After the copying takes place, targetArray and sourceArray have the same content but independent memory locations.
http://java.sun.com/docs/books/tutorial/java/data/copyingarrays.html
The arraycopy method requires five arguments:
public static
void arraycopy(Object source,
int srcIndex,
Object dest,
int destIndex,
int length,
The two Object arguments indicate the array to copy from and the array to copy to. The three integer arguments indicate the starting location in each the source and the destination array, and the number of elements to copy. The following figure illustrates how the copy takes place:
The following program, ArrayCopyDemo, uses arraycopy to copy some elements from the copyFrom array to the copyTo array.
Public class ArrayCopyDemo {
public static void main(String[] args) {
char[] copyFrom = { ‘d’, ‘e’, ‘c’, ‘a’, ‘f’, ‘f’, ‘e’,
‘I’, ‘n’, ‘a’, ‘t’, ‘e’, ‘d’ };
char[] copyTo = new char[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7);
System.out.println(new String(copyTo));
}
}
Output: caffein
-
The arraycopy method call in this example program begins the copy at element number 2 in the source array. Recall that array indices start at 0, so that the copy begins at the array element ‘c’.
-
The arraycopy method call puts the copied elements into the destination array beginning at the first element (element 0) in the destination array copyTo. The copy copies 7 elements: ‘c’, ‘a’, ‘f’, ‘f’, ‘e’, ‘I’, and ‘n’. Effectively, the arraycopy method takes the “caffein” out of “decaffeinated”, like this:
Note that the destination array must be allocated before you call arraycopy and must be large enough to contain the data being copied.
Summary of Arrays -
An array is a fixed-length data structure that can contain multiple objects of the same type. An array can contain any type of object, including arrays. To declare an array, you use the type of object that the array can contain and brackets.
-
The length of the array must be specified when it is created. You can use the new operator to create an array, or you can use an array initializer. Once created, the size of the array cannot change. To get the length of the array, you use the length attribute.
-
An element within an array can be accessed by its index. Indices begin at 0 and end at the length of the array minus 1.
-
To copy an array, use the arraycopy method in the System class.
Passing Arrays to Methods
-
The following method displays the elements of an int array:
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
-
The following invokes the method to display 3, 1, 2, 6, 4, and 2.
int[] list = {3, 1, 2, 6, 4, 2};
printArray(list);
printArray(new int[]{3, 1, 2, 6, 4, 2});
-
The preceding statement creates an array using the following syntax:
New dataType[] {value0, value1, …, valuek};
-
There is no explicit reference variable for the array. Such an array is called an anonymous array.
-
Java uses pass by value to pass arguments to a method. There are important differences between passing the values of variables of primitive data types and passing arrays.
-
For an argument of a primitive type, the argument’s value is passed.
-
For an argument of an array type, the value of an argument contains a reference to an array; this reference is passed to the method.
public class Test {
public static void main(String[] args) {
int x = 1; // x represents an int value
int[] y = new int[10]; // y represents an array of int values
m(x, y); // Invoke m with arguments x and y
System.out.println("x is " + x);
System.out.println("y[0] is " + y[0]);
}
public static void m(int number, int[] numbers) {
number = 1001; // Assign a new value to number
numbers[0] = 5555; // Assign a new value to numbers[0]
}
}
x is 1
y[0] is 5555
-
This is because y and numbers reference to the same array, although y and numbers are independent variables.
-
When invoking m(x, y), the values of x and y are passed to number and numbers.
-
Since y contains the reference value to the array, numbers now contains the same reference value to the same array.
-
The JVM stores the array in an area of memory called the heap, which is used for dynamic memory allocation where blocks of memory are allocated and freed in an arbitrary order.
-
The primitive type value in x is passed to number, and the reference value in y is passed to numbers.
Example: Passing Array Arguments
-
Write two methods for swapping elements in an array. The first method, named swap, fails to swap two int arguments. The second method, named swapFirstTwoInArray, successfully swaps the first two elements in the array argument.
public class TestPassArray {
/** Main method */
public static void main(String[] args) {
int[] a = {1, 2};
// Swap elements using the swap method
System.out.println("Before invoking swap");
System.out.println("array is {" + a[0] + ", " + a[1] + "}");
swap(a[0], a[1]);
System.out.println("After invoking swap");
System.out.println("array is {" + a[0] + ", " + a[1] + "}");
// Swap elements using the swapFirstTwoInArray method
System.out.println("Before invoking swapFirstTwoInArray");
System.out.println("array is {" + a[0] + ", " + a[1] + "}");
swapFirstTwoInArray(a);
System.out.println("After invoking swapFirstTwoInArray");
System.out.println("array is {" + a[0] + ", " + a[1] + "}");
}
/** Swap two variables */
public static void swap(int n1, int n2) {
int temp = n1;
n1 = n2;
n2 = temp;
}
/** Swap the first two elements in the array */
public static void swapFirstTwoInArray(int[] array) {
int temp = array[0];
array[0] = array[1];
array[1] = temp;
}
}
Result:
Before invoking swap
array is {1, 2}
After invoking swap
array is {1, 2}
Before invoking swapFirstTwoInArray
array is {1, 2}
After invoking swapFirstTwoInArray
array is {2, 1}
-
The two elements are not swapped using the swap method.
-
The second method works. The two elements are actually swapped using the swapFirstTwoInArray method.
-
Since the parameters in the swap method are primitive type, the values of a[0]and a[1]are passed to n1 and n2 inside the method when invoking swap (a[0], a[1]).
-
The memory locations for n1 and n2 are independent of the ones for a[0]and a[1].
-
The contents of the array are not affected by this call.
-
The parameter in the swapFirstTwoInArray method is an array.
-
As shown above, the reference of the array is passed to the method.
-
Thus the variables a (outside the method) and array (inside the method) both refer to the same array in the same memory location.
-
Therefore, swapping array[0]with array[1]inside the method swapFirstTwoInArray is the same as swapping a[0]with a[1] outside of the method.
Returning an Array from a Method
-
You can pass arrays to invoke a method. A method may also return an array.
-
For example, the method below returns an array that is the reversal of another array:
public static int[] reverse(int[] list) {
int[] result = new int[list.length]; // creates new array result
for (int i = 0, j = result.length - 1; // copies array elements
i < list.length; i++, j--) { // list to array result
result[j] = list[i];
}
return result; // returns array
}
-
The following statement returns a new array list2 with elements 6, 5, 4, 3, 2, 1:
int[] list1 = new int[]{1, 2, 3, 4, 5, 6};
int[] list2 = reverse(list1);
Searching Arrays
-
Searching is the process of looking for a specific element in an array; for example, discovering whether a certain score is included in a list of scores.
-
Searching is a common task in computer programming.
-
There are many algorithms and data structures devoted to searching. In this section, two commonly used approaches are discussed, linear search and binary search.
The Linear Search Approach
-
The linear search approach compares the key element key sequentially with each element in the array.
-
The method continues to do so until the key matches an element in the array or the array is exhausted without a match being found.
-
If a match is made, the linear search returns the index of the element in the array that matches the key.
-
If no match is found, the search returns -1.
-
The program below does the following:
-
The key search method compares the key with each element in the array.
-
The elements in the array can be in any order.
-
On Average, the algorithm will have to compare half of the elements in an array before finding the key if it exists.
-
Since the execution time of a linear search increases linearly as the number of array elements increases, linear search is inefficient for a large array.
Note
The program Listing 6.6 page 286 in book is incomplete, however, the one below is:
public class LinearSearch {
/** The method for finding a key in the list */
public static void main(String[] args) {
int[ ] list = {1, 4, 4, 2, 5, -3, 6, 2};
int i = linearSearch(list, 4);
int j = linearSearch(list, -4);
int k = linearSearch(list, -3);
System.out.println("The First Search Returns\t " + i);
System.out.println("The Second Search Returns\t " + j);
System.out.println("The Third Search Returns\t " + k);
}
public static int linearSearch(int[] list, int key) {
for (int i = 0; i < list.length; i++)
if (key == list[i])
return i;
return -1;
}
}
Answer: The First Search Returns 1
The Second Search Returns -1
The Third Search Returns 5
list
key
Compare key with list[i] for i = 0, 1, …
[0] [1] [2] …
list
key
Compare key with list[i] for i = 0, 1, …
[0] [1] [2] …
list
key
Compare key with list[i] for i = 0, 1, …
[0] [1] [2] …
The Binary Search Approach
-
For binary search to work, the elements in the array must already be ordered. Without loss of generality, assume that the array is in ascending order.
e.g., 2 4 7 10 11 45 50 59 60 66 69 70 79
-
The binary search first compares the key with the element in the middle of the array.
-
Consider the following three cases:
-
If the key is less than the middle element, you only need to search the key in the first half of the array.
-
If the key is equal to the middle element, the search ends with a match.
-
If the key is greater than the middle element, you only need to search the key in the second half of the array.
-
Clearly, the binary search method eliminates half of the array after each comparison.
-
Suppose that the array has n elements. For convenience, let n be a power of 2.
-
After the first comparison, there are n/2 elements left for further search.
-
After the second comparison, there are (n/2)/2 elements left for search.
-
After the kth comparison, there are n/2k elements left for further search.
-
When k = log2n, only one element is left in the array, and you only need one more comparison.
-
Therefore, the worst case, you need log2n + 1 comparisons to find an element in the stored array when using the binary search approach.
-
For a list of 1024 (210) elements, binary search requires only eleven comparisons in the worst case, where as linear search would take 1024 comparisons in the worst case.
-
The portion of the array being searched shrinks by half after each comparison. Let low and high denote, respectively, the first index and last index of the array that is currently being searched.
-
Initially, low is 0 and high is list.length-1.
-
Let mid denote the index of the middle element. So mid is (low + high) / 2.
Figure below shows how to find key 11 in the list {2 4 7 10 11 45 50 59 60 66 69 70 79} using binary search.
-
The binary Search method returns the index of the search key if it is contained in the list.
-
Otherwise, it returns – (insertion point + 1). The insertion point is the point at which the key would be inserted into the list.
-
For example, the insertion point for key 5 is 2, so the binary search returns -3; the insertion point for key 51 is 7, so the binary search returns -8.
public class BinarySearch {
/** Use Binary Search for finding a key in the list */
public static void main(String[] args) {
int[ ] list = {2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70,
79};
int i = binarySearch(list, 2);
int j = binarySearch(list, 11);
int k = binarySearch(list, 12);
System.out.println("The First Search Returns\t " + i);
System.out.println("The Second Search Returns\t " + j);
System.out.println("The Third Search Returns\t " + k);
}
public static int binarySearch(int[] list, int key) {
int low = 0;
int high = list.length - 1;
while (high >= low) {
int mid = (low + high) / 2;
if (key < list[mid])
high = mid - 1;
else if (key == list[mid])
return mid;
else
low = mid + 1;
}
return -low -1;
}
}
The Array Class
-
The java.util.Arrays class contains various static methods for sorting and searching arrays, comparing arrays, and filling array elements.
-
These methods are overloaded for all primitive types.
-
Since binary search is frequently used in programming, Java provides several overloaded binarySearch methods for searching a key in an array of int, double, char, short, long, and float in the java.util.Arrays class.
-
For example, the following code searches the keys in an array of numbers and an array of characters.
int[] list = {2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79};
System.out.println("Index is " + java.util.Arrays.binarySearch(list, 11));
Return is 4
char[] chars = {'a', 'c', 'g', 'x', 'y', 'z'};
System.out.println("Index is " + java.util.Arrays.binarySearch(chars, 't'));
Return is –4 (insertion point is 3, so return is -3-1)
-
For the binarySearch method to work, the array must be pre-sorted in increasing order.
Two-dimensional Arrays
// Declare array ref var
dataType[][] refVar;
// Create array and assign its reference to variable
refVar = new dataType[10][10];
// Combine declaration and creation in one statement
dataType[][] refVar = new dataType[10][10];
// Alternative syntax
dataType refVar[][] = new dataType[10][10];
int[][] matrix = new int[10][10];
or
int matrix[][] = new int[10][10];
matrix[0][0] = 3;
for (int i = 0; i < matrix.length; i++)
for (int j = 0; j < matrix[i].length; j++)
matrix[i][j] = (int)(Math.random() * 1000);
double[][] x;
You can also use an array initializer to declare, create and initialize a two-dimensional array. For example,
Share with your friends: |