Showing posts with label for. Show all posts
Showing posts with label for. Show all posts

Sunday, November 15, 2015

There's a loop for each of us

This is one of the really useful additions to the Java language specifications.  It greatly simplifies many loop structures, eliminating a bunch of verbiage that we long thought was just part of the deal when writing code.

Let's meet what I hope will become a good friend of yours:  The enhanced for, also known as the 'for each' loop.

The for each loop structure is an enhancement that can be used to replace many of the standard for or while loops you would otherwise be writing.  It is extremely common to have to, for instance, go over the elements of an array or a collection, extract one element at a time, and perform operations on it.  Let's pretend that we have an ArrayList of Person objects, and we want to print a list of first and last names.

In the old days we might have written this (and if you don't understand why I use 'List' instead of 'ArrayList' see 'Good Practices: Coding to the Interface'):

public static void printPersonList1(List personList) {
    System.out.println("Using a 'while' loop the JDK 1.4 (and earlier) way:");
    Iterator iter = personList.iterator();
    while(iter.hasNext()) {
        Person p = (Person) iter.next();
        System.out.println(p.getFirstName() + " " + p.getLastName());
    }
}

Now, one improvement was the addition of 'Generics', which allowed us to simplify the code a bit by informing the compiler that our List and Iterator had to be of type Person:

public static void printPersonList2(List personList) {
    System.out.println("Using a 'while' loop with generics:");
    Iterator <Person> iter = personList.iterator();
    while(iter.hasNext()) {
        Person p = iter.next();
        System.out.println(p.getFirstName() + " " + p.getLastName());
    }
}

Now, you might be wondering why I did my demonstrations of old style code with while loops to demonstrate a better for loop.  This is mostly because the while loop syntax is better suited to running over an Iterator than an old style for loop was.  It could be done, but frankly it's not as clean.  You'll note I had to leave out the third term of the for loop because it only gets executed after the body of the loop is complete and I had to pre-seed with the first value:

public static void printPersonList3(List<Person> personList) {
    System.out.println("Using a 'for' loop with generics:");
    Person p = null;
    for(Iterator <Person> iter = personList.iterator(); iter.hasNext(); ) {
        p = iter.next();
        System.out.println(p.getFirstName() + " " + p.getLastName());
    }
}


Alternately, we could have skipped the Iterator altogether, which is really more in keeping with the natural usage of the old style for loop:

public static void printPersonList4(List<Person> personList) {
    System.out.println("Using a 'for' loop with no iterator:");
    Person p = null;
    for(int i = 0; i < personList.size(); i++) {
        p = personList.get(i);
        System.out.println(p.getFirstName() + " " + p.getLastName());
    }
}


OK, here's the actual example I'm trying to get across to you.  This is the 'enhanced for' loop, also knows as the 'for each':

But the for each loop construct went a lot further and made things much better:

public static void printPersonList5(List<Person> personList) {
    System.out.println("Using a 'for each' loop:");
    for(Person p:personList) {
        System.out.println(p.getFirstName() + " " + p.getLastName());
    }
}

Note how concise it is, with no extra stuff.  Get Person objects from this collection and run with it.  Using the enhanced for loop simplifies our code, letting us get on with the conceptual task at hand and saving our fingers from some typing.  It's extremely common to go over a collection of data and perform some task on every element, so why should we have to write it all out explicitly every time?  You can use for each loops on classes based on Collection and on arrays equally well, which means we're more likely to use it and get the code right the first time.

private static void printStringArray(String[] aList) {
    System.out.println("The enhanced for can also work on array types:");
    for(String s: aList) {
        System.out.println(s);
    }
    System.out.println();
}

It actually took me a while to get used to using this loop structure, because I spent so much time supporting code that had to run in 1.4 level JREs.  In order to ensure the best compatibility I was also compiling with a 1.4 JDK so I didn't have access to this feature.  I'll tell you what, I was really missing out.  My fingers are probably a couple of millimeters shorter than they should be because of all the wear and tear from the extra typing I did.  I for one am glad we have this loop available, and you probably should be, too.

View Code


Friday, November 21, 2014

Collections Part 1: List

Let's talk about Collections.  I don't mean baseball cards...  or dust.  I'm talking about the Collections framework, which is a powerful set of classes included with your Java distribution.

This is not meant to be an in depth tutorial.  I'm merely going to scratch the surface and give a few guidelines regarding basic use of the framework.

The Collections framework is incredibly important to the Java developer.  You will spend a great deal of time working with the data structures within it.  The two that you will most likely use more than any other are List and Map.

List and Map are not classes.  They are interfaces.  An interface can be thought of as the set of controls for a range of classes.  Much like you might have a gas powered or electric powered oven, you still turn a dial and set a desired temperature.  The interface is the same, although the implementation is different.  This is a key concept:  Code to the Interface is commonly said, and slightly less commonly actually done.  I will do other posts on this idea, it's very important.

Let's start with List.  We'll do Map in another post.

Suppose I wanted to keep track of a few numbers read in from a file.  Each line contains one number, but I don't know how big the file is.  While it would be possible to load the numbers into an array, it would be a bit messy, as I would have to manage the size of the array.  Enter the 'ArrayList'.  This is a Collections based object that works very much like an Array with a turbocharger on it.  I don't have any hard numbers on this, but my suspicion is that it is the most commonly used Collections class out there.

Let's say my pseudocode looks something like this:

Open a file

For each line in the file:

    Read an integer number from the file
    Store the integer in a list for later use

Generate a sum of all the integers in the list as SumTotal
Display SUM to the user

There are multiple paths to success of course, and it's hard to say that any given solution is exactly 'wrong'.  However, unless we know in advance how many values we're going to store, or we wildly oversize the initial allocation, using an array would require us to modify the length of the array regularly.  It's not that this is particularly hard, but it's even easier not to do it.

And let's face it:  One of the secrets of successful programming is doing things the easy way.  It's a hard enough job, there's no reason to add unnecessary bells, whistles and epicycles to our code.

I'm not going to address the bits about reading the file right now, that will be in another post.  I just want to concentrate on 'Store the integer in a list for later use' and 'Generate a sum of all the integers in the list as SumTotal'.

First, we have to create the ArrayList object.  I'm going to do so in a way I haven't shown you before, but it's not too awful to understand:

List<Integer> numberList = new ArrayList<Integer>();

What?

Well, honestly Java can deal with this without having those '<Integer>' parts, but I thought you ought to get used to using them.  They're really handy for preventing certain classes of errors when programs get bigger.

What this is doing is creating a variable called 'numberList'.  It is an object of type 'List', and that 'List' is constrained to hold only Integer values.  That's the reason for the syntax, it makes sure we don't do something silly like try to put a String or a PersonData in there.

List is NOT a class.  You cannot create a 'new List()' directly.  It is what's known as an interface, and essentially describes how to use a category of classes, rather than one single class.

ArrayList IS a class.  You could do this if you so choose:

ArrayList<Integer> sillyNumberList = new ArrayList<Integer>();

This is roughly akin to adding the name of the manufacturer before mentioning an appliance.  Every time.  You wouldn't tell someone to go get you a beer from the Acme refrigerator, you'd just say refrigerator.  The fact that it's an Acme was only important when you bought it (or when you need to have it repaired.  Don't ask me about refrigerator repair, it's a sore spot).  The fact that it's a refrigerator means that you will grab a handle, pull it, and find something yummy and cold inside.  The specific manufacturer does not matter.  Similarly, a List allows you to add items, remove items, look at items and such, all without having to know that it is specifically an ArrayList.

Let's imagine that we've now got a value we want to add as an Integer, in a variable called 'numberToAddToList' (imaginative, huh?)  We'd just do this:

numberList.add(numberToAddToList);

No muss, no fuss, no checking capacity.  Set it and forget it.  You can do this once, or a thousand times or more.  That one line is all you'll need to use.

The other bit we need to work on is generating a sum of the numbers.  The way to do this, of course, is to take all the numbers, one by one, and add them to a variable that started at zero.  I'm going to do this three times here.  The first time using a for loop the way we've already done.  Next, I'll do so using an 'Iterator', which is a helper type designed to go through all the items in a Collection one by one, has been around forever, and is oftentimes a better choice than a standard for loop.  The last is using the 'enhanced' for loops that have been in the Java spec for a few years now.  None of these ways are strictly wrong, but if I was reviewing your code I'd want to see or hear a good reason for not doing it the third way.

Integer sumTotal = 0;

1)
for (int i = 0; i < numberList.size(); i++ ) {
    sumTotal = sumTotal = numberlist.get(i);
}

