Stargrasper's Java Basics Tutorial Series
FML. At least I finally found time to write another one of these things that nobody is actually using or likely even reading! It's short because I'm short on time and wanted to get this out. Ask questions.
Lesson 0.5: Arrays and Loops
Arrays ~ A Box Enclosing Smaller Boxes
Arrays are a contiguous block of memory addresses that store a grouped set of values. In English, that means that arrays can store a bunch of different things in one variable provided that all of those values are compatible. By that I mean, you have to define a type for an array and it can only contain values of that type. Fortunately, arrays don't care whether that type is a primitive or an object. Note that as of now, objects are still magic. You use square brackets to declare an array. This is actually a holdover notation from C/C++.
// Arrays can be declared as follows
type[] name = new type[size]
// For example...
int[] intArray = new int[5];
That's how you'll usually instantiate arrays. You do have to have the maximum size of the array in mind when you instantiate it. There's nothing wrong with using a variable to contain the size.
byte size = 5;
int[] intArray = new int[size];
You can also instantiate them by just handing them the set of data they will contain.
int[] intArray = { 1, 2, 3, 4, 5 };
The size is inferred from the dataset handed to it. In this case, the maximum size of the array is five.
Now, I want a value out of the array. Because there are multiple values in an array, I can't just use the name of the variable to get the value. I have to tell it which value I want by giving it the index or slot number I want.
// Grab the element from index 2 and print it to the console
System.out.println(intArray[2]);
Another trick is that arrays, like pretty much everything in programming, are zero-indexed. That is, they start counting from zero, not one. So the first entry in the array is index 0. That index 2 above is the third element.
// Grab the element from index 0 and print it to the console
System.out.println("This is the first element: " + intArray[0]");
Of course, it would suck if I couldn't modify the contents of my array. Doing that is exactly like reassigning normal variables. Just tell the array which index you want to alter.
intArray[0] = 3;
// Takes the existing value of intArray[4] and adds 4 to it
// Identical to intArray[4] = intArray[4] + 4;
intArray[4] += 4;
I can create multidimensional arrays, too. They work just like normal arrays, but I have to tell it all the indexes. Think of it as a two or three dimensional grid.
// 2d array
int[][] array = new int[10][10];
// 3d array
int[][][] array2 = new int[10][10][10];
Technically, you can create arrays of objects. This is magic. Move along. You don't need to care about his.
Object[] objects = new Object[5];
Rectangle[] rects = new Rectangle[5];
Lets say I need to keep a list of something or other and I don't know how many I need. The easiest way to handle that it to use an array with such a large maximum length that you'll never hit it.
// Five million...that ought to do...
int[] intArray = new int[5000000];
That takes up a lot of memory you aren't using, though. Wouldn't it be nice if the thing could just dynamically resize itself? Well, through the magic of objects, it can! Yes objects. You aren't supposed to understand them yet. They're magic. Just follow along...
// We're going to create a list. Specifically, an ArrayList
// When we declare one of these, we should really tell it
// the type of object that it will contain. In this example,
// Objects.
ArrayList<Object> list;
// We still instantiate with new.
// And we need to still tell it the type of objects it will
// contain. And we need to place parenthsis after that.
// It's an object thing. Just do it.
list = new ArrayList<Object>();
// To add things, we conveniently use the .add(Object) command
// It takes the thing we're adding as a parameter
list.add(new Object());
// To fetch things, we conveniently use the .get(int) command
// It takes the index of the thing we're getting as a parameter
list.get(0);
// You can actually reassign values in the ArrayList with .set(int, Object)
list.set(0, 4);
// Of course, we may need to get rid of things too.
// Use the .remove(Object) or .remove(int) commands.
// The first takes the object to remove as a parameter.
// The second takes the index to remove as a parameter.
Object o = new Object();
list.add(o);
list.remove(o);
list.remove(0);
Okay, I think that will do for arrays and lists right now. Before we get into loops, lets take a brief aside to look at some funky math I used up there once.
Math ~ For The Lazy Programmer
Okay, lets instantiate a few things.
int a = 4;
int b = 6;
int c = 3;
int d = 8;
Okay, that'll do. Now let me show you how we traditionally do math.
a = a + b;
b = b - c;
c = c * d;
d = d / a;
Six key strokes. We're entirely too lazy for that! Lets make it smaller!
a += b;
b -= c;
c *= d;
d /= e;
Five key strokes! Told you programmers were lazy! And just because you're probably far too lazy to think it through, I guess I should probably explain what just happened...
To reduce the amount of typing and to simplify code, programmers came up with this idea of reassigning while simultaniously doing some sort of basic mathematical calculation. In the case of a += b;, we're taking the value of a, adding b to it and then assigning that back to a. Same with the others. b -= c; subtracts c from b and reassigns that value to b. c *= d; multiplies c by d and assigns that value back to c. d /= a; divides d by a and assigns that back to d.
Later on, you'll see that there are a lot of cases where we want to increase or decrease a value by 1. Well, writing a += 1 is too much work. So we use this instead.
// These are different, by the way.
// The first increments after any other operations on the line.
// The second increments before.
a++;
++a;
// I can subtract 1 as well.
a--;
--a;
Down to four key strokes. I'm honestly not sure whether they were lazy or if they though that would make the code easier to read...
What we've just done is far too simple, though. I want to do complex math. Now I know that 2 ^ 4 is 2 * 2 * 2 * 2. I could code that like this...
int num = 2 * 2 * 2 * 2;
I don't feel like it. Java has this really handy Math library for complex mathematics. Like this...
int num = Math.pow(2, 4);
Which takes 2 and raises it to the 4th power. There are a lot of functions in there you might like. And if my browser would ever load up the API, I'd show you some of the ones I think you'd like. Still waiting. Getting impatient. Google Search app is unreachable...crap... Yay!
// Pseudo-random number
int randomNumber = Math.random();
// Absolute value
int num = Math.abs(randomNumber);
// e ^ number
double num2 = Math.exp(randomNumber);
// Log base 10
double num2 = Math.log10(randomNumber);
// Natural log
double num2 = Math.log(randomNumber);
// Guess which one we use more often
// Get the maximum of two numbers
num2 = Math.max(Math.random(), Math.random());
// Or the minimum
num2 = Math.min(Math.random(), Math.random());
Good stuff here. Some of these you'll probably use a lot. I seem to use Math.pow(double, double) a lot. Well, that was a nice change of pace. It was also a nice distraction. I'd better get on with loops, though.
Loops ~ Over and over and over again
There are three different types of loops you need to know about. While, For, and Do loops. They're all pretty straightforward in their basic functionality.
A while loop runs so long as the condition passed to it is true.
// This is the general form of how a while loops works
while(condition);
// This is an infinite loop. Always a bad idea.
while(true);
// Might help to...you know...do something...
boolean stop = false;
while(!stop) {
// do something...
// You may want to check some condition and
// set stop = true at some point.
}
// Not intuitive, but this still works
// The statement is true while stop is true
// Confusing, eh?
while(stop) {
// do something...
}
The loop will check the condition at the beginning of each round and if true, run everything in the loop. If false, jump to whatever is after the loop.
For loops are similar except that you define when you want them to start and end.
// Basic form of a for loop
for(start, condition, increment);
// Here's an example
for(int i = 0; i < 10; i++) {
// do something ten times
}
// Here's a more realistic example
// as well as the reason we covered
// arrays just now
// This prints out every element in the array
// Incidentally, I didn't tell you that you
// can call .length on an array to get the
// capacity of it.
int[] num = new int[15];
for(int i = 0; i < num.length; i++) {
System.out.println("Elements #" + i + ": " + num[i]);
}
// I can call .size() on an ArrayList to get the
// number of elements that it contains
ArrayList<Object> al = new ArrayList<Object>();
// Also, cheap way of populating a list
for(int i = 0; i < 5; i++) {
al.add(new Object());
}
// And then reading it
for(int i = 0; i < al.size(); i++) {
System.out.println(al.get(i));
}
// If you really want, you can embed these things
// inside of each other. I use embedded for loops
// all the time
int a = 10, b = 10, c = 10;
int[][][] array = new int[a][b][c];
// This will run 1000 times. Use it for things like
// traversing three dimensional arrays.
for(int i = 0; i < c; i++) {
for(int j = 0; j < b; j++) {
for(int k = 0; k < a; k++) {
System.out.println(array[i][j][k]);
}
}
}
Partly as code style and mostly as tradition, the letters i, j, and k are traditionally used as loop control variables. Ideally, any time a programmer sees those variables, he or she can simply assume they are for loop control. Keep going if you run out of letters. Once, I had to use a six-embedded for loop. I think I was using i, j, k, l, m, and n.
While and for loops must pass their condition before they can ever enter their loops. If for some reason the condition is false the first time the code sees that loop, it's skipped entirely. Do loops are unique in that they are assured to run at least once. That is because do loops don't check their condition until the end of the loop. They still kick out when they see a false condition, though.
// Basic form
do {
// do something
} while (condition);
// For example
do {
System.out.println("I can't think of anything. Ever again.");
} while (true);
// Lets try this
boolean stop = false;
do {
if(stop)
stop = true;
} while (!stop);
// And just to prove it will work once
// remember that stop == true right now
do {
System.out.println("Going...");
} while (!stop);
I'm sorry I don't have as many example for do loops. The reason is that I simply do not use them. I was taught not to use them for some reason. I think it's a stylistic thing on the part of my instructor. It's about flow of code. By my teaching I would much rather use a boolean to control my loops than to use a do loop just to ensure it happens once. It's really not hard to ensure a normal while loop always happens once and is what I was taught to do. It ends up looking something like this...
boolean stop = false;
while(!stop) {
// do something...
if (check something)
stop = true;
}
That will always run at least once and if the check fails, it'll set stop to true and stop the loop. I might have to slap you on the wrist if you ask me for help with code using a do loop.
How do you decide which type of loop to use? Simple, really. If you know exactly how long the loop is going to run and you're only checking one condition, use a for loop. If you don't know when the loop will end or have multiple conditions, use a while loop. As I said, I just don't use do loops, but I imagine you might use them in place of a while loop if you want to ensure that it runs at least once.
What if I need to kick out of a loop early? I was taught to use booleans to control my loops. But there is a command called break that will pull you out of a loop or switch that you're in immedietly. It's another one of those commands that I'll shoot you if I see you using in a loop.
// Here's how to use break.
// When i hits 50, the conditional
// passes and immedietly kills the loop
int i = 0;
while(i < Integer.MAX_VALUE) {
if(i == 50) {
break;
}
i++
}
// Here's how I would do the same thing.
i = 0;
boolean stop = false;
while(i < Integer.MAX_VALUE && !stop) {
if(i == 50) {
stop = true;
}
i++;
}
You know, I just realized that I didn't talk about switch ever. I really should have done that in the Conditionals lesson. Oh well...since there really isn't a good place in the roadmap and it'll go fast, I'll cover the basics of it here...
Switch ~ Conditionals The Old Way
Basically, you pass switch an integer or enum and it runs down it's list of cases and runs the code after that case. This is the only place I won't shoot you for using break. As the code goes down cases, if it doesn't hit a break, it will pass through cases. This is called fall-through. It's sometimes desireable. If it does not find a matching case, it will match to default, assuming that is defined. You can place a break after the last case, but it really isn't necessary.
// Basic structure
switch(condition) {
case 1:
// do something..
break;
case 2:
// do something..
break;
default:
// do something
}
// Choose even or odd numbers
// This utilized fallthrough to our advantage
switch(condition) {
case 1:
case 3:
case 5:
case 7:
case 9:
System.out.println("Odd");
break;
case 2:
case 4:
case 6:
case 8:
case 10:
System.out.println("Even");
break;
default:
System.out.println("Invalid Number");
}
// But maybe I don't want that...
// Yes the last break is unnecessary.
// It also doesn't hurt anything and it may help
// to remember to just put a break on all of them.
switch(condition) {
case 1:
System.out.println("One");
break;
case 2:
System.out.println("Two");
break;
case 3:
System.out.println("Three");
break;
default:
System.out.println("I'm too lazy to write any other numbers.");
break;
}
And that's all I'm saying about switch for now. If you want to know more, ASK.
Post Epilogue
Hopefully somebody's still reading my lessons. It's lower quality than I'd like because I wanted to get the thing out. As always, I want to hear questions, complaints, and comments.
Also, there is no master source code file for this one...I wrote all the code in the lesson itself. I didn't write anything in a programming environment. That also means I'm assuming I did everything right. If I f*ed something up, let me know so I can fix it.