300 likes | 433 Views
Objectives. By the end of this lecture, students should: understand the concepts of Arrays the differences between Array types and classes understand how to pass Arrays to/from Methods understand iteration over Arrays understand typical problems with Array code
E N D
Objectives • By the end of this lecture, students should: • understand the concepts of Arrays • the differences between Array types and classes • understand how to pass Arrays to/from Methods • understand iteration over Arrays • understand typical problems with Array code • be able to write Java Code involving n-dimensional Arrays • Reading: Savitch, Chapter 6
Arrays (Concept) • Conceptually an array is a table of values (or objects) of the same type. • The array name (variable) is a name for the whole table. • The value in a row can be • accessed by the row index • Arrays are the most fundamental way of aggregating multiple values. We will discuss other types of collections (Sets, Lists, Vectors, etc.) later. a a[3]
Array Storage • An array is usually stored in a contiguous block of memory locations for speed of access. • However, from the perspective of the high-level program the way variables are arranged in memory is of no semantic consequence. • What is important, is that the time required to access any array location is constant.
Declaring Arrays (Primitive Type) • An array type can be constructed from any base type or from any class. In the declaration the base type be given. Like an object, an array must be initialized with the “new” statement. This must specify the maximal index (number of rows). • int[] mytable; • mytable = new int[10]; • This can be summarized into a single initializing declaration: • int[] mytable = new int[10]; • You are allowed to later “re-intialize” the array.
Initializing Arrays • Arrays may be initialized with a list of suitable values. • The elements of a fresh array will automatically be set to the default value for the corresponding type, but it is bad style to rely on this. • int[] someNumbers = { 1, 3, 17, 21, 42}; • char[] someChars = {‘B’, ‘E’, ‘M’, ‘F’}; • In this case, neither a “new” statement nor the specification of the maximum index is required.
Array Access • Array elements are accessed but using the array name followed by the index in square brackets. This yields a value of the array’s base type. • int x; • x = someNumbers[4]; • System.out.println(someNumbers[2]); • Assignments to array elements use the same indexing syntax. • someNumbers[0] = 17; • someNumbers[2] = 22 + someNumbers[0];
Array Indexes • Array indexes always start with zero! • If your array has n Elements, the valid indexes are 0 … n-1 • the “read only instance variable” length gives you the length of an array. Thus 0 … (a.length-1) are the valid indexes for an array a. • If you are trying to access an index outside of this range Java will signal a “out of bounds” runtime error (technically speaking, it will throw an ArrayIndexOutOfBounds Exception. (We will meet exceptions later).
Example: MonthlyRainfall • Problem: using Rainfall Table • input month • output mean rainfall for that month
Example: MonthlyRainfall import java.util.*; public class WeatherReport { private static Scanner console = new Scanner(System.in); private static int[] table= { 30, 40, 45, 95, 130, 220, 210, 185, 135, 80, 40, 45 }; private static final String[] months= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; public int rainfall(int month) { return table[month-1]; } public void test() { System.out.print("Enter Month "); int thisMonth = console.nextInt(); System.out.print("Avg. Rainfall in "+months[thisMonth-1]+" is "); System.out.println(rainfall(thisMonth)); } }
Example: Input / Output of Arrays • The typical way to process an array is by looping over it. • Example - Input and print whole arrays: public void readRainTable() { for (int i=0; i < table.length; i++) { System.out.print("Enter Rainfall for " + months[i]+" "); table[i] = console.nextInt(); } } public void display() { System.out.println("Average Rainfalls per month are:"); for (int i=0; i < table.length; i++) System.out.println(months[i]+": "+table[i]+" mm"); }
Iterating over Arrays • Java (from Version 5) offers a convenient way to iterate • over arrays. This is the so-called “for-each” loop. It simply • iterates over all array elements in index order. • Let us re-write the display method. public int totalRain() { int result = 0; for (int x : table) result += x; return result; }
Iterating over Arrays: Pitfall • The problem is that the for-each loop effectively declares a local variable. So you cannot use the iterated variable of a for each loop to assign values to elements of the array. Try the following code. You will notice that the values in the array have not changed due to the first loop (Note: Savitch, p 373-374 is wrong here). public void tryScale() { for (int x : table) x = x / 10; for (int x : table) System.out.println(x); } This is because the first for-each loop is effectively equivalent to: for (int i=0; i<table.length; i++) { int x = table[i]; x = x / 10; }
Testing Bounds • To be on the safe side, you should always test whether array indexes are within the bounds, especially if they come from user input: public void saferTest() { System.out.print("Enter Month "); boolean monthValid = false; int thisMonth=0; while (! monthValid) { thisMonth = console.nextInt(); monthValid = ( 1 <= thisMonth && thisMonth <= 12 ); if (! monthValid) System.out.println("Incorrect Input. Try again."); } System.out.print("Avg. Rainfall in "+months[thisMonth-1]+" is "); System.out.println(rainfall(thisMonth)); }
Are Arrays Objects? • Arrays have a special status in Java. • You will hear different opinions on whether or not an array is an object. • An Array is not an object! • Evidence: • An array seems to have something like an instance variable “length”, but this is read only but not final. • You cannot send a message to an array • An array type is certainly not a class (you cannot subclass it!). As the type of an array is not a class, it cannot be an object.
Null Pointers and Exceptions • The name of an array is effectively just a reference to the table in memory. • The default initialization for any reference is a “Null pointer”. This is a special reference value that is used to mark a reference as invalid (uninitialized). • If you try to use a NULL reference like a normal object or array you will get a nun time error (NullPointerException) • int[] a; • System.out.println(a[1]); ---> NullPointerException • You can test whether a reference is NULL using “==“. • … • if (! (a==null)) System.out.println(“a is initialized”); • else System.out.println(“Problem: The array a is uninitialized”);
Passing Arrays to Methods • Arrays can be passed to and returned from methods much like any other type. Note that you do not need to specify the array length for the formal parameter. The following code prints the monthly rainfall in percentages. public void displayPercentage() { float [] percentageTable = toPercentage(table); System.out.println("Average Rainfalls per month are:"); for (int i=0; i < table.length; i++) System.out.println(months[i]+": "+percentageTable[i]+" %"); } public float[] toPercentage(int[] numbers) { int total = 0; float[] percentages = new float[numbers.length]; for (int x : numbers) total += x; for (int i = 0; i < percentages.length; i++) percentages[i] = 100 * numbers[i] / (float) total; return percentages; }
Modifying Arrays in called Methods • Note: Any change to a elements of an array that is a formal method parameter will be made to the original array, ie. they will be visible to the cllaed method. • Here, an array behaves like an object: The called method is given a reference to the original array and not a copy of it! We will return to this later in the section on “Parameter Passing”. • The following code effectively scales the actual instance variable “table”. public void doScale(int[] numbers) { for (int i=0; i < numbers.length; i++) numbers[i] /= 10; } public void scaleTest() { doScale(table); display(); }
Equality of Arrays • When comparing two arrays, it is important to know what you want to compare: • Equality of all array elements (ie. contents) • this needs to be done with a loop over all elements • The actual array “object” • this is done with “==“ int[] a = new int[10]; int[] b = new int[10]; for (int i = 0; i < 10; i++) { a[i] = 99; b[i]=99; } boolean objectEquality = (a==b) boolean contentsEquality = true; for (int i = 0; i < 10; i++) if (! (a[i]==b[i])) contentsEquality = false; System.out.println(“a and b are the same array: “+ objectEquality); System.out.println(“a and b have the same contents: “+ contentsEquality);
Arrays of Objects • Base types for arrays can of course also be classes. • You have to be aware that the objects are not automatically generated. You need to create these yourself. • The following code generates, initializes and returns an array of students (given the student class from earlier lectures): public Student[] studentList(int length) { Student[] newList = new Student[length]; for (int i=0; i<length; i++) newList[i]= new Student(); return newList; }
Null Pointers and Exceptions • If the base type of an array is a class or a another array (a reference type), then the cells of this array do not directly contain values but references to objects (or arrays). • The default initialization for any reference is a “Null pointer”. This is a special reference value that is used to mark a reference as invalid (uninitialized). • You can test whether a reference is NULL using “==“. • If you try to use a NULL reference like a normal object or array you will get a nun time error (NullPointerException)
Two-dimensional Arrays • An array type is just another (non-basic) type. • As you can construct arrays from any type, you can also construct them from arrays. • An “array-of-arrays” is called “multi-dimensional” because you need to specify several ordinates to locate an actual element. • Consider a two-dimensional table: • Each row is a 1-dimensional array • The entire table is an array of its rows
Example: YearlyRainfall month year Average Yearly Rainfall (in mm) private static final int[][] yearlyTable = { {30,40,75,95,130,220,210,185,135,80,40,45}, {25,25,80,75,115,270,200,165, 85, 5,10, 0}, {35,45,90,80,100,205,135,140,170,75,60,95}, {30,40,70,70, 90,180,180,210,145,35,85,80}, {30,35,30,90,150,230,305,295, 60,95,80,30} };
Declaring Multidimensional Arrays • The declaration is equivalent to 1d-Arrays. • int [][] yearlyTable = new int[5][12]; • You can give all indexes, but you only need to give the first index initially • (why? Explain!) • int [][] yearlyTable = new int[5][]; • … • yearlyTable[0] = new int[12]; • yearlyTable[1] = new int[12]; • yearlyTable[2] = new int[12]; • …
Example (cont): Accessing 2d Arrays To access the elements of a 2d-Array you simply give to indexes. The following method retrieves and returns a single entry from the yearly rainfall table public int rainfall(int month, int year) { return yearlyTable[year-1][month-1]; }
Example (cont): Accessing 2d Arrays Keep in mind that a two-dimensional array is simply an array-of-arrays: You can access an entire row by just giving a single index. The following code uses this to compute Rainfall percentages for a particular year: public void displayPercentagesForYear(int year) { float [] percentageTable = toPercentage(yearlyTable[year]); System.out.println( "Average Rainfalls per month in year "+year+" are:"); for (int i=0; i < table.length; i++) System.out.println(months[i]+": "+percentageTable[i]+" %"); } public float[] toPercentage(int[] numbers) { … Note that the only difference to the previous “displayPercentages” is that the 1d array used as the actual parameter in the call is now a single-indexed 2d array. We are using the same “toPercentage” method as before.
Iteration over a 2-d Array • To iterate over all elements in a 2d-array you need two nested loops. • One of these iterates over the rows, the other over each column in each of the rows. public void printYearlyTotals() { int total = 0; for (int i=0; i<yearlyTable.length; i++) { int totalForYear = 0; for (int j=0; j<yearlyTable[i].length; j++) totalForYear += yearlyTable[i][j]; System.out.println( "Total Rainfall for Year "+i+" is "+ totalForYear+" mm"); total += totalForYear; } System.out.println( "Total Rainfall For All Years is "+total+" mm"); }
Iteration over a 2-d Array • You can use for-each loops instead of regular loops, • but you need to bear bear the restrictions of for-each loops in mind. public void printYearlyTotals2() { int total = 0; for (int[] row : yearlyTable) { int totalForYear = 0; for (int elem : row) totalForYear += elem; total += totalForYear; } System.out.println( "Total Rainfall For All Years is ” +total+" mm"); }
To Infinity and Beyond (n-dimensional) • Of course, there is nothing that restricts you to two dimensions. You can use a 2d-array as the base type for a 3d-array and so on. • Try to extend the example to a 3d-array, that handles yearly rainfall data for a number of years and a number of different cities. • These are given as: private static final String[] cities {“Melbourne”, “Munich”, “Paris”, “Boulder”};
Ragged Arrays • Note (advanced, optional): As a 2d-array is just an array of arrays, there is no reason why all rows have to have the same length. You can use “ragged” arrays: • int [][] raggedTable = new int[4][]; • raggedTable[0] = new int[4]; • raggedTable[1] = new int[6]; • raggedTable[2] = new int[3]; • raggedTable[3] = new int[5]; • You need to be very careful not to run “out of bounds” when indexing this array, as each row has a different length. Always check using “.length”.
Reading • Savitch, Chapter 6