n
).
The simplest way of reading a sequence of numbers and storing them so we can access them individually again is to use an array. The Java declaration
int[] a;declares variable
a
to be of type
array of int
s, or another way of putting it,
int
is the base type of array a
. All the
components of an array must be of the same base type, and each may be
accessed individually using an index. Indexing in Java (like C) always
starts at 0, so a
is made up of separate parts a[0]
,
a[1]
and so on, each of which may be considered a separate
int
variable. A lot of the power of arrays comes from the
ability to use index expressions with them, in other words any
Java expression which evaluates to an integer may occur between the
[
and ]
and is evaluated as the program is run.
For example, if we have variable i
of type int
,
a[i]
refers to the section of a
indexed by whatever
value is in variable i
at the time.
Note that in Java (and here it differs from C) the declaration of an array
variable does not reserve computer store for an array. That must be done
separately through a new
statement. So once we have the previous
declaration int[] a
, to actually make an array of ten
int
s, we need the command
a = new int [10];The
int
s in a
are then a[0]
,
a[1]
and so on up to a[9]
. It is, however, possible
to combine the array declaration and creation in one statement using the
declaration with initialisation capability of Java, so in this case that would be:
int [] a = new int [10];As a simple example, here is a program which just reads in a list of numbers, storing them in an array, and then prints them out:
1 import java.io.*; 2 3 class Numbers0 4 { 5 // Read a number of integers and store them in an array. 6 7 public static void main (String[] args) throws IOException 8 { 9 int [] data; 10 int number,count; 11 BufferedReader in = Text.open(System.in); 12 System.out.print("Type the number of integers that will be entered: "); 13 number=Text.readInt(in); 14 data = new int[number]; 15 for(count=0; count<number; count++) 16 { 17 System.out.print("Enter number "+(count+1)+": "); 18 data[count]=Text.readInt(in); 19 } 20 System.out.println("The numbers entered were:"); 21 for(count=0;count<number;count++) 22 System.out.print(data[count]+" "); 23 System.out.println(); 24 } 25 }Here the array is called
data
It is declared on line 9, but
created on line 14. In this case its later creation means we can use the
number read in, and stored in variable number
to indicate the
size of array to create. The variable count
used in the loop
on lines 15-19 has its value increased by one each time round the loop, so
each time round the loop, data[count]
refers to a new store
location within data
. In the loop on lines 21-22,
count
again cycles in value from 0 to the point where it equals
the value in number
and hence the loop is exited, this time
it is used to print out all the integers stored in array data
.
Note that this example, along with the other examples on this web page, and some further examples of programs with arrays of integers may be found in the directory
/import/teaching/BSc/1st/ItP/numbers
Numbers0
and develop a
few operations on arrays of numbers. Here is a program which, like
Numbers0
reads a sequence of numbers, stores them in an array
and prints them out. But it also find the average, the biggest and the
smallest numbers.
1 import java.io.*; 2 3 class Numbers1 4 { 5 // Read a number of integers and store them in an array. 6 // Find and print the biggest and smallest number and the average. 7 8 public static void main (String[] args) throws IOException 9 { 10 int [] data; 11 int number; 12 double average; 13 BufferedReader in = Text.open(System.in); 14 System.out.print("Type the number of integers that will be entered: "); 15 number=Text.readInt(in); 16 data=NumberOps0.readall(number,in); 17 System.out.println("The numbers entered were:"); 18 NumberOps0.printall(data); 19 System.out.println("The biggest is: "+NumberOps0.biggest(data)); 20 System.out.println("The smallest is: "+NumberOps0.smallest(data)); 21 System.out.print("The average is: "); 22 average=NumberOps0.average(data); 23 System.out.println(Text.writeDouble(average,5,3)); 24 } 25 }The program doesn't look much, and the reason for that is that most of the real work has been put into a separate class, called
NumberOps0
.
This class has a collection of static methods which do the operations we are
interested in. Here it is:
1 import java.io.*; 2 3 class NumberOps0 4 { 5 6 public static int[] readall(int n,BufferedReader reader) 7 throws IOException 8 // Create an array of n integers, read them from reader 9 { 10 int count; 11 int [] a = new int[n]; 12 for(count=0; count<n; count++) 13 { 14 System.out.print("Enter number "+(count+1)+": "); 15 a[count]=Text.readInt(reader); 16 } 17 return a; 18 } 19 20 public static void printall(int [] a) 21 // Print the contents of array a 22 { 23 int i; 24 for(i=0; i<a.length; i++) 25 System.out.print(a[i]+" "); 26 System.out.println(); 27 } 28 29 public static int biggest(int [] a) 30 // return the biggest number in array a 31 { 32 int i,current=a[0]; 33 for(i=1; i<a.length; i++) 34 if(a[i]>current) 35 current=a[i]; 36 return current; 37 } 38 39 public static int smallest(int [] a) 40 // return the smallest number in array a 41 { 42 int i,current=a[0]; 43 for(i=1; i<a.length; i++) 44 if(a[i]<current) 45 current=a[i]; 46 return current; 47 } 48 49 public static double average(int [] a) 50 // return the average of the numbers in array a 51 { 52 int i,sum=0; 53 for(i=0; i<a.length; i++) 54 sum+=a[i]; 55 return (double)sum/a.length; 56 } 57 58 }As you can see, the program is broken up into small fragments, each of which are self-contained, with the
main
method just acting as a
framework bringing them together. Breaking programs up into small parts like
this is recommended as a way of keeping them easy to read, understand and
modify.
The first method in NumberOps0
is the most complex one. However,
all its is really doing is taking the code from lines 14-19 of
Numbers0
and making a separate method out of it. The method
resulting, called readall
can then be re-used whenever it is
required to read a sequence of numbers and store them in an array which
is created for the purpose, just by making a method call similar to that
in line 16 of Numbers1
. Note that readall
takes
as an argument not only the number of integers that are to be read, but
also the reader from which they are to be read. Internally in readall
the reader is called reader
, but the call on line 16 of
Numbers1
means this local variable is instantiated to
the BufferedReader
value in variable in
there,
which line 13 in Numbers1
set to a reader of characters typed
into the command window. The method readall
returns the array
it has created and filled with the numbers read, so its return type is
int[]
. So note it is perfectly possible in Java to have an
array type as a return type. The command on line 16 of Numbers1
means the array referred to locally as a
in readall
is assigned to the variable data
in Numbers1
.
As readall
in NumberOps0
makes use of
BufferedReader
from the java.io
package it is
necessary to have the import
statement on line 1 of
NumberOps0
. Also, since Text.readInt
on line 15
of NumberOps0
can throw the checked exception
IOException
, as this exception is not caught in
readall
it is necessary to indicate, as is done on line 7,
that readall
may throw an IOException
.
The method printall
on lines 20-27 of NumberOps0
turns what was done on lines 21-23 of Numbers0
into a
separate method. As this method does not return any value, but instead has
a side-effect (i.e. it prints the numbers in the array), it has return
type void
, and the call to it on line 18 of Numbers1
forms a statement of its own. One difference between printall
and lines 21-23 of Numbers0
is that printall
does
not have a separate variable holding the size (i.e. number of elements)
of the array. However, the size of any array a
is given by
the integer value a.length
, and this is used in printall
on line 24.
The biggest
and smallest
methods in
NumberOps0
both work by having a variable called
current
, initially set to the first item in the array
(i.e. the one indexed by 0
). The remaining integers in the
array are then looked at in turn, replacing current
by any
bigger/smaller integer found. So at any point in the execution of these
methods the variable current
hold the value of the biggest/smallest
integer stored in that portion of the array which has been looked at so far.
When the whole array has been considered, and the loop is exited with control
passing to line 36 or 46, current
must hold the value of the
biggest/smallest integer in the whole array. So the value in current
is returned as the output of the method. As these methods return a value,
the calls to them, on lines 19 and 20 of Numbers1
occur in the
place where the value is used.
The average
runs through the array, adding together all the
numbers in it in the variable sum
. At any point in the
execution of average
, the variable sum
must hold
the sum of the integers in that portion of the array that has been looked at.
When the whole array has been considered and the loop is exited with control
passing to line 55, sum
must hold the sum of all the integers
in the array. Note that as in the Average
examples, the
average is calculated using floating point division so that it can be
quoted to several decimal places. This means the return type of average
is double
, with the division of the sum of the integers by the
number of integers being done within the average
method.
It is possible to write a program which performs similarly to
Numbers1
but does not divide the code up into separate
parts. For comparison, such a program is given below:
1 import java.io.*; 2 3 class Numbers1a 4 { 5 6 // Read a number of integers and store them in an array. 7 // Find and print the biggest and smallest number and the average. 8 // Program deliberately written as a single method. 9 10 public static void main (String[] args) throws IOException 11 { 12 int [] data; 13 int number,count; 14 int currentBiggest,currentSmallest,sum; 15 double average; 16 BufferedReader in = Text.open(System.in); 17 System.out.print("Type the number of integers that will be entered: "); 18 number=Text.readInt(in); 19 data = new int[number]; 20 for(count=0; count<number; count++) 21 { 22 System.out.print("Enter number "+(count+1)+": "); 23 data[count]=Text.readInt(in); 24 } 25 System.out.println("The numbers entered were: "+data[0]+" "); 26 currentBiggest=data[0]; 27 currentSmallest=data[0]; 28 sum=data[0]; 29 for(count=1;count<number;count++) 30 { 31 System.out.print(data[count]+" "); 32 sum+=data[count]; 33 if(data[count]>currentBiggest) 34 currentBiggest=data[count]; 35 else if(data[count]<currentSmallest) 36 currentSmallest=data[count]; 37 } 38 System.out.println(); 39 System.out.println("The biggest is: "+currentBiggest); 40 System.out.println("The smallest is: "+currentSmallest); 41 average=(double)sum/number; 42 System.out.println("The average is: "+Text.writeDouble(average,5,3)); 43 } 44 }This program has the minor advantage of being slightly more efficient as after reading it in, it only goes through the array once (on lines 29-37), doing the operations of printing, summing and checking for being bigger or smaller than the current biggest or smallest all in one go with each integer. However, because it is not broken up into separate parts with separate functions, it is not so easy to see what it does. Additionally, it is not possible to re-use the components of this program, whereas the methods in
NumberOps0
may be re-used whenever it is required
to perform the relevant operation on an array.
1 import java.io.*; 2 3 class Numbers2 4 { 5 6 // Read a number of integers and store them in an array. 7 // Find and print the biggest and smallest number and the average. 8 9 static final int SENTINEL = -999; 10 static final int MAXNUMS = 100; 11 12 public static void main (String[] args) throws IOException 13 { 14 int [] data; 15 int count,n; 16 double average; 17 BufferedReader in = Text.open(System.in); 18 data = new int[MAXNUMS]; 19 for(count=0; ;count++) 20 { 21 System.out.print("Enter number "+(count+1)+" (or "); 22 System.out.print(SENTINEL+" to finish): "); 23 n=Text.readInt(in); 24 if(n==SENTINEL) 25 break; 26 data[count]=n; 27 } 28 System.out.println("The numbers entered were:"); 29 NumberOps.printall(data,count); 30 System.out.println("The biggest is: "+NumberOps.biggest(data,count)); 31 System.out.println("The smallest is: "+NumberOps.smallest(data,count)); 32 System.out.print("The position of the biggest is: "); 33 System.out.println(NumberOps.posBiggest(data,count)+1); 34 System.out.print("The position of the smallest is: "); 35 System.out.println(NumberOps.posSmallest(data,count)+1); 36 System.out.print("The average is: "); 37 average=NumberOps.average(data,count); 38 System.out.println(Text.writeDouble(average,5,3)); 39 } 40 }In this case the idea of having a separate method to read the array is abandoned. Part of the problem is that if there were to be such a method it would really need to return both the array itself and the number of integers read, but a method can only return one value. We will see ways of dealing with this later. Note that the maximum number of items in the array is given as a constant, declared on line 10. The operations on the array are similar to those of before, but they have to take an extra argument giving the number of integers in the array that are actually being dealt with. The code for them is given below:
1 class NumberOps 2 { 3 // Operations on an array of integers a, 4 // dealing with the first n integers only. 5 6 public static void printall(int [] a,int n) 7 // Print the first n contents of array a 8 { 9 int i; 10 for(i=0; i<n; i++) 11 System.out.print(a[i]+" "); 12 System.out.println(); 13 } 14 15 public static int biggest(int [] a,int n) 16 // find the biggest of the first n contents of array a 17 { 18 int i,current=a[0]; 19 for(i=1; i<n; i++) 20 if(a[i]>current) 21 current=a[i]; 22 return current; 23 } 24 25 public static int smallest(int [] a,int n) 26 // find the smallest of the first n contents of array a 27 { 28 int i,current=a[0]; 29 for(i=1; i<n; i++) 30 if(a[i]<current) 31 current=a[i]; 32 return current; 33 } 34 35 public static int posBiggest(int [] a,int n) 36 // find the position of the biggest of the first n contents of array a 37 { 38 int i,pos=0; 39 for(i=1; i<n; i++) 40 if(a[i]>a[pos]) 41 pos=i; 42 return pos; 43 } 44 45 public static int posSmallest(int [] a,int n) 46 // find the position of the smallest of the first n contents of array a 47 { 48 int i,pos=0; 49 for(i=1; i<n; i++) 50 if(a[i]>a[pos]) 51 pos=i; 52 return pos; 53 } 54 55 public static double average(int [] a,int n) 56 // find the average of the first n contents of array a 57 { 58 int i,sum=0; 59 for(i=0; i<n; i++) 60 sum+=a[i]; 61 return (double)sum/n; 62 } 63 }In this program we have included two extra methods
posBiggest
and posSmallest
which give the array index of the biggest and
smallest elements. It is important to distinguish
these from the actual values of the biggest and smallest elements - a common
source of errors in programs dealing with arrays is failing to note this
distinction between a value and an index to where the value is stored in
an array. Note that in the actual output of the program, 1 is added to
the output of these index methods, to reflect the fact that in Java what
we would think of as the "first" element in an array is indexed by 0, what
we would think of as the "second" element is indexed by 1 and so on.
Note that attempting to access an element of an array by using an index which
goes beyond the size of the array as it was created causes an exception of
the type ArrayIndexOutOfBoundsException
. This is a run-time
exception, so it did not have to be signalled with a throws
statement. However, it can be caught if a try
statement is
written to catch it. Here is a program similar to the above which uses
a try
statement to catch the use of an array index beyond
the bounds of the array:
1 import java.io.*; 2 3 class Numbers3 4 { 5 6 // Read a number of integers and store them in an array. 7 // Find and print the biggest and smallest number and the average. 8 9 static final int SENTINEL = -999; 10 static final int MAXNUMS = 10; 11 12 public static void main (String[] args) throws IOException 13 { 14 int [] data; 15 int count=0,n; 16 double average; 17 BufferedReader in = Text.open(System.in); 18 data = new int[MAXNUMS]; 19 try 20 { 21 for(count=0; ;count++) 22 { 23 System.out.print("Enter number "+(count+1)+" (or "); 24 System.out.print(SENTINEL+" to finish): "); 25 n=Text.readInt(in); 26 if(n==SENTINEL) 27 break; 28 data[count]=n; 29 } 30 } 31 catch(ArrayIndexOutOfBoundsException e) 32 { 33 System.out.println("Cannot take more than "+MAXNUMS+" numbers"); 34 } 35 System.out.println("The numbers entered were:"); 36 NumberOps.printall(data,count); 37 System.out.println("The biggest is: "+NumberOps.biggest(data,count)); 38 System.out.println("The smallest is: "+NumberOps.smallest(data,count)); 39 System.out.print("The average is: "); 40 average=NumberOps.average(data,count); 41 System.out.println(Text.writeDouble(average,5,3)); 42 } 43 }Here, if during the execution of lines 21-29 an attempt is made to index an array using an index beyond its bounds, execution goes to line 33 and prints out the error message there. In fact this use of a out-of-bounds index can only occur if an attempt is made to read more numbers than the size of array, which will occur at line 28. As the for loop which starts at line 21 has an empty condition part there, it can only be exited by such an exception or by the sentinel being read, causing a break initiated at line 27. In both cases, the next step is to execute line 35 and subsequent statements. The size of the array has been reduced to 10 by changing the constant declaration on line 10, thus enabling the effect to be easily demonstrated.
Note that there is no need to write another file of methods here, as the
methods we have already used in NumberOps
are used in this
Numbers3
class as well. We save effort by reusing them.
These notes were produced as part of the course Introduction to Programming as it was given in the Department of Computer Science at Queen Mary, University of London during the academic years 1998-2001.
Last modified: 6 Oct 1998