CISC 1115
Introduction to Programming Using Java
Lecture #14
Techniques IV — Partially-Populated Arrays, Vectors, Parallel Arrays, Subarrays


Overview

Until now, we've created arrays whose size exactly matches the number of elements placed into the array. This is often impractical: There are two basic ways to address the above issues:

Partially Populated Arrays

Program 14.1

Write a program that reads in a sequence of numbers (until eof) from the file "numbers.text", and prints out each number together with whether it is above or below the average of the numbers. Assume a maximum of 100 numbers in the file
import java.io.*;
import java.util.*;

public class Program_14_1 {
        public static void main(String [] args) throws Exception {
                Scanner scanner = new Scanner(new File("numbers.text"));

                final int CAPACITY = 100;

                int [] arr = new int[CAPACITY];

                int size = read(scanner, arr, CAPACITY);

                double average = getAverage(arr, size);

                //for (int num : arr)
                for (int i = 0; i < size; i++)
                        System.out.println(arr[i] + " is " + (arr[i] < average ? "below" : "above") + " average");
        }

        public static int read(Scanner scanner, int [] arr, int capacity) {

                int size = 0;

                while (scanner.hasNextInt()) {
                        if (size >= capacity) {
                                System.out.println("Capacity exceeded - increase the size of your arrya");
                                System.exit(1);
                        }
                        arr[size] = scanner.nextInt();
                        size++;
                }

                return size;
        }

        public static double getAverage(int [] arr, int size) {
                return (double)getSum(arr, size)/size;
        }

        public static double getSum(int [] arr, int size) {
                int total = 0;

                for (int i = 0; i < size; i++)
                        total += arr[i];

                return total;
        }
}
Notes

Physical and Logical Size (Capacity vs Size)

Common Techniques for Logical Arrays

Reading in an array of known maximum size using (eof)

// using eof

final static int CAPACITY = 100;

double [] arr = new double[CAPACITY];
int size = 0;
while (scanner.hasNextInt()) {
	arr[size] = scanner.nextInt();
	size++;
}

// size now contains the actual number of elements read into the array

Reading in an array of known maximum size using a trailer value

// using a trailer of -1

final static int CAPACITY = 100;

double [] arr = new double[CAPACITY];

int size = 0;
arr[size] = scanner.nextInt();	// priming the pump
while (arr[size] >= 0) {
	size++;
	arr[size] = scanner.nextInt();
}

// size now contains the actual number of elements read into the array

Printing an array with a logical size

// Notice the second parameter

void print(double [] arr, int size) {
	System.out.print("{");
	for (int i = 0; i < size; i++)
		System.out.print(arr[i]+ " ");
	System.out.print("}");
}

The Rest of the Techniques

Vector/ArrayList — An Overview

A vector is an array whose size can grow as necessary. While the actual implementation of an actual vector isn't introduced until later (3115 and 3130), we can get already some sense of what they are. Furthermore, the techniques used for implementing vectors can be presented in a more 'low-tech' context — a sequence of elements with a known maximum size.

Vector-Oriented Techniques

Resizing an array

double [] resize(double [] arr) {
	double [] tmpArr = new double[arr.length * 2];
	for (int i = 0; i < arr.length; i++)
		tmpArr[i] = arr[i];
	return tmpArr;
}
double [] arr = new double[…];
…
arr = resize(arr);

Inserting an element into an array

Deleting an element from an array

Parallel Arrays

As we've seen, our programs often manipulate several pieces of information in performing their task:

Program 14.2

Write a program that reads in student data from a data file (whose name should be obtained from the user) consisting of name, midterm, and final, and prints the data to the console in two sections: first all those students who received a 90 or above on at least one exam, followed by the rest of the class.

The program should define the following methods:

import java.io.*;
import java.util.*;

public class Program_14_2 {
        public static void main(String [] args) throws Exception {
                Scanner scanner = new Scanner(new File("exams.text"));

                final int CAPACITY = 100;

                String [] names = new String[CAPACITY];

                int [] 
                        midterms = new int[CAPACITY],
                        finalExams = new int[CAPACITY];

                int size = read(scanner, names, midterms, finalExams, CAPACITY);

                print(names, midterms, finalExams, size);
        }

