More Methods and Arrays Material from Chapter 7 that we didn’t cover in 1226
More from Chapter 7 Objects with Arrays Arrays of Objects use arrays as instance variables using partly-filled-in arrays understand co-reference Arrays of Objects creating and filling in an array of objects
Using Arrays with Classes Each student has several grades array as an instance variable of Student only some assignments graded so far Several students in a course array of Student objects Make a grade sheet program list of Students, each with grades Student.java ClassList.java GradeSheet.java
Arrays as Instance Variables Change our Student class so that it has an array of grades rather than a single grade grades in 8 assignments, say stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 100 98 86 94 96
Array IV, Getter, and Setter Seems like this is the way to do it: private int[] asgnGrades; public int[] getAsgnGrades() { return asgnGrades; } public void setAsgnGrades(int[] newGrades) { if (areValidGrades(newGrades)) { // add this method asgnGrades = newGrades; But later we’ll see a problem with this!
The Constructor The constructor’s job is to give the first values to each of the instance variables constructor needs to give a value to asgnGrades just an array with eight zeroes should have a constant for the eight values! public static final int NUM_ASGN = 8; public Student(String name) { … this.asgnGrades = new int[Student.NUM_ASGN]; }
More Methods Get/set assignment grades individually use 1-based index in the method int a1Grade = stu.getGrade(1); stu.setGrade(2, 100); stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 100 98 86 94 96 81 a1Grade 100
getGrade Method A1 stored in asgnGrades[0], and so on public int getGrade(int asgnNum) { if (1 <= asgnNum && asgnNum <= NUM_ASGN) { return asgnGrade[asgnNum – 1]; } return 0; should make an isValidAsgnNo method the setter will use it, too! there’s an exercise for you!
Exercise Write the setGrade method /** * Set this student’s grade for the given assignment. * @param asgnNum the assignment number * @param grade the grade got for that assignment */ public void setGrade(int asgnNum, int grade) { … } use the isValidAsgnNo method from the previous method
More Methods Calculate assignment average grade double aveGrade = stu.getAverage(); maybe another method that drops low scores? double aveWithDrops = stu.getAverageDropping(2) stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 100 98 86 94 96 91.25 aveGrade 95.66667 aveWithDrops
Unmarked Assignments? What if only two assignments graded? still have zeroes on the rest what does our average calculator do? what should it do? stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 19.5 aveGrade
Partly Full Arrays Sometimes we want space for lots… need space for all 8 assignment grades …but using only some of them now only two have been graded so far Need to keep track of how many are in use another variable – instance or class? average method needs to use it
Using Partly Full Arrays We can make arrays the size user wants… …but user might not know! “Lots here, and more coming later!” We can make a BIG array and use part of it e.g. up to 150 people in a class use only as many spaces as actual students
Unmarked Assignments? Variable tracks # of assignments graded update it after entering all students’ grades method averages only graded assignments aveGrade = stu.getAverage(); Student NUM_ASGN gradedAsgns 8 2 stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 78.0 aveGrade
Averaging Marked Assignments Upper bound of the summing loop is the number of graded assignments instead of NUM_ASGN public double getAverage() { int sum = 0; for (int i = 0; i < gradedAsgns; ++i) { sum += asgnGrades[i]; } if (gradedAsgns == 0) { return 0.0; } // don’t / by 0 else { return (double)sum / (double)gradedAsgns; } or Student.gradedAsgns or this.asgnGrades[i]
Exercise Create an array for up to 100 numbers (int) create a constant for the maximum Ask user for how many numbers they have assume they give a good # Read that many numbers into the array
asgnGrades Getter Revisited Maybe return only the part of asgnGrades that’s actually in use that is, just the graded assignments int[] myGrades = stu.getAsgnGrades(); stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 Student NUM_ASGN gradedAsgns 8 2 myGrades 81 75
Revised getAsgnGrades Return just the graded assignments public int[] getAsgnGrades() { int[] graded = new int[Student.gradedAsgns]; for (int i = 0; i < Student.gradedAsgns; ++i) { graded[i] = this.asgnGrades[i]; } return graded; it’s actually a better way to do getAsgnGrades compared to just return this.asgnGrades
Problems of Arrays as IVs Remember we make IVs private so no one else can change them But making an array private doesn’t do that! give someone our array they can change it! we’ve already seen this! let’s go back to GiftExchange… … and its removeName method
GiftExchange.removeName We give this method an array and a name… …it removes that name from the array p.s. void removeName(String[] names, String name) { for (int i = 0; i < names.length; ++i) { if (names[i].equals(name)) { names[i] = “”; } Angela Barrak Vladimir David Vladimir Look! Look! We’re changing an array someone gave us!
Arrays: Variables and Objects Two different variables can refer to the same array int[] firstVar = new int[]{1, 2, 3}; // a NEW array System.out.println(Arrays.toString(firstVar)); int[] secondVar = firstVar; // NOT a new array! secondVar[0] = 5; // same array as firstName [1, 2, 3] [5, 2, 3]
Co-Reference When two variables point to the same array Or when they point to the same object objects work the same way as arrays Variables can be in the same method Car myCar = new Car(); Car stevesCar = new Car(); Car disCar = myCar; disCar.setColor(blue); (variable) myCar (variable) stevesCar (variable) disCar
Array Co-Reference Objects (values) get passed, not variables removeName(getters, givers[i]); … p.s. void removeName(String[] names, String name) (variable) getters (variable) givers[i] (variable) names (variable) name Angela Barrak Vladimir David Vladimir
Co-Reference Problems OLD version of getAsgnGrades int[] stealGrades = stu.getAsgnGrades(); stealGrades[0] = -99; client can change grades to whatever! we’re not protecting our information stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 100 98 86 94 96 (variable) stealGrades -99 (variable)
Co-Reference Problems NEW version of getAsgnGrades int[] stealGrades = stu.getAsgnGrades(); stealGrades[0] = -99; client changes only his COPY! we’re protected! stu A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 75 100 98 86 94 96 (variable) stealGrades 81 75 100 98 86 94 96 -99 (variable)
Another Co-Reference Problem Setter changes our array to refer to one the client owns – and can modify at will! int[] stealGrades = new int[]{81,75,100,98,86,94,96,100}; stu.setAsgnGrades(stealGrades); stealGrades[0] = -99; stu (variable) stealGrades A_NUMBER name asgnGrades A00123456 “Dent, Stu” 81 -99 75 100 98 (variable) 86 94 96 100
Make Copies of Arrays To protect array contents, make a copy public void setAsgnGrades(int[] newGrades) { if (areValidGrades(newGrades)) { for (int i = 0; i < newGrades.length; ++i) { asgnGrades[i] = newGrades[i]; } stu (variable) stealGrades A_NUMBER name asgnGrades A00123456 “Dent, Stu” -99 81 75 100 98 81 75 100 98 (variable) 86 94 96 100 86 94 96 100
areValidGrades New grades must all be correct and not too many of them! private static areValidGrades(int[] grades) { if (grades.length > NUM_GRADES) { return false; } for (int i = 0; i < grades.length; ++i) { if (!isValidGrade(grades[i])) { return false; } return true; Too many grades! One grade (at least) not valid! Not too many, and all were valid And the method is static because…?
Making Copies of Arrays Copying arrays needs to be done a lot so Java provides a tool to do it Arrays.copyOf(arrayToCopy, sizeOfCopy) public int[] getAsgnGrades() { return Arrays.copyOf(asgnGrades, gradedAsgns); } public void setAsgnGrades(int[] newGrades) { if (areValidGrades(newGrades)) { asgnGrades = Arrays.copyOf(newGrades, newGrades.length);
new elements are zeroes Arrays.copyOf New array can be smaller or larger int[] original = new int[]{1, 2, 3, 4}; int[] smaller = Arrays.copyOf(original, 2); int[] larger = Arrays.copyOf(original, 8); (variable) original 1 2 3 4 (variable) smaller 1 2 (variable) larger 1 2 3 4 extra elements lopped off new elements are zeroes
Arrays of Objects Generally have many students at once lots of objects of same type treated the same an array! Arrays of objects a little bit more complicated than arrays of primitives but not much!
Creating an Array of Students Create the Student array variable and object Student[] student = new Student[MAX]; Student[] student creates the array variable new Student[MAX] creates the array object Do we now have MAX Student objects? NO! We just have that many Student variables An array is a collection of variables each variable needs to have a Student object created for it! ClassList.java
Creating an Array of Students Loop reads a name, creates a Student for (int s = 0; s < student.length; s++) { S.o.p(“Enter Student’s name: ”); String name = kbd.nextLine(); student[s] = new Student(name); } using “s” because it’s a mnemonic for “student” recall that Student constructor accepts a name, assigns a student number ClassList.java
Arrays of Objects Create the array… …then the array elements student “Alice” STUDENT_NUMBER studentName & / student A00000002 “Bill” STUDENT_NUMBER studentName & A00000003 “Carole” STUDENT_NUMBER studentName &
Printing Class List Now we have all the objects created, we can just use them as usual for (int s = 0; s < student.length; s++) { S.o.pln(student[s].getANumber() + “ ” + student[s].getName()); } student[s] is a Student getANumber() the student's # in A00000000 format getName() the student's name ClassList.java
Exercise Create an array of ten Thingamajigs, sized from 1 to 10 Note: new Thingamajig(n) creates a Thingamajig of size n Write a loop to add up the sizes of the Thingamajig in the array use the getSize() method!
Assigning Grades to a Student Client assigns grades to a student create student object Student stu = new Student(“Student, Lowell E.”); assign grades stu.setAsgnGrade(1, 95); stu.setAsgnGrade(2, 100); stu.setAsgnGrade(3, 72); … stu.setAsgnGrade(6, 90);
Reading One Student’s Grades Client can set grade for student for (a = 1; a <= Student.NUM_ASGN; a++) { System.out.print("Enter A" + a + " grade: "); int g = kbd.nextInt(); kbd.nextLine(); stu.setAsgnGrade(a, g); } loop: for each assignment prompt for and read a grade set the student’s grade for that assignment
Reading Many Students’ Grades Enter grades for each assignment for each assignment, read each student’s grade for (int a = 1; a <= Student.NUM_ASGN; a++) { System.out.println("Enter A" + a + " grades: "); for (int s = 0; s < numStu; s++) { System.out.print(student[s].getStudentName() + "> "); int g = kbd.nextInt(); kbd.nextLine(); student[s].setAsgnGrade(a, g); } GradeSheet.java
Calculating the Class Average Add up averages of all students ask each student for their average Divide by number of students int sum = 0; for (int s = 0; s < numStu; s++) { sum += student[s].getPctGrade(); } double avg = (double)sum / (double)numStu; GradeSheet.java
Exercise Suppose we have an array of professors and we want to find their average salary array named professors numProfs professors in the array getSalary method returns a prof’s salary Write the code
Big Objects and Little Objects We have an array of Students Student[] student = new Student[MAX]; Each element of the array is a Student Student stu = student[0]; Each Student object has an array of grades int[] myGrades = student[me].getAsgnGrades(); Each grade is an int value int myA1Grade = student[me].getGrade(1); // better way! or myA1Grade = student[me].getAsgnGrades()[0];
Composition Joining objects together in bigger objects Student has two Strings and an int[] NOTE: has, not is Can build objects as big as we need them Section has a Prof and a Student[] Course has a Section[] and a Course[] (!) the Course[] is the list of prerequisites! Department has a Prof[] and a Course[] University has …
Exercise Get the first letter of the name of the first student in the first section of the first course in the first department in the university myUniversity, getDepartments(), getCourses(), getSections(), getStudents(), getName(), charAt(#) University has a Department[] and other stuff… Department has a Prof[] and a Course[] Course has a Section[] and a Course[] Section has a Prof and a Student[]
Questions Next Time Arrays are nice ArrayLists are nicer!