JMU JMU - Department of Computer Science
Help Tools
Lab: Experimenting with Arrays of Arrays


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

Getting Ready: Before going any further, you should:

  1. Depending on your development environment, create either a directory or a project for this lab.
  2. Setup your development environment.
  3. Download the following files:
    to an appropriate directory/folder. (In most browsers/OSs, the easiest way to do this is by right-clicking/control-clicking on each of the links above.)

1. Declaration, Memory Allocation, and Assignment: This part of the lab will help you understand the declaration of arrays of arrays, and the allocation of memory for arrays of arrays.
  1. Create a file named DataUtilities.java that contains the following.
    import java.io.*;
    import java.util.*;
    
    public class DataUtilities
    {
        
        public static int[][] create(int rows, int columns)
        {
    
    
    
            return data;
        }    
    }
    
  2. Add the following declaration to the top of the create() method.
            int[rows][columns]       data;
    
  3. Will this statement compile? If so, why? If not, why not?


    It will not compile. Memory for arrays is allocated dynamically in Java using the new operator. The size of the array can't be included in the declaration.
    Expand
  4. Change the declaration at the top of the create() method to:
            int[][]       data;
    
  5. Will this statement compile?


    It will compile.
    Expand
  6. Carefully explain this declaration.


    data is declared to be an array of int[]. That is, it is declared to be an array of int arrays.
    Expand
  7. Add the following statements to the create() method after the declaration of data but before the return statement.
            int[] furniture  = {100,  95, 485, 290};
            int[] appliances = {300, 100,   0, 500};
    
    
  8. Will these statements compile? If not, why not? If so, carefully explain them.


    They will compile. They each declare a variable to be an int[] and assign values to the elements of the array.
    Expand
  9. How many elements are in the arrays named furniture and appliances?


    They both have four elements.
    Expand
  10. Add the following statement below the declarations of furniture and appliances.
            data = new int[rows][];
    
  11. Will this statement compile? If not, why not? If so, carefully explain what this statement will do when executed.


    It will compile. It will construct an array that can hold references to rows different int[] objects (and assign the reference to the array to the variable named data).
    Expand
  12. Add the following statement below the instantiation of data
            data[0] = furniture;
    
  13. What type is data?


    It is an int[][] (i.e., an array of int[]).
    Expand
  14. What type is data[0]?


    It is an int[].
    Expand
  15. What type is furniture?


    It is an int[].
    Expand
  16. Will this statement compile?


    It will compile. It assigns an int[] to an int[].
    Expand
  17. How many elements are there in data (after it is instantiated)?


    There are rows elements.
    Expand
  18. How many elements are there in furniture (after it is initialized)?


    There are four elements.
    Expand
  19. How many elements are there in data[0] (after it is initialized)?


    There are four elements.
    Expand
  20. Add the following statement below the instantiation of data
            data[1] = appliances;
    
  21. Will this statement compile?


    It will compile. It assigns an int[] to an int[].
    Expand
  22. What is the (return) type of the create() method?


    int[][] (i.e., an array of int[]).
    Expand
  23. Will the return statement compile?


    Yes. data is an int[][] and create() is declared (to return) an int[][].
    Expand
  24. Compile DataUtilities.java. (It should compile.)