2)
Iterator<Integer> iter = numberList.iterator();
while(iter.hasNext()) {
    sumTotal = sumTotal + iter.next();
}

3)
for(Integer number : numberList) {
    sumTotal = sumTotal + number;
}


In all cases, we'd just then write:

System.out.println("The total is " + sumTotal);

As I think you can see, the new enhanced for loop makes life pretty easy.  You declare a variable and state where it comes from, and then just use it in the loop.

The iterator probably looks pretty awful to you, and to be fair, that's the cleaned up version available to us since we got to start using Generics.  Back before we could add that <Integer> tag it would have looked like this:
Iterator iter = numberList.Iterator();
while(iter.hasNext()) {
    sumTotal = sumTotal + (Integer)(iter.next());
}

But it was still a useful construct quite often.  Naturally in small examples like these the full impact does not show itself.

List can be used for much more than numbers of course.  Any sort of Object can be stored in a list.  You can have a List of Strings, or a List of Lists, or a List of Maps...

Next time, we'll discuss Maps, which instead of sequential access specialize in looking up specific objects based on a key value.

Tuesday, November 18, 2014

Arrays: A new dimension

Let's revisit arrays and take them quite literally to the next level.

To recap:  An array is a means for storing multiple values of the same kind.  Those kinds can be ints.  Those kinds can be Strings.  Those kinds can be...  other arrays.

