Subtype Polymorphism, Comparators, Comparable
1
Lecture 10 (Inheritance 3)
CS61B, Spring 2024 @ UC Berkeley
Slides credit: Josh Hug
Bonus Content: DMS and Type Checking Puzzle
Online Video Only
Lecture 10, CS61B, Spring 2024
A Typing Puzzle
Suppose we have two classes:
Summarizing is-a relationships, we have:
��
Dog
ShowDog
Object
bark()
bark()
A Typing Puzzle
For each assignment, decide if it causes a compile error.
For each call to bark, decide whether: 1. Dog.bark() is called, 2. ShowDog.bark() is called, or 3. A syntax error results.
The rules:
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
LivingThing
Squid
Static Type
Dynamic Type
lt1
Animal
Fox
Fox
Fox
a1
h1
LivingThing
Animal
Fox
Static Methods, Variables, and Inheritance
You may find questions on old 61B exams, worksheets, etc. that consider:
These practices are generally not a good idea.
Subtype Polymorphism vs. Explicit Higher Order Functions
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
Subtype Polymorphism
The biggest idea of the last couple of lectures: Subtype Polymorphism
Consider a variable deque of static type Deque:
Curious about alternatives to subtype polymorphism? See wiki or CS164.
a.k.a. compile-time type
a.k.a. run-time type
Subtype Polymorphism vs. Explicit Higher Order Functions
Suppose we want to write a program that prints a string representation of the larger of two objects.
def print_larger(x, y, compare, stringify):
if compare(x, y):
return stringify(x)
return stringify(y)
Explicit
HoF Approach
def print_larger(x, y):
if x.largerThan(y):
return x.str()
return y.str()
Subtype Polymorphism Approach
Sometimes called a “callback”.
Not to be confused with the fascinating Dr. Ernest Kaulbach, who taught my Old English class.
The Naive Approach
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
Goal: The One True Max Function
Suppose we want to write a function max() that returns the max of any array, regardless of type.
max
5
3
1
7
0 1 2 3
0 1 2
7
max
Sture
9 lbs
Benjamin
15 lbs
Elyse
3 lbs
Compilation Error Challenge: yellkey.com/dog
Suppose we want to write a function max() that returns the max of any array, regardless of type. How many compilation errors are there in the code shown?
public static Object max(Object[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i; }}
return items[maxDex];
}
Maximizer.java
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
DogLauncher.java
Writing a General Max Function
Objects cannot be compared to other objects with >
public static Object max(Object[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i; }}
return items[maxDex];
}
Maximizer.java
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
DogLauncher.java
Dog.maxDog
One approach to maximizing a Dog array: Leave it to the Dog class.
/** Returns maximum of dogs. */
public static Dog maxDog(Dog[] dogs) {
if (dogs == null || dogs.length == 0) {
return null; }
Dog maxDog = dogs[0];
for (Dog d : dogs) {
if (d.size > maxDog.size) {
maxDog = d; }}
return maxDog;
}
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog largest = Dog.maxDog(dogs);
The Fundamental Problem
Objects cannot be compared to other objects with >
public static Object max(Object[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i; }}
return items[maxDex];
}
Maximizer.java
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
DogLauncher.java
OurComparable
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
Solution
Create an interface that guarantees a comparison method.
public static OurComparable max(OurComparable[] items) { ...
OurComparable
compareTo(Object)
Dog
compareTo(Object)
Interface inheritance says what a class can do, in this case compare.
Coding Demo: OurComparable
public class Maximizer {
public static Object max(Object[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i;
}
}
return items[maxDex];
}
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
}
Maximizer.java
This doesn't compile because you can't compare objects with the > operator.
Coding Demo: OurComparable
public interface OurComparable {
}
OurComparable.java
Coding Demo: OurComparable
public interface OurComparable {
public int compareTo(Object o);
}
OurComparable.java
Coding Demo: OurComparable
public interface OurComparable {
/** Return -1 if this < o.
* Return 0 if this equals o.
* Return 1 if this > o.
*/
public int compareTo(Object o);
}
OurComparable.java
Coding Demo: OurComparable
public class Dog {
private String name;
private int size;
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
public int compareTo(Object o) {
}
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
}
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
if (this.size < o.size) {
return -1;
}
}
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
if (this.size < o.size) {
return -1;
} else if (this.size == o.size) {
return 0;
}
}
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
if (this.size < o.size) {
return -1;
} else if (this.size == o.size) {
return 0;
}
return 1;
}
}
Dog.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
if (this.size < uddaDog.size) {
return -1;
} else if (this.size == uddaDog.size) {
return 0;
}
return 1;
}
}
Dog.java
Coding Demo: OurComparable
public class Maximizer {
public static Object max(Object[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i;
}
}
return items[maxDex];
}
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
}
Maximizer.java
Coding Demo: OurComparable
public class Maximizer {
public static OurComparable max(OurComparable[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
if (items[i] > items[maxDex]) {
maxDex = i;
}
}
return items[maxDex];
}
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
}
Maximizer.java
Coding Demo: OurComparable
public class Maximizer {
public static OurComparable max(OurComparable[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
int cmp = items[i].compareTo(items[maxDex]);
if (items[i] > items[maxDex]) {
maxDex = i;
}
}
return items[maxDex];
}
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
}
Maximizer.java
Coding Demo: OurComparable
public class Maximizer {
public static OurComparable max(OurComparable[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
int cmp = items[i].compareTo(items[maxDex]);
if (cmp > 0) {
maxDex = i;
}
}
return items[maxDex];
}
public static void main(String[] args) {
Dog[] dogs = {new Dog("Elyse", 3), new Dog("Sture", 9),
new Dog("Benjamin", 15)};
Dog maxDog = (Dog) Maximizer.max(dogs);
maxDog.bark();
}
}
Maximizer.java
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns -1 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
if (this.size < uddaDog.size) {
return -1;
} else if (this.size == uddaDog.size) {
return 0;
}
return 1;
}
}
Dog.java
This code is kind of long. We can simplify it with the following trick.
Coding Demo: OurComparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
return this.size - uddaDog.size;
}
}
Dog.java
This code is kind of long. We can simplify it with the following trick.
Coding Demo: OurComparable
public interface OurComparable {
/** Return -1 if this < o.
* Return 0 if this equals o.
* Return 1 if this > o.
*/
public int compareTo(Object o);
}
OurComparable.java
We need to modify our interface specification accordingly.
Coding Demo: OurComparable
public interface OurComparable {
/** Return negative number if this < o.
* Return 0 if this equals o.
* Return positive number if this > o.
*/
public int compareTo(Object o);
}
OurComparable.java
We need to modify our interface specification accordingly.
The OurComparable Interface
Specification, returns:
Could have also been OurComparable. No meaningful difference.
public interface OurComparable {
int compareTo(Object o);
}
General Maximization Function Through Inheritance
public class Maximizer {
public static OurComparable max(OurComparable[] a) {
...
}
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog largest = (Dog) Maximizer.max(dogs);
public class Dog implements OurComparable {
public int compareTo(Object obj) {
/** Warning, cast can cause runtime error! */
Dog uddaDog = (Dog) obj;
return this.size - uddaDog.size;
} ...
public interface OurComparable {
int compareTo(Object o);
}
General Maximization Function Through Inheritance
Benefits of this approach:
OurComparable[] objs = getItems("somefile.txt");
return Maximizer.max(objs);
Compilation Error Puzzle
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
Interfaces Quiz #1: yellkey.com/TODO
public class Maximizer {
public static OurComparable max(
OurComparable[] items) {
...
int cmp = items[i].
compareTo(items[maxDex]);
...
} ...
public class Dog
implements OurComparable {
...
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
return this.size
- uddaDog.size;
} ...
public class DogLauncher {
public static void main(String[] args) {
...
Dog[] dogs = new Dog[]{d1, d2, d3};
System.out.println(Maximizer.max(dogs));
}
}
Q: If we omit compareTo(), which file will fail to compile?
Interfaces Quiz #2: yellkey.com/TODO
public class Dog
implements OurComparable {
...
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
return this.size
- uddaDog.size;
} ...
Q: If we omit implements OurComparable, which file will fail to compile?
public class Maximizer {
public static OurComparable max(
OurComparable[] items) {
...
int cmp = items[i].
compareTo(items[maxDex]);
...
} ...
public class DogLauncher {
public static void main(String[] args) {
...
Dog[] dogs = new Dog[]{d1, d2, d3};
System.out.println(Maximizer.max(dogs));
}
}
Answers to Quiz
Problem 1: Dog will fail to compile because it does not implement all abstract methods required by OurComparable interface. (And I suppose DogLauncher will fail as well since Dog.class doesn’t exist)
Problem 2: DogLauncher will fail, because it tries to pass things that are not OurComparables, and Maximizer expects OurComparables.
Comparable
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
The Issues With OurComparable
Two issues:
public class Dog implements OurComparable {
public int compareTo(Object obj) {
/** Warning, cast can cause runtime error! */
Dog uddaDog = (Dog) obj;
return this.size - uddaDog.size;
} ...
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog largest = (Dog) Maximizer.max(dogs);
The Issues With OurComparable
Two issues:
The industrial strength approach: Use the built-in Comparable interface.
public interface OurComparable {
public int compareTo(Object obj);
}
public interface Comparable<T> {
public int compareTo(T obj);
}
Coding Demo: Comparable
public class Dog implements OurComparable {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
return this.size - uddaDog.size;
}
}
Dog.java
Replacing OurComparable with the built-in Comparable interface.
public interface Comparable<T> {
public int compareTo(T obj);
}
Coding Demo: Comparable
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Object o) {
Dog uddaDog = (Dog) o;
return this.size - uddaDog.size;
}
}
Dog.java
Replacing OurComparable with the built-in Comparable interface.
public interface Comparable<T> {
public int compareTo(T obj);
}
Coding Demo: Comparable
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
}
Dog.java
Replacing OurComparable with the built-in Comparable interface.
public interface Comparable<T> {
public int compareTo(T obj);
}
Coding Demo: OurComparable
public class Maximizer {
public static OurComparable max(OurComparable[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
int cmp = items[i].compareTo(items[maxDex]);
if (cmp > 0) {
maxDex = i;
}
}
return items[maxDex];
}
}
Maximizer.java
Coding Demo: OurComparable
public class Maximizer {
public static Comparable max(Comparable[] items) {
int maxDex = 0;
for (int i = 0; i < items.length; i += 1) {
int cmp = items[i].compareTo(items[maxDex]);
if (cmp > 0) {
maxDex = i;
}
}
return items[maxDex];
}
}
Maximizer.java
Comparable vs. OurComparable
Comparable<Dog>
compareTo(Dog)
Dog
compareTo(Dog)
OurComparable
compareTo(Object)
Dog
compareTo(Object)
Comparable Advantages
public class Dog implements OurComparable {
public int compareTo(Object obj) {
Dog uddaDog = (Dog) obj;
return this.size - uddaDog.size;
} ...
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog largest = Collections.max(Arrays.asList(dogs));
public class Dog implements Comparable<Dog> {
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
Much better!
Implementing Comparable allows library functions to compare custom types (e.g. finding max).
Comparators
Lecture 10, CS61B, Spring 2024
Subtype Polymorphism vs. Explicit Higher Order Functions
Building a General Max Function
Comparators
Natural Order
The term “Natural Order” is sometimes used to refer to the ordering implied by a Comparable’s compareTo method.
“Doge”, size: 5
“Grigometh”, size: 200
“Clifford”, size: 9000
Natural Order
May wish to order objects in a different way.
“Grigometh”, size: 200
“Doge”, size: 5
“Clifford”, size: 9000
Subtype Polymorphism vs. Explicit Higher Order Functions
Suppose we want to write a program that prints a string representation of the larger of two objects according to some specific comparison function.
def print_larger(x, y, compare, stringify):
if compare(x, y):
return stringify(x)
return stringify(y)
Explicit
HoF Approach
def print_larger(T x, T y):
if x.largerThan(y):
return x.str()
return y.str()
Subtype Polymorphism Approach??
Can simply pass a different compare function.
Subtype Polymorphism vs. Explicit Higher Order Functions
Suppose we want to write a program that prints a string representation of the larger of two objects according to some specific comparison function.
Some possible designs (not the best):
def print_larger(x, y, compare, stringify):
if compare(x, y):
return stringify(x)
return stringify(y)
Explicit
HoF Approach
Can simply pass a different compare function.
Subtype Polymorphism vs. Explicit Higher Order Functions
Suppose we want to write a program that prints a string representation of the larger of two objects according to some specific comparison function.
def print_larger(x, y, compare, stringify):
if compare(x, y):
return stringify(x)
return stringify(y)
Explicit
HoF Approach
def print_larger(T x, T y, comparator<T> c):
if c.compare(x, y):
return x.str()
return y.str()
Subtype Polymorphism Approach
Can simply pass a different compare function.
Coding Demo: Comparator
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
}
Dog.java
Coding Demo: Comparator
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public class NameComparator implements Comparator<Dog> {
}
}
Dog.java
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public class NameComparator implements Comparator<Dog> {
}
}
Dog.java
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
}
}
}
Dog.java
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
}
Dog.java
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public static class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
}
Dog.java
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
}
}
DogLauncher.java
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = new Dog.NameComparator();
}
}
DogLauncher.java
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = new Dog.NameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
}
}
}
DogLauncher.java
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = new Dog.NameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
}
}
}
DogLauncher.java
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = new Dog.NameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
} else {
d3.bark();
}
}
}
DogLauncher.java
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
public static class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
}
Dog.java
Slight change to reflect Java convention.
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
private static class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
}
Dog.java
Slight change to reflect Java convention.
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
private static class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
public static Comparator<Dog> getNameComparator() {
}
}
Dog.java
Slight change to reflect Java convention.
Coding Demo: Comparator
import java.util.Comparator;
public class Dog implements Comparable<Dog> {
private String name;
private int size;
/** Returns <0 if this dog is less than the dog pointed at by o, and so forth. */
public int compareTo(Dog uddaDog) {
return this.size - uddaDog.size;
}
private static class NameComparator implements Comparator<Dog> {
public int compare(Dog a, Dog b) {
return a.name.compareTo(b.name);
}
}
public static Comparator<Dog> getNameComparator() {
return new NameComparator();
}
}
Dog.java
Slight change to reflect Java convention.
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = new Dog.NameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
} else {
d3.bark();
}
}
}
DogLauncher.java
Slight change to reflect Java convention.
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Dog.NameComparator nc = Dog.getNameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
} else {
d3.bark();
}
}
}
DogLauncher.java
Slight change to reflect Java convention.
Coding Demo: Comparator
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Comparator<Dog> nc = Dog.getNameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
} else {
d3.bark();
}
}
}
DogLauncher.java
Slight change to reflect Java convention.
Coding Demo: Comparator
import java.util.Comparator;
public class DogLauncher {
public static void main(String[] args) {
Dog d1 = new Dog("Elyse", 3);
Dog d2 = new Dog("Sture", 9);
Dog d3 = new Dog("Benjamin", 15);
Dog[] dogs = new Dog[]{d1, d2, d3};
Comparator<Dog> nc = Dog.getNameComparator();
if (nc.compare(d1, d3) > 0) { // if d1 comes later than d3 in the alphabet
d1.bark();
} else {
d3.bark();
}
}
}
DogLauncher.java
Slight change to reflect Java convention.
Additional Orders in Java
In some languages, we’d write two comparison functions and simply pass the one we want :
The standard Java approach: Create SizeComparator and NameComparator classes that implement the Comparator interface.
public interface Comparator<T> {
int compare(T o1, T o2);
}
Dogs and Comparators
public interface Comparator<T> {
int compare(T o1, T o2);
}
compare(T, T)
Comparator<T>
compare(Dog, Dog)
NameComparator
Dog
Dog not related by inheritance to any of the classes below.
compare(Dog, Dog)
SizeComparator
Example: NameComparator
public class Dog implements Comparable<Dog> {
private String name;
private int size;
public static class NameComparator implements Comparator<Dog> {
public int compare(Dog d1, Dog d2) {
return d1.name.compareTo(d2.name);
}
}
...
}
Comparator<Dog> cd = new Dog.NameComparator();
if (cd.compare(d1, d3) > 0) {
d1.bark();
} else {
d3.bark();
}
Result: If d1 has a name that comes later in the alphabet than d3, d1 barks.