2. Nested Loops and Arrays of Arrays: This part of the lab will help you understand how to use nested loops to iterate over the elements in an array of arrays.
  1. Add a static method named print() to the DataUtilities class that is passed an int[][] named table, an int named rows and an int named columns and doesn't return anything.
  2. What code did you add?


        public static void print(int[][] table, int rows, int columns)
        {
        }
    
    Expand
  3. Add the following code to the body of the print() method.
            for (int r = 0; r < rows; r++)
            {
                for (int c = 0; c < columns; c++)
                {
                    System.out.printf("%8d ", table[r][c]);                
                }
                System.out.printf("\n");            
            }
    
  4. Explain this method.


    The outer loop iterates rows times. During each outer iteration, the inner loop iterates columns times. During each inner iteration, it prints an element of table. After an inner iteration is completed, it prints a newline character.
    Expand
  5. Suppose rows is 2 and columns is 4. How many int values will be printed?


    Each inner loop will print four values. The inner loop will be executed twice. So, in total, eight int values will be printed.
    Expand
  6. Compile DataUtilities.java. (It should compile.)
  7. Create a file named Driver.java that contains the following.
    public class Driver
    {
        public static void main(String[] args)
        {
    
    
        }
    }
    
  8. Add the following declaration to the top of the main() method.
            int[][]     sales;
            
            sales = DataUtilities.create(2, 4);
            DataUtilities.print(sales, 2, 4);
    
  9. Explain why the last two statements in this method will compile.


    The second statement will compile because the create() method is passed the correct number and type of parameters and returns a int[][] that is an assigned to a variable that is declared to be an int[][].

    The third statement will compile because the print() method is passed the correct number and type of parameters.

    Expand
  10. Compile and execute Driver.
  11. What is output?


         100       95      485      290
         300      100        0      500
    
    Expand
  12. Modify the call to create() as follows.
            sales = DataUtilities.create(3, 4);
    
  13. Will Driver compile?


    Yes.
    Expand
  14. Will Driver execute properly? Why or why not?


    Yes. The int[][] array that is constructed in create() will have an extra element (row) that won't be used, but it will not cause a run-time exception.
    Expand
  15. Modify the call to create() as follows.
            sales = DataUtilities.create(2, 2);
    
  16. Will Driver compile?


    Yes.
    Expand
  17. Will Driver execute properly? Why or why not?


    Yes. Though columns is, in some sense, wrong, it is not used for anything in the create() method.
    Expand
  18. Modify the call to create() as follows.
            sales = DataUtilities.create(1, 4);
    
  19. Will Driver compile?


    Yes.
    Expand
  20. Will Driver execute properly? Why or why not?


    No. An ArrayIndexOutOfBoundsException will be thrown when the attempt is made to assign appliances to data[1]. Because rows is 1, when data is instantiated it only has an element 0.
    Expand
  21. Modify the call to create() as follows.
            sales = DataUtilities.create(2, 4);
    
  22. Modify the call to print() as follows.
            DataUtilities.print(sales, 1, 3);
    
  23. Will Driver compile?


    Yes.
    Expand
  24. Will Driver execute without throwing an exception?


    Yes (but only some of the values will be printed).
    Expand
  25. Modify the call to print() as follows.
            DataUtilities.print(sales, 2, 5);
    
  26. Will Driver compile?


    Yes.
    Expand
  27. Will Driver execute without throwing an exception?


    No. It will throw an ArrayIndexOutOfBoundsException when c is 4.
    Expand
  28. Modify the call to print() as follows.
            DataUtilities.print(sales, 3, 4);
    
  29. Will Driver compile?


    Yes.
    Expand
  30. Will Driver execute without throwing an exception?


    No. It will throw an ArrayIndexOutOfBoundsException when r is 2.
    Expand
  31. Do arrays have a length attribute?


    Yes.
    Expand
  32. Modify the print() method so that the outer loop uses the length of table.
  33. Will code did you add/change?


    The outer loop is now:
            for (int r = 0; r < table.length; r++)
    
    Expand
  34. Will Driver execute without throwing an exception?


    Yes.
    Expand
  35. What type is table[0]?


    It is an int[].
    Expand
  36. How can you "access" the length of table[0]?


    table[0].length.
    Expand
  37. How can you "access" the length of table[1]?


    table[1].length.
    Expand
  38. How can you "access" the length of table[r]?


    table[r].length.
    Expand
  39. Using the answer to the previous question, modify the print() method so that the inner loop no longer uses the parameter columns.
  40. Will code did you add/change?


    The inner loop is now:
                for (int c = 0; c < table[r].length; c++)
    
    Expand
  41. Does the print() method use the parameters rows and columns?


    No.
    Expand
  42. Remove the formal parameters rows and columns from the print() method and the corresponding actual parameters from the call to this method.
  43. Compile and execute your code to make sure everything is correct.
