Lecture. Arrays, Specs, Testing, and Searching, Part 2
[comp1110-2026s2-lec02b] - August 6, 2026
- Fabian Muehlboeck
Lecture. Arrays, Specs, Testing, and Searching, Part 2
[comp1110-2026s2-lec02b]- August 6, 2026
- Fabian Muehlboeck
1. Creating a finite type
[comp1110-2M] - Liam O'Connor, Fabian Muehlboeck
1. Creating a finite type
[comp1110-2M]- Liam O'Connor, Fabian Muehlboeck
Definition 1.1. Enums
[comp1110-2G] - Liam O'Connor, Fabian Muehlboeck
Definition 1.1. Enums
[comp1110-2G]- Liam O'Connor, Fabian Muehlboeck
An enum (short for enumeration) is a user-definable type whose values come from a fixed finite list. Instead of using arbitrary integers or strings, we define a small set of allowed values and give each one a name. For example:
This defines a new type called Month. A variable of type Month can only hold one of these twelve values. For example:
The names (which are by convention written in ALL_CAPS) inside the enum definition are called constants.
They are always written with the type name in front, such as Month.JANUARY or Month.DECEMBER.
This prevents confusion if different enums contain constants with the same name.
1.2. The benefits of enums
[comp1110-2J] - Liam O'Connor, Fabian Muehlboeck
1.2. The benefits of enums
[comp1110-2J]- Liam O'Connor, Fabian Muehlboeck
One advantage of enums is that they help make illegal states unrepresentable.
If we represent months using integers or strings, the program could accidentally produce values that are not valid months (such as "Spring" or -2).
By defining a Month enum, we restrict the variable to a fixed set of valid values (JANUARY, FEBRUARY, MARCH, and so on).
The compiler then ensures that no other values can appear.
This prevents many kinds of mistakes and makes programs easier to reason about, because whenever we see a variable of type Month, we know it must be one of those twelve possibilities.
Example 1.3. A Month from User Input
[comp1110-2H] - Liam O'Connor, Fabian Muehlboeck
Example 1.3. A Month from User Input
[comp1110-2H]- Liam O'Connor, Fabian Muehlboeck
The final line in the above function also demonstrates that enum types have a built in .toString() method that converts to the string representation of the constant name.
Warning 1.4. Enums are reference types
[comp1110-2I] - Liam O'Connor, Fabian Muehlboeck
Warning 1.4. Enums are reference types
[comp1110-2I]- Liam O'Connor, Fabian Muehlboeck
In Java, enum values are technically things that reside in memory, like Strings and arrays: each constant such as Month.JANUARY or Month.AUGUST has its own place in memory.
However, for each constant there is exactly one object created by the Java runtime.
This means every time the program refers to Month.JANUARY, it refers to the same object.
Because there is only one instance of each constant, it is safe to compare enum values using ==.
The comparison simply checks whether the two references point to the same object, which correctly tells us whether the two enum values are the same.
Construction 1.5. The switch statement on enums
[comp1110-2K] - Liam O'Connor, Fabian Muehlboeck
Construction 1.5. The switch statement on enums
[comp1110-2K]- Liam O'Connor, Fabian Muehlboeck
Java provides a convenient way to perform different actions depending on an enum value: the switch statement.
The switch examines the value of g. Each line specifies what to do for one possible value. If m is Month.MARCH, for example, the program prints "Mar".
Notice that inside the switch we write the constants without the Month. prefix. Java already knows that m has type Month, so it knows which constants we mean.
Warning 1.6. The old-style switch statement
[comp1110-2L] - Liam O'Connor, Fabian Muehlboeck
Warning 1.6. The old-style switch statement
[comp1110-2L]- Liam O'Connor, Fabian Muehlboeck
Older versions of Java used a different syntax for switch statements:
This version uses case labels and colons, and each branch usually ends with break.
If break is omitted, execution falls through into the next case, which often causes mistakes.
Therefore, in this course we will use the arrow form and not the older colon style.
Construction 1.7. The switch expression on enums
[comp1110-76] - Liam O'Connor, Fabian Muehlboeck
Construction 1.7. The switch expression on enums
[comp1110-76]- Liam O'Connor, Fabian Muehlboeck
switch is a control structure, like if and while.
In contrast to these two, however, switch can also be used as an expression form, which means it
can be used as the right-hand side of an assignment. For example:
In this case, it is important that each case of the switch expression returns a value of a suitable type.
If you need more complicated logic for a case, you can have a code block enclosed in curly braces, where the special
yield statement works like a sort of local return statement.
This form is not really important for this course, but you may encounter it in newer Java code.
Construction 1.8. Larger types and the default case for switch
[comp1110-78] - Fabian Muehlboeck
Construction 1.8. Larger types and the default case for switch
[comp1110-78]- Fabian Muehlboeck
The switch statements/expressions do not just work on enum values - in fact, they can distinguish between values of a wide variety of types.
Modern Java uses them to implement a kind of pattern-matching you might be used to from Haskell (but do not worry if you are not - if at all, we will only see that towards the end of this course).
You can also use them on strings or integers.
But those have many possible values - you don't really want to be writing cases for each and every one of them!
Any switch statement or expression can contain a default case for all other values not captures by previous cases.
In addition, individual cases can capture multiple values, like so:
And similarly, you can do the same for Strings:
The main difference here is that the latter works for all kinds of Strings, so you need to be careful about what your catch-all default case expresses. Here, the string "December" would return false, too!
2. Binary Search
[comp1110-77] - Fabian Muehlboeck
2. Binary Search
[comp1110-77]- Fabian Muehlboeck
Example 2.1. Guessing Game
[comp1110-13] - Liam O'Connor, Fabian Muehlboeck
Example 2.1. Guessing Game
[comp1110-13]- Liam O'Connor, Fabian Muehlboeck
In the lecture, we created a guessing game, choosing a "random" number based on a fair die roll.
Note 2.2. Bounding our Guesses
[comp1110-14] - Liam O'Connor, Fabian Muehlboeck
Note 2.2. Bounding our Guesses
[comp1110-14]- Liam O'Connor, Fabian Muehlboeck
If we know that the range of possible answers in Example 2.1 is \(0\) to \(100\), then we can algorithmically devise a procedure that will always guess the right answer:
- We know that the number is between \(0\) and \(100\). Guess \(50\). We get the report
Smaller!. - We know that the number is between \(0\) and \(49\). Guess \(25\). We get the report
Bigger!. - We know that the number is between \(26\) and \(49\). Guess \(37\). We get the report
Smaller!. - We know that the number is between \(26\) and \(36\). Guess \(31\). We get the report
Bigger!. - We know that the number is between \(32\) and \(36\). Guess \(34\). We succeed.
Following this procedure of always bisecting the possible range means that we will always get the answer in at most \(\log _2 100 \simeq 7\) guesses. In general, this bisecting means that for a range \(0\) to \(n\), we will get the answer in at most \(\log _2 n\) guesses.
Example 2.3. Binary Search
[comp1110-1J] - Liam O'Connor
Example 2.3. Binary Search
[comp1110-1J]- Liam O'Connor
If we add a precondition to the spec of contains, that the input array is sorted,
we can use a trick similar to our solution algorithm for our guessing game, which as we saw,
can reduce the amount of iterations of the program from linear in the size of the input to logarithmic.
The idea is that we consistently pick the middle index from the range of possible indices. If the value at this index is our target, we have found what we're looking for, and we're done. If the value at this index is larger than our target, that means our desired index is to the left, and reduces the range of possible indices by half. If it is smaller, then our desired index is to the other half, on the right of the selected midpoint.
This narrows the range of possible indices, which permits us to repeat this technique until we reach single elements.
3. Syntax sugar
[comp1110-1H] - Liam O'Connor
3. Syntax sugar
[comp1110-1H]- Liam O'Connor
There are a number of syntactic conveniences in Java that I have been avoiding (and likely will continue to avoid) in this course. Still, it's worth knowing these to understand code you find elsewhere
Construction 3.1. Three statement for loops
[comp1110-1F] - Liam O'Connor
Construction 3.1. Three statement for loops
[comp1110-1F]- Liam O'Connor
Many times throughout this course we have written while loops of the following format:
Sometimes, for greater conciseness, and to prevent forgetting to increment the counter,
Java programmers will instead write this loop as follows, using the for keyword:
For this course, I will not use this notation because the three statements inside the for
are executed at three separate locations in the code, so the for loop obscures code clarity slightly.
If you see this loop elsewhere though, its meaning is identical to the while loop above.
And you may feel free to use this loop if it's something to which you're already accustomed.
Construction 3.2. Update operators
[comp1110-1I] - Liam O'Connor
Construction 3.2. Update operators
[comp1110-1I]- Liam O'Connor
Instead of:
One may write:
Or even:
Also, instead of:
One may write:
Or even:
Note 3.3. Omitting braces
[comp1110-1G] - Liam O'Connor
Note 3.3. Omitting braces
[comp1110-1G]- Liam O'Connor
For for and while loops, as well as if statements, the braces may be omitted
if the body consists of just one statement. For example, the body of contains (Example [comp1110-1A] and
Example [comp1110-16]) can be rewritten as follows:
However, this abbreviation can be a danger, because minor syntax errors can lead to unexpected behaviour. For example:
This appears correct, but that's only because of indentation (which Java ignores). So this code is actually equivalent to:
Quite a different program indeed!