1 of 82

Subtype Polymorphism, Comparators, Comparable

1

Lecture 10 (Inheritance 3)

CS61B, Spring 2024 @ UC Berkeley

Slides credit: Josh Hug

2 of 82

Bonus Content: DMS and Type Checking Puzzle

Online Video Only

Lecture 10, CS61B, Spring 2024

3 of 82

A Typing Puzzle

Suppose we have two classes:

  • Dog: Implements bark() method.
  • ShowDog: Extends Dog, overrides bark method.

Summarizing is-a relationships, we have:

  • Every ShowDog is-a Dog
  • Every Dog is-an Object.
    • All types in Java are a subtype of Object.

��

Dog

ShowDog

Object

bark()

bark()

4 of 82

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:

  • Compiler allows memory box to hold any subtype.
  • Compiler allows calls based on static type.
  • Overridden non-static methods are selected at run time based on dynamic type.
    • Everything else is based on static type, including overloaded methods. Note: No overloaded methods for problem at left.

5 of 82

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

LivingThing

Squid

Static Type

Dynamic Type

lt1

Animal

Fox

Fox

Fox

a1

h1

LivingThing

Animal

Fox

6 of 82

Static Methods, Variables, and Inheritance

You may find questions on old 61B exams, worksheets, etc. that consider:

  • What if a subclass has variables with the same name as a superclass?
  • What if subclass has a static method with the same signature as a superclass method?
    • For static methods, we do not use the term overriding for this.
  • What if a subclass has methods that overload superclass methods?

These practices are generally not a good idea.

  • It is bad style.
  • There is almost no good reason to ever do this.
  • The rules for resolving the conflict are a bit confusing to learn.
  • I’ve pushed 61B away from learning these rules.
  • But if you want to learn them, see https://docs.oracle.com/javase/tutorial/java/IandI/override.html

7 of 82

Subtype Polymorphism vs. Explicit Higher Order Functions

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

8 of 82

Subtype Polymorphism

The biggest idea of the last couple of lectures: Subtype Polymorphism

  • Polymorphism: “providing a single interface to entities of different types”

Consider a variable deque of static type Deque:

  • When you call deque.addFirst(), the actual behavior is based on the dynamic type.
  • Java automatically selects the right behavior using what is sometimes called “dynamic method selection”.

Curious about alternatives to subtype polymorphism? See wiki or CS164.

a.k.a. compile-time type

a.k.a. run-time type

9 of 82

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.

10 of 82

The Naive Approach

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

11 of 82

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

12 of 82

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?

  1. 0
  2. 1
  3. 2
  4. 3

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

13 of 82

Writing a General Max Function

Objects cannot be compared to other objects with >

  • One (bad) way to fix this: Write a max method in the Dog class.

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

14 of 82

Dog.maxDog

One approach to maximizing a Dog array: Leave it to the Dog class.

  • What is the disadvantage of this?