3. A Review of Reference Types: This part of the lab will help refresh your memory about reference types (particularly arrays).
  1. Add the following statement to the create() method in the DataUtilities class after appliances is assigned to data[1] but before the return statement.
            appliances[500] = 999;        
    
  2. Will this statement compile?


    Yes. appliances is an int[] and 999 is an int.
    Expand
  3. Why doesn't the compiler throw an ArrayIndexOutOfBoundsException?


    Because that's a runtime exception. The compiler does not check to see if array indexes are out of bounds. Indeed, in most cases it couldn't because the size of arrays is determined at runtime.
    Expand
  4. Change the statement to:
            appliances[2] = 999;        
    
  5. Execute Driver. What is output?


         100       95      485      290
         300      100      999      500
    
    Expand
  6. Why is 999 now output rather than 0?


    We often say that data[1] is an int[], but it is really a reference to an int[]. When appliances is assigned to data[1] the two become aliases for the same array. So, appliances[2] and data[1][2] refer to the same int value (i.e., 999).
    Expand
  7. Change the assignment statements in create() to the following:
            data[0] = appliances;
            appliances[2] = 999;        
            data[1] = appliances;
    
  8. What will be output now?


         300      100      999      500
         300      100      999      500
    
    Expand
  9. Why?


    Now, data[0], data[1], and appliances are all aliases.
    Expand
4. Revisiting Some Earlier Topics: This part of the lab returns briefly to some topics considered earlier.
  1. Change the assignment statements in create() back to the following:
            data[0] = furniture;
            data[1] = appliances;
    
  2. Compile and execute Driver. What was outupt?


         100       95      485      290
         300      100        0      500
    
    Expand
  3. Change the assignment statements in create() back to the following:
            data[0] = furniture;
            data[1] = appliances;
    
  4. Change the initialization of furniture as follows.
            int[] furniture  = {100,  95, 485};
    
  5. Compile and execute Driver. What was outupt?


         100       95      485
         300      100        0      500
    
    Expand
  6. Are you surprised?


    Of course not. I knew that my implementation of the print() method would handle this situation.
    Expand
  7. Change the initializations of furniture and appliances as follows: as follows.
            int[] furniture  = {100,  95, 485, 290, 880, 730};
            int[] appliances = {300, 100};
    
  8. Compile and execute Driver. What was outupt?


         100       95      485      290       80      730
         300      100
    
    Expand
  9. Are you surprised?


    Again, I knew that my implementation of the print() method would handle this situation. I rock!
    Expand
  10. Add the following statement before the return statement.
            data[2] = furniture;
    
  11. Will this statement compile?


    Yes.
    Expand
  12. Will it execute without throwing a run-time exception?


    No. It will throw an ArrayIndexOutOfBoundsException because data only has two elements indexed 0 and 1.
    Expand
  13. Comment-out the implementation of the create() method in the DataUtilities class and the call to the create() method in the Driver class.
