Download presentation
Presentation is loading. Please wait.
Published byMilo Robinson Modified over 7 years ago
1
Feedback from exercises Arrays Nested loops & 2D arrays
Tirgul 5 Feedback from exercises Arrays Nested loops & 2D arrays
2
Common mistakes in ex3 Not defining String/repeating Strings as consts
many people wrote a method to get the parameter input from the user, but within it - repeated the input procedure 3 times (copy-paste), instead of creating a single method that prints a message, reads and verifies the input (and call it 3 times with a different message). private int getInput(String msg, int minLegalValue, int maxLegalValue)
3
Ex4
4
Arrays – basic use
5
Initializing Arrays At Creation Time
int[] numbers={5,15,5,6,5}; boolean[] bits= {true,false,true}; String[] words = {“hi”,”bye”); Position[] positions = {new Position(1,2),new Position()};
6
Working with the Command Line
Congratulations! We can finally understand the entire signature of the main function.
7
Command Line Arguments
The main method takes a String[] as a parameter. public static void main(String[] args) The contents come from the command line that called the program: java HelloCommandLine how are you 1 2 “how” “are” “you” args
8
Example: public class HelloCommandLine {
public static void main(String[] args){ System.out.println("There are " + args.length + “ arguments"); System.out.println("They are:"); for(int i=0; i<args.length; i++){ System.out.println(args[i]); }
9
Redirecting the Input and Output of Programs
The following saves the output of the program to the file out.txt (instead of printing it): java MyClass arg1 arg2 >out.txt To use input from a file (not from keyboard): java MyClass arg1 arg2 <input.txt Or we can combine: java MyClass arg1 arg2 <input.txt >out.txt These are all very useful features of the shell and work on any command (not just Java).
10
One more helpful shell command
If you are working on CSE computers from outside and would like to transfer a file to yourself maybe the easiest way is to use mutt mutt < -address> -a <file> < /dev/null For example: mutt –a ex4.jar < /dev/null
11
Common Array Errors: public class Test {
public static void main(String[] args) { String[] words; int num = words.length; //no array there yet! words[0]="hi"; words = new String[15]; num = words[0].length(); //no object there yet! words[15]="Hello"; //out of bounds! } Won’t compile crashes the program Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:7) Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15 at Test.main(Test.java:8)
12
Arrays of length 0 It is legal to create an array of length 0.
char[] letters = new char[0]; int num = letters.length; //okay. char letter = letters[0]; //out of bounds! Notice the difference from these lines of code: char[] letters = null; //Allowed. int num = letters.length; //null pointer exc. char letter = letters[0]; //null pointer exc.
13
clone() The “method” clone() creates a copy of the array and returns it: int[] nums1 = new int[5]; // …put numbers into the array… int[] nums2 = nums1; int[] nums3 = nums1.clone(); 1 -2 8 nums1 nums2 1 -2 8 nums3
14
Call by Reference vs. Call by Value – Test Yourselves
In function calls, technically, arguments are always passed by-value (copied into a local variable in the function) When complex objects are passed, we get the effect of call by-reference (the local variable is an alias of the original one) The actual reference value is passed by value. The function gets direct access to the original object in the memory, and can influence it.
15
Call by Reference vs. Call by Value – Test Yourselves
We want to swap the values of two variabls using a method: public staic void main(Sting[] args){ int a = 5, b = 10; swapX(a,b); System.out.println(“a=“+a+” b=“+b);l }
16
Call by Reference vs. Call by Value – Test Yourselves
public void swap0(int a, int b){ int temp = a; a = b; b = temp; } Useless public void swap1(int[] a, int[] b){ int[] temp =a; a = b; b = temp; } Useless Which of these is useless?
17
Call by Reference vs. Call by Value – Test Yourselves
We want to swap the values of two variabls using a method: public staic void main(Sting[] args){ int[] a = {5}, b = {10}; swapX(a,b); System.out.println(“a=“+a+” b=“+b);l }
18
Call by Reference vs. Call by Value – Test Yourselves
public void swap2(int[] a, int[] b){ int[] temp =a.clone(); a = b.clone(); b = temp; } Useless public void swap3(int[] a, int[] b){ for(int i=0; i<a.length; i++){ int temp = a[i]; a[i] = b[i]; b[i] = temp; } Useful Which of these is useless?
19
Call by Reference vs. Call by Value – Test Yourselves
Remember that the reference is copied into a local variable in the function (object aliasing). In the useless examples the value of the local reference variables is changed (changing what a,b, temp point to). This doesn’t influence the original object in the memory, or the original reference to it. The useful example changes the values of the object’s properties (the array’s cells).
20
Examples of arrays in action
21
Random Shuffle public static void main(String[] args){
final int NUMBERS = 10; int[] numbers = new int[NUMBERS]; for(int i=0; i<numbers.length; i++){ numbers[i] = i; } shuffle(numbers); System.out.print(numbers[i] + " "); System.out.println(); Load up the array with numbers. Randomly shuffle the array Print the results
22
How do we shuffle? First, we randomly select the element that will appear last in the array, and swap it into place. Then, we’ll select the 2nd to last element, and swap it into place. Etc. We use java.util.Random – an object that selects random numbers.
23
Need to import java.util.Random;
Random Shuffle Need to import java.util.Random; private static void shuffle(int[] numbers) { Random rand = new Random(System.currentTimeMillis()); for(int i=numbers.length-1; i>=1; i--){ swap(numbers, i, rand.nextInt(i+1)); } private static void swap(int[] numbers, int i, int j){ int temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; This will change the array in the calling method since we are working through references!
24
Nested Loops & 2D Arrays
25
Powers Table We would like to calculate the non-negative powers of the positive integers Notice that there’s a difference between positives and non-negatives Positives integers are 1,2,3, … Non-negatives are 0,1,2,3,… Calculating the powers of a single integer is easy, as demonstrated in 2 more slides We are not going to use Math.pow()
26
PowersPrinter Ctor //this class a prints powers table for numbers 1-highestNumber and powers 0-highestPower public class PowersPrinter { //consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //members private int highestNumber; private int highestPower; //ctor public PowersPrinter(int highestNumber, int highestPower) { //sets highestNumber if (highestNumber <= 0) { System.err.println("highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber; } //sets highestPower if (highestPower < 0) { System.err.println("highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; else { this.highestPower = highestPower; } Default highest number, power to which the table is generated Highest number, power to which the table is generated
27
PowersPrinter – Table & Rows
Prints a full powers table in a top-down design style. The table consists of single rows //prints a full table public void printTable() { //prints table rows in a loop for (int i = 1; i <= highestNumber; i++) { printRow(i); } //prints a single row public void printRow(int rowNumber) { //prints rowNumber's powers by calling calcPower for (int j = 0; j <= highestPower; j ++) { System.out.print(calcPower(rowNumber, j) + "\t"); System.out.println(""); Prints a single row in a top-down design style. The row consists of single power elements
28
PowersPrinter – A Single Power
Notice that calcPower() is defined static since it only provides an “external” calculation and does not interact with some specific instance data members private static long calcPower(int number, int power) { /* Assumptions: 1) number is positive 2) power is non-negative */ //power of 0 long result = 1; //multiply current result by number - power times for (int i = 1; i <= power; i++) { result *= number; } return result; Since calcPower() is a private method, it’s the programmer’s responsibility to provide this method the right arguments Follows the mathematical definition of the power function. long is another type, very similar to int but capable of representing larger numbers
29
PowersPrinter – Main public static void main(String[] argv) {
//verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersPrinter <highest-number>" + " <highest-power>\n"); System.exit(-1); } //get user arguments - assuming legal argument types int userHighestNumber = Integer.parseInt(argv[0]); int userHighestPower = Integer.parseInt(argv[1]); //calculates userHighestNumber ^ userHighestPower System.out.println( PowersPrinter.calcPower(userHighestNumber, userHighestPower)); … argv is a Strings array and has a length member If the user types non-integer arguments, java will throw NumberFormatException during runtime. The whole program terminates with exit code of -1 on System.exit(-1) No instance needed yet – static method call
30
PowersPrinter – Main (2)
… //create an instance of PowersPrinter PowersPrinter pp = new PowersPrinter(userHighestNumber, userHighestPower); //prints a single row int rowNumber = 2; System.out.println("\nSingle row number " + rowNumber); pp.printRow(rowNumber); //prints the full table System.out.println("\nFull table "); pp.printTable(); }
31
PowersPrinter - Analysis
Invoking “java PowersPrinter 3 4” generates the following output : How many multiplications costs the 2nd row (for example) 1 takes 0 multiplications 2 takes 1 (2 = 1 * 2) 4 takes 2 (4 = 1 * 2 * 2) 8 takes 3 (8 = 1 * 2 * 2 * 2) 81 Single row number 2 Full table Total number of multiplications needed for a row of 5 elements is : =10 !!!
32
PowersPrinter2 – A Lighter Version
This is the only method of PowersPrinter2 different from its corresponding method in PowersPrinter public void printRow(int rowNumber) { //set first number to 1 (0 power) long number = 1; //prints rowNumber's powers by multiplying number by rowNumber for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } System.out.println(""); Instead of invoking calcPower() implements the power calculation algorithm originally placed in calcPower() Now, a row of N elements takes N-1 multiplications Conclusion : Top-down design isn’t always better
33
PowersPrinter3 – Nested Loops
public void printRow(int rowNumber) { long number = 1; for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } System.out.println(""); public void printTable() { for (int i = 1; i <= highestNumber; i++) { printRow(i); } public void printTableWithNestedLoops() { //prints table rows in a loop long number; for (int i = 1; i <= highestNumber; i++) { //single row number = 1; for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= i; } System.out.println(""); We separated number declaration from its assignment since it needs to be declared only once We multiply number by i which is equivalent to printRow’s rowNumber argument
34
PowersPrinter3 – Another Look
Generally, i is a legal loop variable name. But renaming it as currentRow makes the code more readable public void printTableWithNestedLoops() { //prints table rows in a loop long number; for (int currentRow = 1; currentRow <= highestNumber; currentRow++) { //inside a specific row number = 1; for (int currentPow = 0; currentPow <= highestPower; currentPow ++) { System.out.print(number + "\t"); number *= currentRow; } System.out.println(""); Rows loop. The current row number is currentRow Actually, we could have left number’s {declaration + assignment} attached, but it’s really unnecessary (re-declaring it again and again) Powers loop. The current power number is currentPow. This power too refers to the current row currentRow
35
Nested Loops 2D Arrays What if we know, we’ll need later to check some powers (within bounds), and The most important thing is the easy / quick access to the power results We wouldn’t like to scan the whole table for the right cell Nor would we like to recalculate the results every time We are willing to “pay” in memory pre-calculate once the whole table, and store it (cache)
36
Same members & constants as in PowerPrinter
PowersTable Class public class PowersTable { //original consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //original members private int highestNumber; private int highestPower; //new const + member private static final long ILLEGAL_INDICES_ELEMENT = -1; private long[ ][ ] table; //ctor public PowersTable(int highestNumber, int highestPower) { … } Same members & constants as in PowerPrinter
37
PowersTable - Constructor
public PowersTable(int highestNumber, int highestPower) { //sets highestNumber if (highestNumber <= 0) { System.err.println("Highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber;} //sets highestPower if (highestPower < 0) { System.err.println("Highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; } else { this.highestPower = highestPower; } //allocates and fills the table createTable(); } This is the only new line
38
PowersTable – createTable
This method is intended for internal use only (it is not part of the API) There’re highestNumber numbers – [1,…, highestNumber]. There’re highestPower +1 powers – [0, …, highestPower] private void createTable(){ //allocates the table table = new long[highestNumber][highestPower + 1]; //fills the rows’ entries in a loop for (int i = 1; i <= highestNumber; i++) { fillRow(table[i-1], i); } We would like to fill the i-th row of table (which index is i-1) with the powers of the number i
39
Heap Diagram Powers’ array are allocated one after the other
3 2 1 3 2 1 4 3 2 1 Rows’ array is allocated 3 2 1 highestNumber highestPower table 5 3 3 2 1 When an object (e.g. PowersTable) is constructed, it is kept in the heap The entries of the long arrays are initialized with 0 – the default long value 3 2 1
40
PowersTable - fillRow private void fillRow(long[] row, int rowNumber) { //power of 0 long number = 1; //other powers - multiply number by rowNumber for (int j = 0; j < row.length; j ++) { row[j] = number; number *= rowNumber; } fillRow() doesn’t know and doesn’t care that the parameter row is only a single row belongs to a 2D array We could have used (highestPower + 1) instead of row.length, since there’re highestPower+1 powers in every row – [0, …, highestPower]
41
What Just Happened Here?
createTable() is about to invoke filleRow(table[1], 2) row is created as a parameter of table[i-1] according to call by value concept table is created in createTable Heap Stack (createTable) Stack (fillRow) table = 87a9f5d i = 2 row = 5a76bfc table[i-1] is sent as fillRow’s argument table[i -1] = 5a76bfc number = 1 row.length = 4 Power of 0 j = 0 number = … Loop begins 1 2 4 8 3 2 1 table[i-1] values were updated !!!
42
PowersTable – Printing A Table
public void printTableWithNestedLoops() { //prints table rows in a loop for (int currentNumber = 1; currentNumber <= highestNumber; currentNumber ++) { //single row – loops over the powers for (int currentPower=0; currentPower<=highestPower; currentPower++) { System.out.print(table[currentNumber -1][currentPower] + "\t"); } System.out.println(""); Simple internal access to table indices
43
PowersTable - calcPower
public long calcPower(int number, int power) { //verify that number is in bounds if ((number < 1) || (number > highestNumber)){ System.err.println("number out of bounds"); return ILLEGAL_INDICES_ELEMENT; } //verify that power is in bounds if ((power < 0) || (power > highestPower)) { System.err.println("power out of bounds"); return table[number - 1][power]; External access to the powers table within Row number-1 contains the powers of number
44
PowersTable - Main public static void main(String[] argv) {
//verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersTable <max-number> <max-power>\n"); System.exit(-1); } //get user arguments - assuming legal argument types int userHighestNumber = Integer.parseInt(argv[0]); int userHighestPower = Integer.parseInt(argv[1]); //create an instance of PowersTable PowersTable pp = new PowersTable(userHighestNumber, userHighestPower); //prints the full table System.out.println("\nFull table "); pp.printTableWithNestedLoops(); //prints a single power System.out.println("\nThe " + userHighestPower + "-th power of “ userHighestNumber + " is : " + pp.calcPower(userHighestNumber, userHighestPower)); PowersTable (unlike PowersPrinter) has no static methods and an instance must be constructed
45
Extra Slides
46
Static Cascade You got an API, implemented the public members / methods but then comes the hard part – thinking )-:
47
StaticCascadeBad This simple class has:
A single non-static member + getter Some non-static methods Ctor main - static import java.util.Scanner; //This class demonstrates a badly written code with a static cascade problem public class StaticCascadeBad { private String name; //instance name private static Scanner sc=new Scanner(System.in) //ctor public StaticCascadeBad(String name) {this.name = name;} //name getter public String getName() {return name;} //Does action #1. If instance name is david - should print:"david says: Action1 done" public void doAction1() { System.out.println(name + " says: Action1 done");} public void doAction2() { …} public void doAction3() { … } /* Counts from 1 to 10 .Creates a new StaticCascadeBad named by the user, prints a menu that begins with the instance name and performs on this instance an action chosen by the user.*/ public static void main (String[] argv) { countFrom1To10(); System.out.println ("What's the StaticCascadeBad name?"); StaticCascadeBad scb = new StaticCascadeBad(sc.next()); doAction(scb); } This class has a private member that affects its methods output Main code is top-down designed. Private methods need to be implemented doAction needs the instance data and therefore takes it as an argument
48
StaticCascadeBad - count
The programmer doesn’t know when to use static, so he tries without the static first main is static, countFrom1To10 is not … Code Compiler private void countFrom1To10() { for (int i = 0; i < 10; i ++) { System.out.println(i + 1); } StaticCascadeBad.java:59: non-static method countFrom1To10() cannot be referenced from a static context countFrom1To10(); Maybe the static will help? private static void countFrom1To10() { for (int i = 0; i < 10; i ++) { System.out.println(i + 1); } OK!!! Obviously that was the right choice, since this method does not interact with any non-static members or other non-static method
49
StaticCascadeBad - doAction
The programmer concluded from the last example that main can only invoke static method so this method is declared static as well private static void doAction(StaticCascadeBad instance) { //prints menu and get user chosen option int option = printMenu(instance); //performs the chosen action switch (option) { case 1: instance.doAction1(); break; case 2: instance.doAction2(); case 3: instance.doAction3(); default: System.err.println("Illegal action"); } Top-down design again… The right action is invoked on the instance argument
50
StaticCascadeBad - printMenu
The programmer doesn’t know when to use static, and this method is not invoked directly from main so he tries without the static first doAction is static, printMenu is not … Code private int printMenu(StaticCascadeBad instance) { System.out.println(instance.getName() + " says : choose an option"); System.out.println("1) bla bla"); System.out.println("2) bla bla"); System.out.println("3) bla bla"); return sc.nextInt(); } Compiler StaticCascadeBad.java:99: non-static method printMenu(StaticCascadeBad) cannot be referenced from a static context int option = printMenu(instance); Maybe the static will help? private static int printMenu(…) { … } OK!!! And one method after the other falls into the hands of the evil static (cascade)
51
The Fixed Code - StaticCascadeFixed
import java.util.Scanner*; //This class is the fixed code of StaticCascadeBad public class StaticCascadeFixed { //similar code to StaticCascadeBad … //main public static void main (String[] argv) { countFrom1To10(); System.out.println ("What's the StaticCascadeFixed name?"); StaticCascadeFixed scb = new StaticCascadeFixed(sc.next()); scb.doAction(); } doAction() became a non-static method of this class – Object Oriented Programming
52
doAction – A Comparison
It’s a non-static method that is invoked on a specific object no argument needed Original Code Fixed Code private static void doAction(StaticCascadeBad instance) { //prints menu and get user chosen option int option = printMenu(instance); //performs the chosen action switch (option) { case 1: instance.doAction1(); break; case 2: instance.doAction2(); case 3: instance.doAction3(); default: System.err.println("Illegal action"); } private void doAction() { //prints menu and get user chosen option int option = printMenu(); //performs the chosen action switch (option) { case 1: doAction1(); break; case 2: doAction2(); case 3: doAction3(); default: System.err.println("Illegal action"); } These methods are invoked on the same object that doAction() was invoked on (this). Similar code correction in printMenu() too
53
Daily Schedule Let’s create a class that represents an appointment schedule We’ll build an object that will hold the appointments for a single day (later we can have several of these objects in order to build an appointment book for the month).
54
The first hour in the day The number of appointments on that day
public class DailySchedule { private int start; private String[] schedule; private int events; public DailySchedule(int startHour, int endHour){ if(startHour > endHour){ //bad input. do our best. endHour = startHour; } schedule = new String[endHour-startHour]; start = startHour; events =0; The first hour in the day The appointments The number of appointments on that day We remember the first hour so we can translate future times to indices in the array correctly.
55
Get the event at a given hour. What if there is no event?
public boolean schedule(String event, int hour){ int index = hour-start; if(index>=schedule.length || index<0 || schedule[index]!=null){ return false; } schedule[index] = event; events++; return true; public String eventAt(int hour){ int index =hour-start; if(index<0 || index>=schedule.length ){ return null; return(schedule[index]); Add a new event at a given hour. Returns true if we could schedule the event Get the event at a given hour. What if there is no event?
56
public String clear(int hour){ int index = hour-start; if(index<schedule.length && index>=0 && schedule[index]!=null){ String event = schedule[index]; schedule[index] = null; events--; return event; } else{ return null; public int numberOfEvents(){ return events; Clears a given hour Returns the number of scheduled events. Could we do without this field? Why use it?
57
public int findEvent(String event){ for(int i=0; i<schedule
public int findEvent(String event){ for(int i=0; i<schedule.length; i++) { if(schedule[i]!=null && schedule[i].equalsIgnoreCase(event)) return i+start; } return NOT_FOUND; public String toString(){ String result = "Daily schedule:\n"; for(int i=0; i<schedule.length; i++){ if(schedule[i] != null){ result = result + (i+start) + “ : " + schedule[i]; return result; Looks for a certain event. Returns a string representation of this object.
58
Example: class MyArray
class MyArray { public static void main(String[] args) { ... } /** * Print the 2D array nicely, surrounded by lines of ### */ public static void print(int[][] ar) { ... } }
59
Class MyArray public static void main(String[] args) { int[][] b = new int[3][2]; print(b); ... }
60
Class MyArray
61
Class MyArray
62
Class MyArray public static void main(String[] args) { ... int[][] a = null; print(a); }
63
Class MyArray
64
Class MyArray public static void main(String[] args) { ... a = new int[3][]; print(a); }
65
Class MyArray
66
Class MyArray public static void main(String[] args) { ... int n = a.length; System.out.println("a has " + n + " rows"); }
67
Class MyArray
68
Class MyArray public static void main(String[] args) { ... a[0] = new int[6]; a[0][2] = 14; a[0][5] = 26; a[1] = new int[0]; print(a); }
69
Class MyArray
70
Class MyArray public static void main(String[] args) { ... a[2] = new int[3]; print(a); }
71
Class MyArray
72
Class MyArray public static void main(String[] args) { ... a[2][0] = 3; a[2][1] = 5; a[2][2] = 13; print(a); }
73
Class MyArray
74
Conclusions The whole 2D array doesn’t need to be initialized all together. A 2D array is an array of arrays. The “sub-arrays” don’t have to be of the same length. All the elements (cells) of the array have to be of the same type. If arr is of type int[][], then arr[0] is of type int[] and arr[1][3] is of type int.
75
class Calendar Remember class DailySchedule?
Lets use it to create an annual calendar.
76
class Calendar class Calendar { private DailySchedule[][] days; public Calendar(boolean meuberet) { days = new DailySchedule[12][]; // 12 months days[0] = new DailySchedule[31]; // January days[1] = new DailySchedule[meuberet ? 29 : 28]; // February days[2] = new DailySchedule[31]; // March ... }
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.