        public static int read(Scanner scanner, String [] names, int [] midterms, int [] finalExams, int capacity) {

                int size = 0;

                while (scanner.hasNext()) {
                        if (size >= capacity) {
                                System.out.println("Capacity exceeded - increase the size of your arrya");
                                System.exit(1);
                        }
                        names[size] = scanner.next();
                        midterms[size] = scanner.nextInt();
                        finalExams[size] = scanner.nextInt();
                        size++;
                }

                return size;
        }

        public static void print(String [] names, int [] midterms, int [] finalExams, int size) {
                System.out.println("Received at least one 90 or above");
                for (int i = 0; i < size; i++)
                        if (midterms[i] >= 90 || finalExams[i] >= 90)
                                System.out.println(names[i] + " " + midterms[i] + " " + finalExams[i]);
                System.out.println();
                System.out.println("Rest of the class");
                for (int i = 0; i < size; i++)
                        if (midterms[i] < 90 && finalExams[i] < 90)
                                System.out.println(names[i] + " " + midterms[i] + " " + finalExams[i]);
        }
}

Program 14.3

Write a program that reads in student data from a data file (whose name should be obtained from the user) consisting of last name, first name, midterm, and final. The program calculates each student's average, and grade, and prints out a roster consisting of all the information, together with whether the student performed above or below the class average.

The program should define the following methods:

import java.io.*;
import java.util.*;

public class Program_14_3 {
   public static void main(String [] args) throws Exception {
      Scanner keyboard = new Scanner(System.in);    
      
      System.out.print("roster file? ");
      String filename = keyboard.next();
      
      final int CAPACITY = 100;
      
      String [] 
         lastNames = new String[CAPACITY],
         firstNames = new String[CAPACITY];
      
      int [] 
         midterms = new int[CAPACITY],
         finals = new int[CAPACITY];
      
      double [] averages = new double[CAPACITY];
      
      char [] grades = new char[CAPACITY];
      
      int size = read(filename, lastNames, firstNames, midterms, finals, CAPACITY);
      
      calculateAverages(midterms, finals, averages, size);
      
      double classAverage = calculateClassAverage(averages, size);
      
      calculateGrades(averages, grades, size);
      
      printRoster(lastNames, firstNames, averages, grades, classAverage, size);
   }
   
   public static int read(String filename, String [] lastNames, String [] firstNames,
                          int [] midterms, int [] finals, int capacity) throws Exception {
      Scanner scanner = new Scanner(new File(filename));
      
      int size = 0;
      
      while (scanner.hasNext()) {
         if (size >= capacity) {
            System.out.print("Reached array capacity and still more data. Make the array bigger");
            System.exit(1);
         }
         lastNames[size] = scanner.next();
         firstNames[size] = scanner.next();
         midterms[size] = scanner.nextInt();
         finals[size] = scanner.nextInt();
         size++;
      }
      return size;
   }
      
   public static void calculateAverages(int [] midterms, int [] finals, double [] averages, int size) {
      for (int i = 0; i < size; i++)
         averages[i] = calculateOneAverage(midterms[i], finals[i]);
   }
      
   public static double calculateOneAverage(int midterm, int finalExam) {return (midterm + finalExam)/2.0;}
   
   public static double calculateClassAverage(double [] averages, int size) {
      double total = 0;
      for (int i = 0; i < size; i++)
         total += averages[i];
      return total / size;
   }

   public static void calculateGrades(double [] averages, char [] grades, int size) {
      for (int i = 0; i < size; i++)
         grades[i] = calculateOneGrade(averages[i]);
   }
   
   public static char calculateOneGrade(double average) {
      return average >= 90 ? 'A' : average >= 80 ? 'B' : average >= 70 ? 'C' : average >= 60 ? 'D' : 'F';
   }
   