/** 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);

15 of 82

The Fundamental Problem

Objects cannot be compared to other objects with >

  • How could we fix our Maximizer class using inheritance / HoFs?

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

16 of 82

OurComparable

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

17 of 82

Solution

Create an interface that guarantees a comparison method.

  • Have Dog implement this interface.
  • Write Maximizer class in terms of this interface.

public static OurComparable max(OurComparable[] items) { ...

OurComparable

compareTo(Object)

Dog

compareTo(Object)

Interface inheritance says what a class can do, in this case compare.

18 of 82

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.

19 of 82

Coding Demo: OurComparable

public interface OurComparable {

}

OurComparable.java

20 of 82

Coding Demo: OurComparable

public interface OurComparable {

public int compareTo(Object o);

}

OurComparable.java

21 of 82

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

22 of 82

Coding Demo: OurComparable

public class Dog {

private String name;

private int size;

}

Dog.java

23 of 82

Coding Demo: OurComparable

public class Dog implements OurComparable {

private String name;

private int size;

}

Dog.java

24 of 82

Coding Demo: OurComparable

public class Dog implements OurComparable {

private String name;

private int size;

public int compareTo(Object o) {

}

}

Dog.java

25 of 82

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

26 of 82

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

27 of 82

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

28 of 82

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

29 of 82

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

30 of 82

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

31 of 82

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

32 of 82

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

33 of 82

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

34 of 82

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.

35 of 82

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.

36 of 82

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.

37 of 82

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.

38 of 82

The OurComparable Interface

Specification, returns:

  • Negative number if this is less than obj.
  • 0 if this is equal to object.
  • Positive number if this is greater than obj.

Could have also been OurComparable. No meaningful difference.

public interface OurComparable {

int compareTo(Object o);

}

39 of 82

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);

}

40 of 82

General Maximization Function Through Inheritance

Benefits of this approach:

  • No need for array maximization code in every custom type (i.e. no Dog.maxDog(Dog[]) function required).
  • Code that operates on multiple types (mostly) gracefully, e.g.

OurComparable[] objs = getItems("somefile.txt");

return Maximizer.max(objs);

41 of 82

Compilation Error Puzzle

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

42 of 82

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?

  1. DogLauncher.java
  2. Dog.java
  3. Maximizer.java
  4. OurComparable.java

43 of 82

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?

  • DogLauncher.java
  • Dog.java
  • Maximizer.java
  • OurComparable.java

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));

}

}

44 of 82

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.

45 of 82

Comparable

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

46 of 82

The Issues With OurComparable

Two issues:

  • Awkward casting to/from Objects.
  • We made it up.
    • No existing classes implement OurComparable (e.g. String, etc).
    • No existing classes use OurComparable (e.g. no built-in max function that uses OurComparable)

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);

47 of 82

The Issues With OurComparable

Two issues:

  • Awkward casting to/from Objects.
  • We made it up.
    • No existing classes implement OurComparable (e.g. String, etc).
    • No existing classes use OurComparable (e.g. no built-in max function that uses OurComparable)

The industrial strength approach: Use the built-in Comparable interface.

  • Already defined and used by tons of libraries. Uses generics.

public interface OurComparable {

public int compareTo(Object obj);

}

public interface Comparable<T> {

public int compareTo(T obj);

}

48 of 82

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);

}

49 of 82

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);

}

50 of 82

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);

}

51 of 82

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

52 of 82

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

53 of 82

Comparable vs. OurComparable

Comparable<Dog>

compareTo(Dog)

Dog

compareTo(Dog)

OurComparable

compareTo(Object)

Dog

compareTo(Object)

54 of 82

Comparable Advantages

  • Lots of built in classes implement Comparable (e.g. String).
  • Lots of libraries use the Comparable interface (e.g. Arrays.sort)
  • Avoids need for casts.

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).

55 of 82

Comparators

Lecture 10, CS61B, Spring 2024

Subtype Polymorphism vs. Explicit Higher Order Functions

Building a General Max Function

  • The Naive Approach
  • OurComparable
  • Compilation Error Puzzle
  • Comparable

Comparators

56 of 82

Natural Order

The term “Natural Order” is sometimes used to refer to the ordering implied by a Comparable’s compareTo method.

  • Example: Dog objects (as we’ve defined them) have a natural order given by their size.

“Doge”, size: 5

“Grigometh”, size: 200

“Clifford”, size: 9000

57 of 82

Natural Order

May wish to order objects in a different way.

  • Example: By Name.

“Grigometh”, size: 200

“Doge”, size: 5

“Clifford”, size: 9000

58 of 82

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.

59 of 82

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):

  • Add more functions compareTo2, compareTo3, compareTo4, etc.
  • Add an extra argument to specify which comparison you want:�public int compareTo(Dog uddaDog, String whichCompare)

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.

60 of 82

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.

61 of 82

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

62 of 82

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

63 of 82

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

64 of 82

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

65 of 82

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

66 of 82

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

67 of 82

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

68 of 82

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

69 of 82

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

70 of 82

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

71 of 82

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

72 of 82

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.

73 of 82

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.

74 of 82

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.

75 of 82

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.

76 of 82

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.

77 of 82

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.

78 of 82

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.

79 of 82

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.

80 of 82

Additional Orders in Java

In some languages, we’d write two comparison functions and simply pass the one we want :

  • sizeCompare()
  • nameCompare()

The standard Java approach: Create SizeComparator and NameComparator classes that implement the Comparator interface.

  • Requires methods that also take Comparator arguments (see project 1C).�

public interface Comparator<T> {

int compare(T o1, T o2);

}

81 of 82

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

82 of 82

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.