Arrays

Array Basics

An array is a collection of entities of the same type which are referenced by a single variable. The syntax, as given in the textbook, is:
int[] numbers;
numbers = new int[6];
We can, of course, merge these into a single statement:
int[] numbers = new int[6];
In the uninitialized state
int[] numbers;
it has the null value, like objects.

What you get, as indicated in the textbook, is a reference to a block of memory with 6 (in this case) int elements. We reference these elements by position, starting with position 0:
numbers:
ref
 
 
 
 
 
 

numbers:
ref
0
1
2
3
4
5
The individual elements are accessed by this syntax:
numbers[p],  for p = 0,1,…,5
They are variables and so we can both set and retrieve the values, e.g.:
numbers[0] = 10;
numbers[5] = 20;
int x = numbers[0]; // 10
int y = numbers[1]; // 10
This declaration/creation syntax applies to all Java types, e.g.,
double[] measurements = new double[10];
Student[] alumni = new Student[20];
In every case, Java initializes the newly-created variables by the default value of the Java type used.

Textbook examples

Let's take a look at the textbook's introductory examples.
ArrayDemo1.java  
This, intentionally, is meant to be a very clunky way to write the elements into an array, and the author follows closely with a much better approach:
ArrayDemo2.java  
In particular, the position index is usually a variable, not an integer constant. For example, we would almost never write the array elements in some "random" non-sequential order like:
hours[2] = keyboard.nextInt();
hours[0] = keyboard.nextInt();
hours[1] = keyboard.nextInt();

Array display

Note the loop used at the end to display the array; it's not a user-defined class. Can we simply print it? Try adding:
System.out.println(hours);
You'll see as the output some incomprehensible string. The part after the "@" is a representation of the memory reference. The array is one of the few Java built-in elements which cannot be printed directly.

Bounds Checking

Java will generate an error if the write operation attempts to write to a non-existent position in the array. In the ArrayDemo2.java program, replace the line:
for (int index = 0; index < EMPLOYEES; index++)
by this (changing < to <=):
for (int index = 0; index <= EMPLOYEES; index++)
You'll see the error after entering a number for Employee 4:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
The textbook refers to this problem as an "off by one error." In this course, we do not deal with exceptions, so we'll have to find a way to avoid them.

Partial array usage

The book's two examples tend to give the impression that the entire array must be used, but this is not so. Start with this version of the employee hours. Create the class and key it in.

EmployeeHours.java (version 1)
import java.util.Random;
import java.util.Scanner;
 
public class EmployeeHours {
 
  public static void main(String[] args) {
    final int MAX_EMPLOYEES = 100;
    int[] hours = new int[MAX_EMPLOYEES];
 
    Scanner keyboard = new Scanner(System.in);
 
    System.out.print("How many employees? : ");
    int num_employees = keyboard.nextInt();
 
    Random rand = new Random();
    for (int i = 0; i < num_employees; ++i) {
      hours[i] = rand.nextInt(16);
    }
 
    System.out.println("-------");
    for (int i = 0; i < num_employees; ++i) {
      System.out.println(hours[i]);
    }
    System.out.println("-------");
  }
}
select
Test run it. The printing feature is something we may want to reuse, so let's make it a static member:

EmployeeHours.java (version 2)
import java.util.Random;
import java.util.Scanner;
 
public class EmployeeHours {
 
  public static void main(String[] args) {
    final int MAX_EMPLOYEES = 100;
    int[] hours = new int[MAX_EMPLOYEES];
 
    Scanner keyboard = new Scanner(System.in);
 
    System.out.print("How many employees? : ");
    int num_employees = keyboard.nextInt();
 
    Random rand = new Random();
    for (int i = 0; i < num_employees; ++i) {
      hours[i] = rand.nextInt(16);
    }
 
    System.out.println("-------");
    print_array(hours, num_employees);
    System.out.println("-------");
  }
 
  static void print_array(int[] values, int size) {
    for (int i = 0; i < size; ++i) {
      System.out.println(values[i]);
    }
  }
}
select
Passing an array is like passing any other object: by-reference-by-value. Here's a diagram:

(parameter) values:
ref

(argument)  hours: 
ref
 
 
 
 
 
...
(argument)  hours: 
ref
0
1
2
3
4
...
In particular, changes made using the parameter values within the method will change the actual hours argument.

Other features

Once we have this array there are many operations we can perform. For example, try adding this feature:
Count the number of employees with less than 10 hours.

Array declaration alternative syntax

It turns out that the new [] syntax in the array declaration can be moved after the variable being declared, e.g.
int hours[] = new int[MAX_EMPLOYEES];
Used in this way the [] syntax is referred to as a declarator. You can see that works just as well for the array parameters; you can write:
static void print_array(int values[], int size)
As the textbook points out, what can go wrong with this usage is when multiple variables are declared in the same statement. For example:
int[] numbers, codes;
declares both variables as arrays. However if you write:
int numbers[], codes;
the outcome is quite different. It makes numbers an array, but codes simply an int.

The latter declarator style is considered somewhat of a legacy from the original C language. Usually it's preferable to use our original declaration style. If you really want what codes to be simply an int, make a separate declaration:
int[] numbers;
int codes;

Array Initialization and length

Java provides a way to initialize an array when you create it, like these examples:
int numbers = { 22, 30, 15, 17 };
double temperatures = { 33.2, 98.6, 75.1, };
This syntax uses curly braces, not brackets. The comma can optionally be placed after the last entry (unlike function argument). Doing so makes the entries more uniform; e.g., moving an entry to the first position is the same operation for all positions, including the last one:
double temperatures = { 75.1, 33.2, 98.6,  };
Here is an example from the textbook:
ArrayInitialization.java  
What should stand out as being a mistake is that 12 should not be hard-coded in the program. Yes, it is the number of months, and it is the size of the array, but we should be able to derive the length from the array variable itself, not by counting.

What we want is the new syntax:
days.length
Test it by keying in this shortened version:

ArrayInit.java
public class ArrayInit {
 
  public static void main(String[] args) {
    int[] days = {31, 28, 31, 30,};
 
    for (int index = 0; index < days.length; index++) {
      System.out.printf(
         "Month %s has %s days\n", index + 1, days[index]);
    }
  }
}
select

The enhanced for loop

Consider the simple loop:
int[] numbers = { 3, 7, 4, };
for (int i = 0; i < numbers.length; ++i) {
  System.out.println( numbers[i] );
}
The iterator variable i serves only to retrieve the value numbers[i] for printing. The idea of the enhanced for loop is to cut out the middle man, so to speak, and get the value we want directly. Here is the rewritten segment with the enhanced for loop.
int[] numbers = { 3, 7, 4, };
for (int value: numbers) {
  System.out.println( value );
}
The syntax is this:
dataType[] someArray = /* a "full" array */
// ...
for (dataType elementVariable : someArray) { ... }
This enhanced loop was not part of the original Java; it appeared as of Java version 1.5. The apparent goal is to try to mimick the simplicity of array iteration found in other programming languages.

Limitations of the enhanced for loop

This enhanced for loop does not always suit your needs. The textbook notes various limitations in the section which the enhanced loop is introduced.

For example, try a rewrite of the ArrayInit program from the last section. In this case we want the index position to identify the month number, but the enhanced for loop no longer makes the index position available. The solution is to introduce this index and manage it yourself.

ArrayInit.java (w/ enhanced for loop)
public class ArrayInit {
 
  public static void main(String[] args) {
    int[] days = {31, 28, 31, 30,};
 
    int index = 0;
    for (int value: days) {
      System.out.printf("Month %s has %s days\n", ++index, value);
    }
  }
}
Another limitation is that the value obtained from the iterator is read-only, and so you could not rewrite this loop:
int[] numbers = { 3, 7, 4, };
for (int i = 0; i < numbers.length; ++i) {
  numbers[i] += 2;
}
Yet another example of the limitation is when you access only a portion of the full array. Consider the EmployeeHours.java program above. The full array size is
MAX_EMPLOYEES = 100
But we use only a portion of it:
num_employees <= 100
The code which prints the hours array is this:
for (int i = 0; i < num_employees; ++i) {
   System.out.println(hours[i]);
}
It cannot be converted to the enhanced for loop (without introducing poor programming).

Copying Arrays

This section discusses how to and not to copy an array so that you create a separate duplicate.
SameArray.java  
What is wrong is the intended copy operation.
int[] array2 = array1;
with this outcome:
array2:
ref

array1:
ref
2
4
6
8
10

hours: 
ref
0
1
2
3
4
Given the setup in the program, the copy operation should be:
int [] array2 = new int[array1.length];
for (int i = 0; i < array1.length; ++i) {
  array2[i] = array1[i];
Once again, you cannot easily use the enhanced loop structure to achieve this outcome.

Example Array Algorithms

The section of the textbook is 7.4. We explored a number of these algorithms already, such as finding max, min, and average values of numerical arrays. The one new thing introduced in this section is using an array as a data member of a class. Here is the class:
SalesData.java  
and here is the main driver program:
Sales.java  

Returning Arrays from Methods

The section of the textbook is 7.5. Because an array is like an object, returning an array returns a reference to the array. Here is a demo program:
ReturnArray.java  
There is nothing really new here, just a proof of concept.

Arrays of Objects

The sections of the textbook are 7.6 and 7.7. Let's take a look at the textbook's examples of arrays of objects.

Array of Strings

MonthDays.java  
The point is to illustrate the new usage of a String array:
String[] months = 
   { "January", "February", "March", "April", "May", "June", "July",
     "August", "September", "October", "November", "December" };
Note how it is created just like an array of other primitive types. However, it is different in that we're actually getting an array of references. If we copy this array as we've indicated in the previous section, the references are copied. Fortunately, there will not be any associated problems because of the immutability of Strings.

From a programming perspective. The program wants to match an array of month names with an array of number of days. This technique is called parallel arrays. The problem is that it is somewhat error prone: We'll look at an improvement later.

When you have an array of Strings or other objects, you can access the member functions on the array elements. For example, to print the month names in upper case in the demo program use:
months[index].

Array of BankAccounts

We a class developed in the previous Object chapter.
BankAccount.java  
It is used in the following demo program:
ObjectArray.java  
First observe how the array of these objects is declared:
BankAccount[] accounts = new BankAccount[NUM_ACCOUNTS];
The next new thing is the creation of account at a specific index in the array, which occurs in the helper method createAccounts:
array[index] = new BankAccount(balance);
The last step is to display the balance for each account by calling the appropriate member function at each index:
accounts[index].getBalance()


© Robert M. Kline