   public static void printRoster(String [] lastNames, String [] firstNames, double [] averages, 
                                  char [] grades, double classAverage, int size) {
      for (int i = 0; i < size; i++)
         printOneStudent(lastNames[i], firstNames[i], averages[i], grades[i], classAverage);
   }
   
   public static void printOneStudent(String lastName, String firstName, double average, 
                                      char grade, double classAverage) {
      System.out.println(lastName + " " + firstName + " " + average + " " + grade + " " +
                       (average >= classAverage ? "Above" : "Below"));
  }
}

Using a Class

Separate variables vs a class:

Using Arrays:

import java.io.*;
import java.util.*;

public class Program_14_3 {
   public static void main(String [] args) throws Exception {
      Scanner keyboard = new Scanner(System.in);    
      
      System.out.print("roster file? ");
      String filename = keyboard.next();
      
      final int CAPACITY = 100;
      
      Student [] students = new Student[CAPACITY];
      
      int size = read(filename, students, CAPACITY);
      
      double classAverage = calculateClassAverage(students, size);
      
      printRoster(students, size, classAverage);
   }
   
   public static int read(String filename, Student [] students, int capacity) throws IOException {
      Scanner scanner = new Scanner(new File(filename));
      
      int size = 0;
      
      while (scanner.hasNext()) {
         if (size >= capacity) {
            System.out.print("Reached array capacity and still more data. Make the array bigger");
            System.exit(1);
         }
         String lastName = scanner.next();
         String firstName = scanner.next();
         int midterm = scanner.nextInt();
         int finalExam = scanner.nextInt();
            students[size] = new Student(lastName, firstName, midterm, finalExam);
         size++;
      }
      return size;
   }
      
   public static double calculateClassAverage(Student [] students, int size) {
      double total = 0;
      for (int i = 0; i < size; i++)
         total += students[i].average;
      return total / size;
   }
   
   public static void printRoster(Student [] students, int size, double classAverage) {
      for (int i = 0; i < size; i++)
         System.out.println(students[i] + " " + (students[i].average >= classAverage ? "Above" : "Below"));
   }
}

class Student {
        Student(String last, String first, int mid, int fin) {
                lastName = last;
                firstName = first;
                midterm = mid;
                finalExam = fin;
                average = (midterm + finalExam) / 2.0;
                grade = average >= 90 ? 'A' : average >= 80 ? 'B' : average >= 70 ? 'C' : average >= 60 ? 'D' : 'F';
        }
      
        public String toString() {return lastName + " " + firstName + " " + average + " " + grade;}

        String lastName, firstName;
        int midterm, finalExam;
        double average;
        char grade;
}

SubArrays — Subsequences of Arrays

Program 14.4

Write a program that reads in an array of integers from the file"numbers.text" (using a header value), prints the entire array, and then prompts the user for the first and last elements of a subarray to be printed.

The program should define and call the following methods:

import java.io.*;
import java.util.*;

public class Program_14_4 {
        public static void main(String [] args) throws Exception {
                Scanner scanner = new Scanner(new File("numbers.text"));

                int [] arr = read(scanner);

                print(arr);
                System.out.println();

                Scanner keyboard = new Scanner(System.in);

                System.out.print("First index to print: ");
                int first = keyboard.nextInt();
                System.out.print("Last index to print: ");
                int last = keyboard.nextInt();

                print(arr, first, last+1);
                System.out.println();
        }

        public static int [] read(Scanner scanner) {

                int size = scanner.nextInt();

                int [] arr = new int[size];

                for (int i = 0; i < size; i++)
                        arr[i] = scanner.nextInt();

                return arr;
        }

        public static void print(int [] arr) {
                System.out.print("{");
                for (int i = 0; i < arr.length; i++)
                        System.out.print(arr[i] + (i < arr.length-1 ? ", " : ""));
                System.out.print("}");
        }

        public static void print(int [] arr, int first, int end) {
                for (int i = first; i < end; i++)
                        System.out.print(arr[i] + (i < end-1 ? ", " : ""));
        }
}
Notes

Files used in this Lecture