Programming for Geographical Information Analysis: Core Skills Lecture 3: Program Flow I Loops and Branches
Mar 15, 2016
Programming for Geographical Information Analysis:
Core Skills
Lecture 3: Program Flow ILoops and Branches
Last lecture looked at classes, blocks, variable and objects.
public class Numbers {public static void main (String args[]) {
int number = 10;System.out.println(number);
int[] numbers = new int[2];numbers[0] = 123;numbers[1] = 321;System.out.println(numbers[0]);
}}
Review
public class GIS{public static void main (String args[]) {Point point1 = new Point();
System.out.println(point1.x);}
}
public class Point {double x = 100.0;
}
Review
Code structureWe have seen that you can structure code through classes, linking them by object instantiation.However, the code still reads like a shopping list of commands to do one after another.This is inflexible, and also results in very long code.We need some way of:
Repeating useful code without copying it out again.Branching our code based on processing and user decisions.Separating off useful code into the classes that contain the data the code acts on.Responding to user interactions.
This lecture:LoopingLooping with arraysBranching[Coding style]
Flow control
Flow control
Future parts will look at:Separating code into procedures.
And then, a bit later in the course:Responding to user events.
LoopsLet’s imagine we wanted to run a piece of code until some condition was true. To do this, we can use the while construction. For example,
int i = 0;while (i < 3) {
i++;}
Remember “i++” increments i by one, and is the same as i = i + 1;
How does i change as this code runs?
LoopsLet’s throw in some printlns to see how i changes (always useful):
int i = 0;while (i < 3) {System.out.println(i);i++;}System.out.println("Finished");
The code in the block is repeated all the time a is less than 3, so prints “0”, “1”, “2”.The code then continues with the next line and prints “finished”.Note that at this point, i is 3.
Conditions and comparisons
The “(i < 3)” bit is known as the condition.The loop runs all the time it is true.
Along with the mathematical operators, there are also comparison operators:
> : greater than>= : greater than or equal to< : less than<= : less than or equal to
== : equal to (used because “=“ is for assigning variables)
!= : not equal to
Comparing Strings
Because Strings are objects, you can’t do this:String a = “hi”;String b = “hi”;while (a == b) {Because the answer is, no, they’re not the same object. There’s a special way of comparing Strings, which is:while (a.equals(b)) {while (a.equals(“hi”)) {this compares the value of the text in the String.
Boolean operators
There are also Boolean operators, used for putting several conditions together:
& : Boolean AND&& : Shortcut Boolean AND| : Boolean OR|| : Shortcut Boolean OR! : Not
Note that if you are going to use multiple conditions, each condition, and the overall condition need to be in parentheses:
while ( (a != b) & (b > 10) ) {
Exampleswhile ((a != b) & (b > 10)) {
Means do this while it is true that a is not equal to b, AND b is greater than 10.
while ((a != b) | (b > 10)) {Means do this while it is true that a is not equal to b, OR b is greater than 10.
while (booleanVariable == true){while (booleanVariable){
Means do it while a boolean variable is true.while (booleanVariable == false) {while (!booleanVariable)
Means do it while it is true that a boolean variable is false.
ShortcutsThe checking of conditions is quite complicated, and takes the computer a relatively long time, so we want to minimise checking. The shortcut operators don’t bother to assess the second condition, if the first is unfavourable, for example, in:
while ((a != b) && (b > 10)){the “(b > 10)” isn’t assessed if “(a != b)” is untrue, because there isn’t any point – the overall condition is false.
Equally, in:while ((a != b) || (b > 10)){
the “(b > 10)” isn’t assessed if “(a != b)” is true, because there isn’t any point – the overall condition is true.
While-loops continued
With:while (i < 3) {
i++;}
The “i++” only happens if the condition is true. If you want the while loop to run once whether it is true or not, use:
do {i++;
} while (i < 3) ;
Counting loopsThis code is works ok:
int i = 0;while (i < 3) {
i++;}
but as a coder it is a bit issue-prone. The variable declaration for “i”, the condition, and the incrementing of “i” are all in different places. There are various problems with this, not least that the scope of “i” is larger than it needs to be, and that, with cutting and pasting, all kinds of problems could creep in.While-loops are good for some things (like looping until you find a file) but bad for counting.
For-loops
There is a special construction for counting, which is much cleaner:for (int i = 0; i < 3; i++) {
System.out.println(i);}System.out.println("Finished");
Here we see all the familiar parts: the variable declaration, the condition, and the increment, but all are in the same place, and the scope of i is just the loop block.Again, this prints “0”, “1”, “2”, but at the end, i is destroyed, rather than hanging around causing potential problems.
Variations
There is nothing to stop you dropping, one, two, or all of the parts of the for-loop, as long as you have the semi-colons; so this loops forever:
for ( ; ; ) {System.out.println(“All work and no play makes Jack a dull boy.”);
}
Hint: to get out of infinitely looping or unresponsive (“hung”) programs at the command prompt, push the CTRL and C key together.
Variations
Note also, that the increment can be replaced with expanded maths, so:
for (int i = 0; i < 3; i = i + 1) {Or any other kind of maths to do each loop. The increment doesn’t have to be plus one.
for (int i = 0; i < 3; i = i + 2) {for (int i = 3; i > 0; i--) {
What do you think “i--” does?
For-each
Introduced in Java 1.5.Allows iteration through variable collections.int[] arr = {10,50,30};for (int a: arr) {
System.out.println(a);}Will print “10”, “50”, “30”.
Assignment to variablesRemember, however, that primitives are copied, while objects are linked to, so:int arr = {10,50,30};for (int a: arr) {
a = 2;}won’t change the data in the array, whereas:Point arr =
{new Point(),new Point(),new Point()};for (Point a: arr) {
a.x = 2;}will change the Points, as “a” is a link to them.
More about loopsWith all loops, if there is just one statement to do, you can forget the brackets, e.g.
for (int i = 0; i < intArray.length; i++) System.out.println(i);
do System.out.println(i++); while (i < 10);
Don’t. Always put in brackets. That way, if you decide to put more in the loops, the brackets are there already.
Infact, generally, with all blocks, put in both the brackets before you write any code in them.
Evil control statements
gotoDarkness encoded, goto is Satan’s only friend in this realm
of joy and light.
break (end loop) and continue (go to beginning line).
Used to end blocks and temporarily skip loops respectively.Not as bad as goto was, but still to be used very sparingly.
When to use break and continue
Use only when you need to escape a loop in the middle of something that would be very complex to write avoiding it.
while (file == wrongFile) {// code to get a file;// if we find the right file,
continue;// code to destroy file for space}
Review
for (int i = 0; i < 3; i++) {System.out.println(i);
}
while (i < 3) {i++;
}
Looping
Looping with arraysBranching[Coding style]
Flow control
Using arraysWhen we looked at arrays, we saw that you need to assign them a value, like other variables:array1D[0] = 10.0;And to use them you need to get the data from them, thus:System.out.println(array1D[0]);
Ok, so having a single name saves us from thinking up new names, but this still seem pretty intensive work if we have to type a line for each array position. What if we have 10000?
One key idea will make our lives easier:Instead of hardwiring in our position number, why not use the index from a loop to go through all the positions?
Looping through arrays
Here’s the trick with a simple assignment and request from the array:
int array1D[] = new int[100];for (int i = 0; i < array1D.length; i++) {
array1D[i] = 10;System.out.println(array1D[i]);
}
Note the clever use of array1D.length, which is never reached (and quite right too – remember that numbering of positions starts at zero).
Assignment
Obviously we might want more complex assignments, including things like:
array1D[i] = 10 * i;array1D[i] = // some code to read data
I cannot express how wonderful this simple slight of hand is. You’ll soon take it so for granted that you’ll barely notice it, so take some time now to appreciate how clever this really is.
Enlarging arraysArrays are fixed in size. To enlarge or shrink them, copy them into a larger or smaller array, adding/removing a space where needed.
// using some pre-existing array: arrayA.
int[] arrayB = new int[arrayA.length + 1];for (int i = 0; i < arrayA.length; i++) {
arrayB[i] = arrayA[i];}arrayA = null; arrayB[arrayB.length – 1] = 10;
Note that we use the same index value to loop through both arrays.Removing a space is more complex. Can you work out how to do it?
Looping
But what about multi-dimensional arrays?
In geography, where data is often in 2D arrays, this is common. We’d like some way of going to each row and then travelling across it to each space in a row.
Well, this is even cleverer. For 2D arrays, we nest two for-loops.
Allows us to run across each cell in a series of rows.
First, let’s look at it without arrays.
Nesting loopsfor (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {System.out.println (i + " " + j);}
}Remember, that variables are destroyed as the processing leaves their scope, and re-made if the code runs again. 1)The outer loop starts, then the inner loop starts.2)When the inner loop has run once, it returns to the start of the inner loop, not the outer loop.3)It keeps doing this until run to completion (j == 3; i still zero).What do you think happens to j then, and where does the code go next?
Nesting loopsfor (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {System.out.println (i + " " + j);
}}
4) j is destroyed, and the outer loop increments to i = 1.5) The inner loop runs again, j recreated as j = 0.6) The inner loop runs to completion.Thus, each time the outer loop runs once, the inner loop runs to completion.7) This is repeated until the outer loop completes.8) The code then moves on.
Nested loopsLet’s look at i and j:i j0 00 10 21 01 11 2
This is exactly what we need for moving down a row at a time in our array (i) and then running across each row a space at a time (j).
2D arraysint array2D [][] = new int[2][3];
for (int i = 0; i < array2D.length; i++) {for (int j = 0; j < array2D[i].length; j++) {
array2D[i][j] = 10;System.out.println (array2D[i][j]);
}}
Note that i is in scope in the inner block, so we can use array2D[i].length to cope with irregular arrays.
2D issuesThis is surely one of the neatest algorithms ever!However, it is easy to make mistakes. There are three problems with the below. Can you spot them?
int array2D [][] = new int[2][3];
for (int i = 0; i < array2D.length; i++) {for (int j = 0; j < array2D[j].length; i++) {
array2D[i][j] = 10;System.out.println (array2D[j][i]);
}}
2D issuesThe three mistakes are classics that everyone makes, even experienced coders:
int array2D [][] = new int[2][3];for (int i = 0; i < array2D.length; i++) {
for (int j = 0; j < array2D[j].length; i++) {array2D[i][j] = 10;System.out.println (array2D[j][i]);
}}
1)array2D[j].length Looping through to the wrong dimension length. This is very common if the lengths are hard-wired in, so avoid that.
2D issuesint array2D [][] = new int[2][3];for (int i = 0; i < array2D.length; i++) {
for (int j = 0; j < array2D[j].length; i++) {array2D[i][j] = 10;System.out.println (array2D[j][i]);
}}
2)i++ Cutting and pasting your outer loop to make your inner loop, and forgetting to change part of the variable use; here, the inner increment should be to j.
2D issuesint array2D [][] = new int[2][3];for (int i = 0; i < array2D.length; i++) {
for (int j = 0; j < array2D[j].length; i++) {array2D[i][j] = 10;System.out.println (array2D[j][i]);
}}3)System.out.println (array2D[j][i]) Switching the indices the wrong way round. This should be array2D[i][j]. With an non-square array, this will result in trying to read off one side of the array and the program will break. Worse, with a square array, your data will silently be transposed. If you get confused, run through your algorithm by hand on paper, using a 2 by 3 non-square array.
Looping through 2D arraysSo, here’s our standard code for looping through a raster image or other dataset:
for (int i = 0; i < array2D.length; i++) {for (int j = 0; j < array2D[i].length; j++) {
System.out.println(array2D[i][j]);}
}j
i
VariationsLooping through the same positions in two arrays:
for (int i = 0; i < arrayA.length; i++) {for (int j = 0; j < arrayA[i].length; j++) {
arrayB[i][j] = arrayA[i][j];}
}j
i
arrayA
arrayB
VariationsLooping through two arrays at positions relative to one array (note boundary problem):
for (int i = 1; i < arrayA.length - 1; i++) { for (int j = 1; j < arrayA[i].length - 1; j++) {
arrayB[i][j]= arrayA[i-1][j-1]; }}
j
iarrayA
arrayB
Boundary problemsVarious solutions.Depends on problem context.
Wrap boundaries:Suitable for modelling
abstract landscapes
Only process as many cells as you can:Suitable for modelling non-abstract landscapes
Only process cells that can have complete processing:
Suitable for image processing
Review
Loops allow us to repeat the same code, with two important results:
1) we make less mistakes in our code;2) we can get arduous jobs, like processing arrays, done
easily.
Looping
Looping with arrays
Branching[Coding style]
Flow control
Branching
Processing can rarely be done by a single list of instructions.
We usually need to have different sets of code running, depending on conditions or user interaction.
For this, we need to branch our code down one or more execution paths.
Branching: ifThe simplest form is the if-statement:
if (some condition) {
do something;
}
For example:if (earthRadius == 6378) {
System.out.print("radius correct");}
Block only done if the whole condition is true.Note that if there’s only one line, it can be written without
brackets, but avoid this.
if… else…
The if-else statement lets us branch down two mutually exclusive routes:
if (condition) {do something;} else {do something else;}
if (earthRadius == 6378) {System.out.println("radius correct");} else {earthRadius = 6378;System.out.println("radius corrected");}
Ternary kung fu
The ?: Ternary operator A replacement for the if / else statement in assignment.The most nifty move you can pull. Use it and other coders will
give you a knowing nod in the street. You will be the Jackie Chan Kung Fu King/Queen of Code.
How do I pull this amazing move?
variable = condition?expression1:expression2;
If the condition is true, expression1 is used, otherwise expression2 is used.
Ternary example
name = (fileFound==true)?(filename):(defaultName); …is the same as…
if (fileFound==true) { name = filename;
} else { name = defaultName;
}
Why use it?Because we can… just because we can.
The if / else / if ladderFor more complex statements with multiple choices.
if (condition) statement or {statements;}
else if (condition) statement or {statements;}
else if (condition) statement or {statements;}
elsestatement or {statements;}
You need to put the elements with the most chance of being true at the top, otherwise it is very inefficient.
The switch statementswitch (variable) {
case value1:statements1;break;
case value2:statements2;break;
case value3:statements3;break;
default:statements4;
}
Slightly slower, but not as slow as a bad if-else-if ladder.
The break's are optional, if you leave one out, the computer will just run on into the next values case statements.
int day = 2;
switch (day) { case 1: System.out.println("Saturday");
break; case 2: System.out.println("Sunday");
break; default: System.out.println("Meh, whatever");}
Note that unlike the ‘if / else if / else’ ladder the conditions generally have to be fixed; they can’t be variables (this changed with Java 7, but many people have JRE 6).
Review
if (some condition) { do something;
} else {do something else;
}
LoopingLooping with arrays
Branching
[Coding style]
Flow control
Why
We think of coding as all about the computer, but it is really all about the people: users (first) but also developers.
For the users, we want code that runs fast and in an obvious manner (we’ll come back to the latter when we look at user interfaces).
For developers, we want code that is easy to understand and reuse, otherwise our code will die off.
For Users: Efficiency
Trying to speed up the program.
Knowing how the JVM and compiler work and making sure you program in the way that will make it fastest.
For example, using switch rather than if / else / if ladders, as switches only need one decision to be made.
Hard to learn because it relies on understanding how computers work.
We’ll point out examples, and the book list has some good sources.
For developers
We want code that other people can pick up and understand, just incase we spontaneously combust.
As it happens, this is also good for us. Your own code can seem like a stranger’s work in two weeks’ time.
This comes down to clarity and comments.
Other coders also have an appreciation of the art involved in programming, so you should aspire to elegance in your code – it will also usually help with clarity and efficiency.
Clarity
You could write all your code on one line:
public class HelloWorld{public static void main(String args[])char H=“H”;char e=“e”; char l=“l”; char o=“o”;{System.out.println(H+e+l+l+o+” W“+o+”r”+l+”d”);}}
It would run, but would make very little sense to you or anyone else.
Instead, because spaces don’t matter, we can make it look clearer, and we try to simplify the how it does stuff...
public class HelloWorld {
public static void main (String args[]) {
System.out.println(“Hello World”);
}
}
Note the amount of space and the tabbing as we enter blocks.
Comments
We also put in comments in our code like this: // This is a comment.
Using // at the start of the line. Such comments help when we come back to the code later.
Don’t leave it until the end to tab and comment – it is useful to do it as you go along, trust me – even if it takes a bit of time.
Conventions
Coders also stick to certain conventions, like capitals for classes, and lower class for variables/objects. This means you’re always thinking about what you are using, and others can understand the code.
Most coders work in teams, but even if you don’t, you need to get used to pretending you do – it will help your code.
Java code conventions online at…http://www.oracle.com/technetwork/java/codeconvtoc-136057.html
Elegance
It’s a piece of pi to write code that works, but runs badly and is impossible to understand.
Programmers therefore have a notion of ‘elegance’ – doing something in the simplest, clearest manner.
O Poesy! for thee I hold my pen//That am not yet a glorious denizen//Of thy wide heaven—Should I rather kneel//Upon some mountain-top until I feel//A glowing splendour round about me hung,//And echo back the voice of thine own tongue?//O Poesy! for thee I grasp my pen//That am not yet a glorious denizen//Of thy wide heaven; yet, to my ardent prayer,//Yield from thy sanctuary some clear air,//Smoothed for intoxication by the breath//Of flowering bays, that I may die a death//Of luxury, and my young spirit follow//The morning sun-beams to the great Apollo//Like a fresh sacrifice; or, if I can bear//The o’erwhelming sweets, ’twill bring me to the fair//Visions of all places: a bowery nook
John Keats (1795-1821)
Mad with poetry I stride like Chikusaiinto the wind.
Matsuo Basho (1644 ~ 1694)
Course text
Elegance is having the right solution for the job.
Review
Always tab appropriately and break up your code with blank lines.Comment your code extensively.Always stick to coding conventions and name your variables sensibly.Keep your eyes open for efficiency hints.Keep reading other people’s code: you never stop learning to program, and you can learn a lot from seeing how other people tackle problems.
Practical
Filling our array with loops.
Flow control II: Methods
Next lecture