The simplest way to think of this is to picture a grid.

int [] [] twoDArray = new int [3][3];

Would generate something akin to this:

012
0
1
2

Each of the empty boxes can hold an int value.

The type of twoDArray[0] is 'int []'.

To process ALL of the cells in this block you'd most likely write a nested set of for loops:

for (int i = 0; i < 3; i ++) {
    for (int j = 0; j < 3; j++ ) {
        System.out.println(i + ", " + j + ": " + twoDArray [i] [j] );
    }
}

Now the grid analogy breaks down just a bit when you make an array more complicated.  For instance, each row could have a different number of columns.  If you were building a more sophisticated application you would probably not want to hard-code the size of the arrays in your loops, but would be more likely to use:

for (int i = 0; i < twoDArray.length; i++) {
    for (int j = 0; j < twoDArray[i].length; j++) {

But the principle is the same.  

By way of example, let's make a table of five rows, where each row has one more column than the last.  We'll populate each cell with the product of the row and column indexes:

int [] [] twoDArray = new int [5][];

for (int i = 0; i < 5; i ++) {
twoDArray [i] = new int[i+1]; //NOTE THIS!  For each row we create a new row of boxes of the correct length.
for (int j = 0; j <= i; j++) {
twoDArray [i] [j] = i*j;
}
}

01234
00
101
2024
30369
40481216

To print out the contents one could simply write this:

for (int i = 0; i < twoDArray.length ; i ++) {
for (int j = 0; j < twoDArray [i].length ; j++) {
System.out.println(i + ", " + j + ": " + twoDArray [i] [j] );
}
}

Which would generate the following output:

0, 0: 0
1, 0: 0
1, 1: 1
2, 0: 0
2, 1: 2
2, 2: 4
3, 0: 0
3, 1: 3
3, 2: 6
3, 3: 9
4, 0: 0
4, 1: 4
4, 2: 8
4, 3: 12
4, 4: 16

It would certainly possible to put this into a more readable format if one wished, of course.

For instance, if you changed the code to this:

for (int i = 0; i < twoDArray.length ; i ++) {
for (int j = 0; j < twoDArray [i].length ; j++) {
System.out.print( twoDArray [i] [j] );
if (j < (twoDArray [i].length - 1)) {
System.out.print(",");
}
else {
System.out.println();
}
}
}

We've introduced something I haven't used before on this blog.  While System.out.println should be familiar, we also have System.out.print.  It's basically the same thing, but it doesn't end by creating a new line.  This gives us the option to add more text after it.  System.out.println() with no arguments just ends the current line of output.

The output from the above would therefore take the following form:

0
0,1
0,2,4
0,3,6,9
0,4,8,12,16

Which closely matches the table up above.  Naturally, if the arrays had been created in a more complex manner the output would reflect that.

This concept can be extended to three, four, or 12 dimensions if you so choose.  Mind you, it gets mighty hard to visualize past three,  Just remember that the content of an array cell can be pretty much anything, including another array.

Friday, November 14, 2014

This Should Throw You For a Loop

Hopefully you digested the information from my last post about while loops and you're feeling eager for more.  Fortunately, the rest of what you need to know about loops should come easily if you're already comfortable.

There are two other basic loop structures available to Java developers.  These are the for loop and the do/while loop.  As with the while loop, you could conceivably accomplish any looping task with either of these, but usually one or another will jump out at you as being best suited to the task at hand.

Since we've already looked at while, let's look at do/while.  We'll start with making a simple loop that duplicates the function of the first one from the while loop post:

boolean keepRunning = true;

do {
    System.out.println("I am in a loop.");
    keepRunning = false;
} while ( keepRunning );

Note that it really is the same inside the loop, only the location of the 'while', along with an added semicolon, and the addition of the word 'do' make it any different.  So why do we even have it?  The reason is that a while loop is an entry condition loop, whereas do/while is an exit condition loop.  When you reach a while loop, if the condition for which it tests is false you will never execute it at all, whereas a do loop will always execute at least once.

The difference is better illustrated if we start with 'keepRunning' set to false.

boolean keepRunning = false;

System.out.println("About to enter loop.");
while ( keepRunning ) {
    System.out.println("I am in a loop.");
}
System.out.println("Done with loop.");

Will generate the following output:
About to enter loop.
Done with loop.

Whereas:

boolean keepRunning = false;

System.out.println("About to enter loop.");
do {
    System.out.println("I am in a loop.");
} while ( keepRunning );
System.out.println("Done with loop.");

Will generate this:
About to enter loop.
I am in a loop.
Done with loop.

As with a while loop, and ignoring the possibility of multiple threads, if you ever want it to exit something needs to happen to make the exit condition evaluate to false.

That about sums up the differences between while and do/while.  Use whichever one makes the most sense based on the code you need to execute and the variables you have available to you.  You'll get a feel for it over time.  Without having done any surveys or run any metrics, I'd say that the regular while loop is used several times more often than do/while.

The other loop structure you need to know about, and perhaps the most commonly used of all, is the for loop.  It works like this:

for( starting condition ; loop conditional ; loop increment ) {
   //do something
}

Lean back and take a deep breath, it's not that bad.  To prove it, let's duplicate the code for looping five times (for is most commonly used for counting or iterating over some multiple part data structure).

First, a refresher.  In my previous post I put this up as how to use a while loop to generate five lines of output:

int runCount = 0;

while ( runCount < 5 ) {
    System.out.println("I am in a loop.");
    runCount ++;
}
This loop is an absolutely perfect candidate to use a for loop.  Here's the same thing expressed as a for:

for (int runCount = 0 ; runCount < 5 ; runCount ++ ) {
    System.out.println("I am in a loop.");
}

This is cleaner, more concise, and just plain shorter than the same loop expressed as a while.  It also illustrates some syntax differences of which you need to be aware.

First of all, note that 'runCount' is available ONLY within the loop parentheses and in the body of the loop.  Once you reach the closing bracket it goes out of scope.  This differs from the while loop and is a potential 'gotcha':

This is perfectly valid:

int runCount = 0;

while ( runCount < 5 ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 


But this is not:

for ( int runCount = 0 ; runCount < 5  ; runCount ++ ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 

You will receive a compiler error because runCount is completely unknown by the time you reach that attempt to print it out.  You could of course write it like this to get around the problem:

int runCount;

for ( runCount = 0 ; runCount < 5  ; runCount ++ ) {
...
}

System.out.println("The value of runCount is now " + runCount ); 

Note that one can pretty much mechanically translate between while and for loops.  Just move the first and third terms inside the parentheses to before the while and just before the closing curly brace.

The for loop is a natural fit for processing arrays and Collections, both of which I will be discussing soon.  You can use the value of the index variable (runCount in this case) inside the loop for all sorts of reasons, providing a counter, spitting out line numbers, whatever you need.

By convention, when you create an index variable in a for loop, and have no particular name for it, we tend to just use the letter i.  You'll see this kind of thing a lot:

for ( int i = 0 ; i < 10 ; i++ ) {
  System.out.println("Loop iteration " + i );
}

Well, to be fair, you'll see something that starts that way but actually DOES stuff a lot.

It is also possible to embed one loop inside of another.  You can't use 'i' again, so we move on to 'j' (then 'k', 'l', etc. if we want to go nuts.  Try not to go nuts).

This is an extremely basic example of that:

for ( int i = 0 ; i < 5 ; i++ ) {
    for ( int j = 0 ; j < 5 ; j++ ) {
        int product = i * j ;
        System.out.println (i + " X " + j + " = " + product );
    }
}

These few lines of code will generate 25 lines of output:

0 X 0 = 0
0 X 1 = 0
0 X 2 = 0
0 X 3 = 0
0 X 4 = 0
1 X 0 = 0
1 X 1 = 1
1 X 2 = 2
1 X 3 = 3
1 X 4 = 4
2 X 0 = 0
2 X 1 = 2
2 X 2 = 4
2 X 3 = 6
2 X 4 = 8
3 X 0 = 0
3 X 1 = 3
3 X 2 = 6
3 X 3 = 9
3 X 4 = 12
4 X 0 = 0
4 X 1 = 4
4 X 2 = 8
4 X 3 = 12
4 X 4 = 16

The various loops are critical to your understanding of software development.  Get comfortable with them, then get more comfortable with them.

As always, if you have comments or questions, please post them.  I'd love to hear from you.

View code here