5. Reading Arrays of Arrays from a File: This part of the lab will help you understand some of the issues that arise when reading arrays of arrays from a file. It will involve the use of the files containing annual sales data (in millions of dollars) of U.S. retail and food services firms. The data are from the Annual Retail Trade Survey. The lines/rows of the file correspond to the following kinds of firms: motor vehicle and parts dealers; electronics and appliance stores; building materials and garden equipment and supplies dealers; food and beverage stores; health and personal care stores; gasoline stations; clothing and clothing accessories stores; sporting goods, hobby, book, and music stores; general merchandise stores; miscellaneous store retailers; nonstore retailers; and food services and drinking places. In one file the columns correspond to the years 2009-2013 and in the other file the columns correspond to the years 1992-2013.
  1. Add the following code to the DataUtilities class.
        public static int[][] read(String name, int rows, int columns)
            throws FileNotFoundException
        {
            int[][]       data;
            Scanner       scanner;
    
            scanner = new Scanner(new File(name));
            scanner.useDelimiter(",|\\r\\n");
    
    
        }
    

    Note that the Scanner in this method treats both the comma character and the carriage return character followed by the line feed character as delimiters. A comma is used between columns and a carriage return followed by a line feed is used between rows.

  2. Add a statement that instantiates data so that it has rows elements, each of which contains an array of column elements. What code did you add?


            data = new int[rows][columns];
    
    Expand
  3. Add an outer for loop that iterates over the rows. What code did you add?


            for (int r = 0; r < rows; r++)
            {
            }
    
    Expand
  4. Add an inner for loop that iterates over the columns. What code did you add?


                for (int c = 0; c < columns; c++)
                {
                }
    
    Expand
  5. Inside the two loops, add a statement that calles the nextInt() method of scanner and assigns the result to the appropriate element of data. What code did you add?


                    data[r][c] = scanner.nextInt();                
    
    Expand
  6. Add a return statement.


            return data;
    
    Expand
  7. Modify Driver so that it now contains the following code.
    import java.io.*;
    
    
    public class Driver
    {
        public static void main(String[] args)
        {
            int[][]     sales;
            
            try
            {
                sales = DataUtilities.read(args[0], 12, 5);        
                DataUtilities.print(sales);
            }
            catch (FileNotFoundException fnfe)
            {
                System.out.println("Unable to open " + args[0]);
            }
        }
    }
    
  8. Compile and execute Driver, passing it sales_2009-2013.txt as the command-line argument.
  9. Is the output correct? (You can either load the .txt file into a text editor or a spreadsheet to check.)


    Yes.
    Expand
  10. Execute Driver, passing it sales_1992-2013.txt as the command-line argument.
  11. Is the output correct? (You can either load the .txt file into a text editor or a spreadsheet to check.)


    No.
    Expand
  12. Why is the output incorrect? (Oops - I gave away the answer to the previous question.)


    It's incorrect because the bigger file has more than 5 columns.
    Expand
  13. Since the existing read() method reads one element at a time it must know the number of row and columns. One could, instead, create a read() method that reads a row at a time (as a line). To that end, add the following code to the DataUtilities class.
        public static int[][] read(String name, int rows)
            throws FileNotFoundException
        {
            int[][]       data;
            int[]         row;        
            String        line;
            Scanner       scanner;
            
            scanner = new Scanner(new File(name));
    
        }
    
  14. (Review) There are now two read() methods with different signatures in the DataUtilities class. What word is used to describe this situation?


    Overloading (i.e., the read() method is said to be overlaoded).
    Expand
  15. Add a statement that instantiates data so that it has rows elements, each of which contains an int[]. What code did you add?


            data = new int[rows][];
    
    Expand
  16. Add a for loop that iterates over the rows. What code did you add?


            for (int r = 0; r < rows; r++)
            {
            }
    
    Expand
  17. Inside the for loop, add a statemen that reads the next line from scanner and assigns the result to the variable named line. What code did you add?


                line   = scanner.nextLine();
    
    Expand
  18. Inside the for loop, add a statement that calls the line object's split() method, passing it the String literal ",", and assigning the result to the variable rows. What code did you add?


                tokens = line.split(",");
    
    Expand
  19. Inside the for loop, add a statement that instantiates element r of data to be an int[] that contains as many elements as tokens. What code did you add?


                data[r] = new int[tokens.length];
    
    Expand
  20. Add an inner for loop that iterates over the elements of tokens, converts each to an int, and assigns that int to the appropriate element of data. What code did you add?


                for (int c = 0; c < tokens.length; c++)
                {
                    data[r][c] = Integer.parseInt(tokens[c]);
                }
    
    Expand
  21. Modify Driver so that it uses this version of the read() method. What code did you change?


    I changed:

                sales = DataUtilities.read(args[0], 12, 5);        
    

    to:

                sales = DataUtilities.read(args[0], 12);        
    
    Expand
  22. Compile and execute Driver, passing it sales_2009-2013.txt as the command-line argument.
  23. Is the output correct? (You can either load the .txt file into a text editor or a spreadsheet to check.)


    Yes.
    Expand
  24. Execute Driver, passing it sales_1992-2013.txt as the command-line argument.
  25. Is the output correct? (You can either load the .txt file into a text editor or a spreadsheet to check.)


    Yes.
    Expand

Copyright 2019