ITEC120-ibarland (incl. office hrs)—info—lectures—labs—hws
Today's lab
will have you modify a for-each loop,
as well as a while-loop using an iterator.
You may work in pairs, or individually.
We will not check off today's lab,
but its questions will be fair game for tomorrow's Chapter-6 quiz.
import java.io.File; /** * Return The sum of the length of each file immediately inside directoryName. * Doesn't recur into any sub-directories (but does include any size a directory * itself takes up, aside from its sub-contents). * @param directoryName The pathname of a directory. * @return The sum of the length of each file immediately inside directoryName. */ public static String directoryListing( String directoryName ) { // Convert the directoryName into a File object, so we can get its size etc.: final File theDirectory = new File( directoryName ); // Note that we import'd java.io.File. if (theDirectory.isDirectory()) { long fileLengthsSoFar = 0; // Accumulate the sum of all immediate file sizes. String listingSoFar = ""; for ( File f : theDirectory.listFiles() ) { // For each `f' in the directory-listing... textualListing += f.toString() + "\t\t\t" + f.length() + "\n"; listingSoFar += f.length(); // Add f's length to our sum. } return listingSoFar + "\nTotal length: " + fileLengthsSoFar + "\n"; } else { // Hmm, this file wasn't a directory; print a message to System.err. String errMsg = "immediateDirectorySize: " + directoryName + " is not the name of a directory."; System.err.println( errMsg ); return errMsg; // Is this an appropriate sentinel value? I want to return 'false', but can't! } } |
While it is simple code to have #4 call #3, there is also a performance penalty: even if you find a .java right off the bat, your code still looks at every single file in the directory. This is a drawback of the for-each loop.
Since a for-each loop seems not to be appropriate,
instead
write boolean hasJavaFiles_v2(String),
which uses a while loop and an iterator.
Hint: your while-loop will keep track a
variable “foundSoFar”.
You only want to continue your loop as long as there
are more files to consider, and you haven't yet
found any java file so far.
For comparison, also look at If you look at directoryListing_v2, which works just like directoryListing except it uses an iterator instead of a for-each loop. The one line of that function which is totally confusing to us (and which you can ignore) is a line which converts the result of theDirectory.listFile() from a collection into an Iterator:
ArrayIterator<File> it = new ArrayIterator<File>( theDirectory.listFiles() ); |
Exactly what the <…> means must wait until ITEC220; why it is a ArrayIterator yet we use it as if it were an Iterator (with methods hasNext() and next()) will wait until we cover interfaces, section 6.5.
ITEC120-ibarland (incl. office hrs)—info—lectures—labs—hws
We can pass object references as parameters, just like anything else. What actually is being passed to the function is a piece of paper which has a reference written down on it. For example, we saw Kennel.setDog(), which is passed a piece of paper, upon which is a reference to some particular Dog.
class Dog { // ...fields and other methods omitted... /** Have this and otherDog exchange their ages. * A very useful method for sitcoms and Disney movies. * @param otherDog the dog who we'll swap ages with. */ void swapAge(Dog otherDog) { // ... WRITE THIS METHOD, in a moment ... } } |
Dog yourDog = new Dog( "rex", 5); Dog myDog = new Dog( "fido", 7 ); Dog worldsBestDog = myDog; myDog.toString() (myDog == worldsBestDog) // Should be ...??? myDog.ageOneYear(); // myDog is still the same dog, just older. yourDog.swapAge( myDog ); // myDog is still the same dog, just younger. myDog.toString() (myDog == worldsBestDog) // Should be ...??? |
Dog badClone() { // Not an evil clone, just broken: no new Dog is made. Dog d; d = this; // Note that "new Dog()" is *not* getting created. return d; // A three-line version of "return this". } |
Dog d1 = new Dog( "lassie", 3); Dog d2 = d1.badClone(); (d1 == d2) // Should this be true, or should it be false? |
class Dog { /** * @return a new dog which looks just like this one, * but is not == to this one.. */ public Dog clone() { // ... WRITE THIS METHOD ... } } |
Dog d3 = new Dog( "lassie", 3); Dog d4 = d3.Clone(); (d3 == d4) // Should this be true, or should it be false? |
class Dog { /** * @param partner the dog who is breeding with this. * @return a new puppy dog, whose age is 0 and whose name is a blend * of this's and partner's names. * For example: * (new Dog("rex",4)).breed( new Dog("fifi", 6) ) = new Dog( "refi", 0 ); */ public Dog breed( Dog partner ) { // ... WRITE THIS METHOD ... } } |
1If you prefer, you can count files with some other criterion — e.g. those files whose size is more than 1000000 (1MB). back
2 Btw, note that some people feel there are good reasons to avoid implementing clone, due to the danger of an object and its clone sharing state. For instance, if we clone a Kennel, should that cloned Kennel contain identically the same Dogs as the original? Or, will the cloned Kennel contain clones of those Dogs? It's highly problem-specific, as to what the correct answer should be. back
ITEC120-ibarland (incl. office hrs)—info—lectures—labs—hws
©2006, Ian Barland, Radford University Last modified 2006.Nov.10 (Fri) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |