Second Summer 2002

Lecture Notes Twenty-Three: Vectors, Hashtables, Leftovers.
First here's a Selection Sort that we have developed in class.

```class One {
static void sort(int[] a) {
for (int start = 0; start < a.length - 1; start++) {
for (int j = start; j < a.length; j++) {
if (a[start] > a[j]) { // sorting in ascending order
int temp = a[start];
a[start] = a[j];
a[j] = temp;
}
}
}
}
public static void main(String[] args) {
int[] numbers = new int[args.length];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = Integer.parseInt(args[i]);
}
System.out.println("Here's the initial array: ");
One.show(numbers);
System.out.println("Let me sort it in ascending order...");
One.sort(numbers);
System.out.println("... Done\nHere it is sorted: ");
One.show(numbers);

}
static void show(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
} ```
Here's how it runs:
```frilled.cs.indiana.edu%javac One.java
frilled.cs.indiana.edu%java One 3 4 1 2 6 7
Here's the initial array:
3 4 1 2 6 7
Let me sort it in ascending order...
... Done
Here it is sorted:
1 2 3 4 6 7
frilled.cs.indiana.edu%```
To clarify the idea of scope of a variable let's look at this example:
```class Two {
public static void main(String[] args) {
int a = 1;

{
int b = 2;

System.out.println("a: " + a);
a = 4; // change will be seen by the other block
System.out.println("b: " + b);

}

// System.out.println("b: " + b);

{
int b = 3;

System.out.println("a: " + a);
System.out.println("b: " + b);

}

}
}```
I'll let you experiment with it.

Here's a second method of sorting: Bubble Sort.

```class Three {
static void sort(int[] a) {
boolean done;
do {
done = true;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) { // sort in ascending order

int temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
done = false;

}
}
} while (! done);
}
static void main(String[] args) {
int[] numbers = new int[args.length];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = Integer.parseInt(args[i]);
}
System.out.println("Here's the initial array: ");
Three.show(numbers);
System.out.println("Let me sort it in ascending order...");
Three.sort(numbers);
System.out.println("... Done\nHere it is sorted: ");
Three.show(numbers);

}
static void show(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
} ```
It runs just like the other one, but the mechanism is different.

The outer `do-while` loop is normally added at the end.

For this reason I find the following method much more intuitive.

```class Four {

static void sort(int[] a) {
boolean done = true;
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) { // sort in ascending order
int temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
done = false;
}
}
if (! done)
sort(a);
}

static void main(String[] args) {
int[] numbers = new int[args.length];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = Integer.parseInt(args[i]);
}
System.out.println("Here's the initial array: ");
One.show(numbers);
System.out.println("Let me sort it in ascending order...");
One.sort(numbers);
System.out.println("... Done\nHere it is sorted: ");
One.show(numbers);

}
static void show(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
}  ```
Yes, recursion, in some cases, amounts to just a loop.

One could improve on the Bubble Sort technique above.

Here's an applet that illustrates the differences between three sorting methods:

• quick sort (not selection sort)
• regular bubble sort
• improved bubble sorting
The applet, I believe, is very exciting.

It shows how the methods work, and illustrates topics from chapter 15.

Let's move on.

• inheritance and
• the class extension mechanism.

These are more or less the same topic.

We can illustrate them both by this example:

```class Horse {
int numberOfLegs();
void fun() {
System.out.println("I am a Horse.");
}
}

class Unicorn extends Horse {
void fun() {
System.out.println("I am a Unicorn. Like a horse, but with a horn.");
}
}

class Experiment {
public static void main(String[] args) {
Horse      a = new Horse();
System.out.println("A horse has " + a.numberOfLegs + " legs.");
Horse      b = new Unicorn();
Unicorn    c = new Unicorn();
System.out.println("A unicorn has " + c.numberOfLegs + " legs.");
// Unicorn d = new Horse(); // Not allowed.
System.out.print("First test:  ");
a.fun(); // a horse, of course
System.out.print("Second test: ");
c.fun(); // a unicorn, of course
System.out.print("Third test:  ");
b.fun(); // what will this be?

}
}
```
That's what you need to know to understand applets.

It's also important to understand how `Vector`s work.

We will talk about `Vector`s in a little while.

Here's the example promised on developing things in stages:

```frilled.cs.indiana.edu%cat Stages.java
class One {
int add(int n, int m) {
if (m == 0) return n;
}
}

class Two extends One {
int mul(int n, int m) {
if (m == 1) return n;
}
}

class Three extends Two {
int pow(int n, int m) {
if (m == 0) return 1;
else return mul(n, pow(n, m-1));
}
}

class Calculator {
public static void main(String[] args) {
Three calc = new Three();
int n = 3, m = 5;
System.out.println(n + " + " + m + " = " + calc.add(n, m));
System.out.println(n + " * " + m + " = " + calc.mul(n, m));
System.out.println(n + " ^ " + m + " = " + calc.pow(n, m));
}
}

frilled.cs.indiana.edu%javac Stages.java
frilled.cs.indiana.edu%java Calculator
3 + 5 = 8
3 * 5 = 15
3 ^ 5 = 243
frilled.cs.indiana.edu%```
Here's a different, somewhat similar, example on interfaces.

```frilled.cs.indiana.edu%cat Example.java
interface Multiplier {
int mul(int n, int m);
}

class Alpha implements Multiplier {
public int mul(int n, int m) {
return n * m;
}
}

class Beta implements Multiplier {
public int mul(int n, int m) {
int result = 0;
for (int i = 0; i < m; i++)
result += n;
return result;
}
}

class Gamma implements Multiplier {
public int mul(int n, int m) {
if (m == 1) return n;
else return n + mul(n, m-1);
}
}

class Example {
public static void main(String[] args) {
Alpha a = new Alpha();
Beta b = new Beta();
Gamma g = new Gamma();
int n = 5, m = 3;
System.out.println(n + " * " + m + " = " + a.mul(n,m) + " (by Alpha)");
System.out.println(n + " * " + m + " = " + b.mul(n,m) + " (by Beta )");
System.out.println(n + " * " + m + " = " + g.mul(n,m) + " (by Gamma)");
}
}

frilled.cs.indiana.edu%javac Example.java
frilled.cs.indiana.edu%java Example
5 * 3 = 15 (by Alpha)
5 * 3 = 15 (by Beta )
5 * 3 = 15 (by Gamma)
frilled.cs.indiana.edu%```

 An interface is an element of pure design. Now let's talk about `Vector`s.

 What is a `Vector`? Here's a hint.
`http://java.sun.com/products/jdk/1.2/docs/api/java/util/Vector.html`

 Can I make a summary? Go for it.

 A `Vector` object responds to the following messages:
`void addElement (Object obj) `
Adds the object to the end of the vector, increasing its size by one.

`boolean contains (Object obj) `
Returns `true` if the object is among the values stored in the vector, or `false` otherwise.

`Object elementAt (int index) `
Returns the object at the specified index position.

`int indexOf (Object obj) `
Returns the index position of the first instance of the object in the vector (if the object is in the vector) or `-1` otherwise.

`int indexOf (Object obj, int index) `
Same as above, but starts the search from the specified index.

`void insertElementAt(Object obj, int index)`
Inserts the object at the specified index position, after shifting down objects at and below the insertion point.

`boolean isEmpty () `
Returns `true` if the vector contains no objects, or `false` otherwise.

`void removeElement (Object obj) `
Removes the first occurrence of the specified object, and then shifts up objects at and below the deletion point.

`void removeElementAt(int index) `
Deletes the object at the specified index position, and then shifts up objects at and below the deletion point.

`void setElementAt (Object obj, int index) `
Replaces the existing object at the specified index position with the specified object.

`int size () `
Returns the number of objects currently stored in the vector.

 That's only part of what a `Vector` does best!

 To create a new `Vector` ... one should invoke a no-arg constructor.

 Something like this: `Vector a = new Vector();` This creates a new (and empty) `Vector` object.

 Can you define a class `Vector`? Here's a reasonable start:
```class Vector {

Object[] localStorage = new Object[0];

int size() {
return localStorage.length;
}

int currentLength = this.size();

Object[] aux = new Object[currentLength + 1];
aux[currentLength] = obj;

for (int i = 0; i < currentLength; i++) {
aux[i] = localStorage[i]; // transfer elements
}

localStorage = aux;
}

public String toString() {

String returnString = "Vector of size " + size() + ": (";

for (int i = 0; i < localStorage.length; i++)
returnString += " " + localStorage[i];  // delay printing...

return returnString + ")";
}

public static void main(String[] args) {

Vector v = new Vector();
System.out.println(v); // convenient printing

System.out.println(v);

System.out.println(v);

System.out.println(v);
}
}```

 What would this be? An operational model for `java.util.Vector`

 "What I cannot create, I cannot understand." So we put one together, just for the fun of it.

 Very good. Can I see this running? No.

 What do you mean? Of course you can!
```tucotuco.cs.indiana.edu% javac Vector.java
tucotuco.cs.indiana.edu% java Vector
Vector of size 0: ()
Vector of size 1: ( 2)
Vector of size 2: ( 2 4)
Vector of size 3: ( 2 4 6)
tucotuco.cs.indiana.edu%```

 Now let's look at the code line by line. It will be my pleasure.

```class Vector {
Object[] localStorage = new Object[0];```
 I see you use an array of `Object`s inside an instance of my `Vector` class. OK, I should have made it `private`, but now it's too late.

 This is the internal (local) storage that is available to every instance of type `Vector`, ... to every object that is instantiated with the `new` operator out of class `Vector`.

 I make a distinction between an array of size `0` and no array whatsoever (that is, a `null` pointer). And so do I.

 I start with an array of size `0` because I want my `localStorage` to always have a useful `length` to return (a `null` pointer returns an exception when asked about it's `length`.) That was exactly my thinking.

 So I start with an array of size `0` for uniformity. And implementing `size` is a breeze.
```  int size() {
return localStorage.length;
}```

 Now let's tell the story of `addElement`.
 OK, here we go:
`  void addElement(Object obj) {`

 This method will reveal our style of implementation. I will not worry about efficiency, I will rely heavily on Java's automatic memory management facilities.

 It's good to optimize one's programs. Yes, but as Donald Knuth remarked once, "premature optimization is the root of all evil".

 Once my program works fine I can try to optimize it. But first, I need to make it work correctly.

 Correctness concerns us most at this stage. Yes. Let's start. We first get the size of the vector (our local storage is always at capacity.)
`    int currentLength = this.size(); `

 Would've worked just as well if we had talked to `localStorage` directly, right? Yes, but this way we are expressing ourselves in `Vector` terms.

 Then we get ready to store a new element, ... and allocate space that's bigger with one than our current size.
`    Object[] aux = new Object[currentLength + 1]; `

 Now place the object that needs to be added in the last position. Indeed, that's what we said we'd be doing.
`    aux[currentLength] = obj;`

 Transfer the objects from the local storage into the new array one by one.
```    for (int i = 0; i < currentLength; i++) {
aux[i] = localStorage[i];
} ```
 Then call this new array our `localStorage`.
`    localStorage = aux; `

 What will happen to the array that the `localStorage` variable's previously pointing to? Gone with the wind.

 That's quite correct. And since no variable references it any longer, ... it will be collected by Java's garbage collector.

`  } `
 Curly brace. End of story.

 That's how we add a new element to a `Vector`. Removing an element should be similar.

 The rest of my program only serves testing purposes. Yes, but it's still instructive!

 If I ever place a `Vector` in a `String` context ... it will be this method that will kick in.
`  public String toString() {`

 Let's see how it works. I start by printing the type (vector) and the size.
`    String returnString = "Vector of size " + size() + ": (";`

 You're not really printing, are you? No, just putting together a `String` representation that will eventually be printed (but not here).

 The elements if any will be listed one by one
```    for (int i = 0; i < localStorage.length; i++)
returnString += " " + localStorage[i]; ```
 ... and the list will appear in between parens.
```    return returnString + ")";
} ```

 The `main` method creates a vector, and adds three elements to it. We could have used `Product`s, you know?

 Yes, but this points out what you need to do if you want to store numbers. You have to use wrapper classes.

 Which are number holders. ... and after each addition the `Vector` is printed.
```  public static void main(String[] args) {

Vector v = new Vector();
System.out.println(v);

System.out.println(v);

System.out.println(v);

System.out.println(v);
}
}```

 Well, that was easy! Easy and clear!

 What's a `Hashtable`? Let me look it up!
`http://java.sun.com/products/jdk/1.2/docs/api/java/util/Hashtable.html`

 A `Hashtable` is a generalized kind of `Vector`. A `Vector` is a generalized kind of array.

 The `Vector` is more general than an array because it grows and shrinks dynamically, and the elements don't have to be of the same type. Both arrays and `Vector`s map indices (numbers) to elements contained.

 They're sequences. A `Hashtable` is more general in that it stores associations between keys and values.

 The keys and the values could be any objects. For example `String`s.

 If you wanted to store associations of this kind: `username --> password` using `Vector`s or arrays You'd have to use parallel `Vector`s or arrays!

 `Hashtable`s are built just for that! They're sometimes called associative arrays.

 Once the association is built, ... we want to use it.

 So, given a `username`, we need to... ... look up the `password` that is associated with it.

 That's what `Hashtable`s do best! Here's an example that uses a `Hashtable` object to interactively manage a set of `String`s.
```import java.util.*;

class Set {
public static void main(String[] args) {

Hashtable h = new Hashtable();

while (true) {

String command = "", argument = "";

if (s.hasMoreTokens()) { command  = s.nextToken(); }

if (s.hasMoreTokens()) { argument = s.nextToken(); }

h.put(argument, argument);
System.out.println("OK");

} else if (command.equals("delete")) {
h.remove(argument);
System.out.println("OK");

} else if (command.equals("list")) {
Enumeration e = h.keys();
while (e.hasMoreElements()) {
System.out.println(" :" + e.nextElement());
}

} else if (command.equals("contains")) {
System.out.println(h.containsKey(argument));

} else if (command.equals("quit")) {
System.exit(0);

} else {
System.out.println("Unknown command: " +
command + " " + argument);
}
}
}
}
```

 This is an interactive program. Yes, you need to type commands into it.

 Can I see it running? Here's the program (in blue) talking to a user.
```frilled.cs.indiana.edu%java Set
OK
OK
list
:one
:two
OK
list
:one
:two
:three
OK
list
:one
:two
:three
delete three
OK
list
:one
:two
contains three
false
contains two
true
quit
frilled.cs.indiana.edu%```

 Arrays and vectors can store linear sequences. Hashtables are functions of just one variable.

 It often happens that you want to store collections that have a two-dimensional layout. Such an arrangement, consists of rows and columns of values, and is called (not surprisingly) a two-dimensional array.

 ... or matrix (sometimes). When constructing a two-dimensional array, you specify how many rows and columns you need.

 If you want `10` rows and `8` columns:
`int[][] matrix = new int[10][8];`
 A `10 x 8` matrix of `int`s.

 To access a particular element in the array
`matrix[3][4] = 5;`
 ... specify two subscripts, in separate brackets.

 In Java, two-dimensional arrays are stored as arrays of arrays. And three dimensional arrays are stored as arrays of two-dimensional arrays.

 That means arrays of arrays of arrays. Yes, arrays of (arrays of arrays).

 And n-dimensional arrays will be stored as arrays of (n-1)-dimensional arrays. What a recursive definition.

 We won't use more than two-dimensions. Let's take a closer look at them though: because a two-dimensional array is really an array of the row arrays,

 ... the number of rows is: And the number or columns?
`int nrows = matrix.length;`

 Because a two-dimensional array is really an array of the row arrays, ... the number of elements in each row can vary.

 But it doesn't have to.
 If it doesn't, the number of columns is the same as the length of the first row:
`int ncols = matrix[0].length;`

 Can I see an example of a two-dimensional array that has rows of various lengths? Yes, you can quickly create one with an array initializer:
```int[][] b = { {1},
{2, 3},
{4, 5, 6},
{7, 8, 9, 10}
}; ```

 Can you do the same thing without it? Sure, I thought you'd ask:
```int[][] b = new int[4][];
int count = 1;
for (int i = 0; i < 4; i++) {
b[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
b[i][j] = count;
count += 1;
}
} ```

 I see you have to work harder. Yes, first you allocate space to hold four rows.

 You indicate that you will manually set each row by leaving the second array index empty. Then you need to allocate (and fill) each row separately.

 You can access each array element as `b[i][j]`, ... but you must be careful that `j` is less than `b[i].length` as illustrated below:
```class Testing {
public static void main(String[] args) {

int[][] b = new int[4][];
int count = 1;
for (int i = 0; i < 4; i++) {
b[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
b[i][j] = count;
count += 1;
}
}

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

}
}
```
 Naturally, such "ragged" arrays are not very common. Except when you need them.

 Then they become very natural. And they're no longer "ragged".

 Exactly, because they fit that problem ... perfectly.

Last updated: Jul 24, 2002 by Adrian German for A201