1 of 98

Announcement

My office hour this week are Wednesday 12 - 1 (only one person today!) and on Friday 11 - 12 PM.

2 of 98

What do you want covered in MT 1 review?

61A-style coding questions

Java Syntax

Inheritance (Overloading/Overriding/Implements)

Different forms of Lists (DLLists in particular)

Comparators and Comparables (x2)

Generics

Data Structure Review

Inner Classes

3 of 98

Iterators, Object Methods

3

Lecture 10 (Inheritance 3)

CS61B, Spring 2025 @ UC Berkeley

Slides credit: Josh Hug

4 of 98

Today’s Goal: ArraySet

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

5 of 98

Sets in Java and Python

Today’s goal: Build an implementation of a Set called ArraySet.

  • Won’t be implementing any interface (for now).
  • Starting from basic implementation, we’ll add some “industrial strength” features to the ArraySet like iteration, equality checking, and toString.

ArraySet<String> S = new ArraySet<>();

S.add("Oakland");

S.add("Toronto");

S.add("Minneapolis");

S.add("Oakland"); // no effect

S.add("Taipei");

System.out.println(S.contains("Oakland"));

s = set()

s.add("Oakland")

s.add("Toronto")

s.add("Minneapolis")

s.add("Oakland") # no effect

s.add("Taipei")

print("Oakland" in s)

$ java SetExample

true

$ python set_example.py

True

6 of 98

Goals

Starting point: A class ArraySet with the following methods:

  • add(value): Add the value to the ArraySet if it is not already present.
  • contains(value): Checks to see if ArraySet contains the key.
  • size(): Returns number of values.

For simplicity, I’ll ignore resizing.

The basic functionality is quite straightforward, so I’ll avoid live coding.

7 of 98

ArraySet (Basic Implementation)

public class ArraySet<T> {

private T[] items;

private int size;

public ArraySet() {

items = (T[]) new Object[100];

size = 0;

}

...

}

Array implementation of a Set:

  • Use an array as the core data structure.
  • contains(x): Checks to see if x is in the underlying array.
  • add(x): Checks to see if x is in the underlying array, and if not, adds it.

"Unchecked cast" compiler warning here. Nothing we can do about it.

8 of 98

ArraySet (Basic Implementation)

public void add(T x) {

if (!contains(x)) {

items[size] = x;

size += 1;

}

}

public boolean contains(T x) {

for (int i = 0; i < size; i += 1) {

if (items[i].equals(x)) {

return true;

}

}

return false;

}

Can also throw an IllegalArgumentException if you want to disallow null.

We used items[i].equals(x), not items[i] == x. Recall: == just compares the addresses. We’ll cover what equals does later today.

9 of 98

The Enhanced For Loop

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

10 of 98

The Enhanced For Loop

Java allows us to iterate through Lists and Sets using a convenient shorthand syntax sometimes called the “for-each loop” or “enhanced for loop”.

Set<Integer> javaset = new HashSet<>();

javaset.add(5);

javaset.add(23);

javaset.add(42);

for (int i : javaset) {

System.out.println(i);

}

11 of 98

The Enhanced For Loop

Java allows us to iterate through Lists and Sets using a convenient shorthand syntax sometimes called the “for-each loop” or “enhanced for loop”.

  • This doesn’t work with our ArraySet.
  • Let’s strip away the magic so we can build our own classes that support this.

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

for (int i : aset) {

System.out.println(i);

}

$ javac IterationDemo

error: for-each not applicable to expression type

for (int i : aset) {

^

required: array or java.lang.Iterable

found: ArraySet<Integer>

12 of 98

iterator, next, hasNext

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

13 of 98

Why Doesn’t the Enhanced For Loop Work?

The enhanced for loop works by first calling the .iterator method of the object.

  • This returns an object of type Iterator<Integer>.
  • The Iterator interface has its own API for fetching values one-by-one:
    • hasNext: Tells us whether there are more values.
    • next: gets the next value.

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

for (int i : aset) {

System.out.println(i);

}

What is missing?

14 of 98

How Iteration Really Works

An alternate, uglier way to iterate through a Set is to use the iterator() method.

Suppose we have a Set<Integer> called javaset.

  • In that case, we can iterate with either of the two equivalent pieces of code.
  • Left code is shorthand for right code, i.e. the code on the left is LITERALLY doing the thing on the right.

for (int x : javaset) {

System.out.println(x);

}

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

int x = seer.next();

System.out.println(x);

}

public Iterator<E> iterator();

Set.java:

“Nice” iteration.

“Ugly” iteration.

15 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

5

23

42

javaset:

16 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

$ java IteratorDemo.java

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

17 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

True

$ java IteratorDemo.java

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

18 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

5

$ java IteratorDemo.java

5

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

19 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

True

$ java IteratorDemo.java

5

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

20 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

23

$ java IteratorDemo.java

5

23

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

21 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

$ java IteratorDemo.java

5

23

True

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

22 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

$ java IteratorDemo.java

5

23

42

42

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

23 of 98

How Iterators Work

An alternate, uglier way to iterate through a Set is to use the iterator() method.

5

23

42

javaset:

$ java IteratorDemo.java

5

23

42

False

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

24 of 98

iterator, next, hasNext for ArraySet

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

25 of 98

The Secret of the Enhanced For Loop

The secret: The code on the left is just shorthand for the code on the right. For code on right to compile, which checks does the compiler need to do?

  1. Does the Set interface have an iterator() method?
  2. Does the Set interface have next/hasNext() methods?
  3. Does the Iterator interface have an iterator method?
  4. Does the Iterator interface have next/hasNext() methods?

Set<Integer> javaset = new HashSet<Integer>();

for (int x : javaset) {

System.out.println(x);

}

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

26 of 98

The Secret of the Enhanced For Loop

The secret: The code on the left is just shorthand for the code on the right. For code on right to compile, which checks does the compiler need to do?

  1. Does the Set interface have an iterator() method?
  2. Does the Set interface have next/hasNext() methods?
  3. Does the Iterator interface have an iterator method?
  4. Does the Iterator interface have next/hasNext() methods?

Set<Integer> javaset = new HashSet<Integer>();

for (int x : javaset) {

System.out.println(x);

}

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

System.out.println(seer.next());

}

27 of 98

Supporting Ugly Iteration in ArraySets

To support ugly iteration:

  • Add an iterator() method to ArraySet that returns an Iterator<T>.
  • The Iterator<T> that we return should have a useful hasNext() and next() method.

public interface Iterator<T> {

boolean hasNext();

T next();

}

Iterator<T>

Iterator<Integer> aseer

= aset.iterator();

while (aseer.hasNext()) {

System.out.println(aseer.next());

}

28 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public static void main(String[] args) {

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

}

}

ArraySet.java

29 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public static void main(String[] args) {

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

Iterator<Integer> aseer = aset.iterator();

}

}

ArraySet.java

30 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public static void main(String[] args) {

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

Iterator<Integer> aseer = aset.iterator();

while (aseer.hasNext()) {

}

}

}

ArraySet.java

31 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public static void main(String[] args) {

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

Iterator<Integer> aseer = aset.iterator();

while (aseer.hasNext()) {

int i = aseer.next();

}

}

}

ArraySet.java

32 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public static void main(String[] args) {

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

Iterator<Integer> aseer = aset.iterator();

while (aseer.hasNext()) {

int i = aseer.next();

System.out.println(i);

}

}

}

ArraySet.java

33 of 98

Coding Demo: Iteration

public class ArraySet<T> {

public Iterator<T> iterator() {

}

}

ArraySet.java

34 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

}

}

ArraySet.java

35 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ???;

}

}

ArraySet.java

36 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ???;

}

private class ArraySetIterator implements Iterator<T> {

}

}

ArraySet.java

37 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ???;

}

private class ArraySetIterator implements Iterator<T> {

public boolean hasNext() {

}

}

}

ArraySet.java

38 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ???;

}

private class ArraySetIterator implements Iterator<T> {

public boolean hasNext() {

}

public T next() {

}

}

}

ArraySet.java

39 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

public boolean hasNext() {

}

public T next() {

}

}

}

ArraySet.java

40 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public boolean hasNext() {

}

public T next() {

}

}

}

ArraySet.java

41 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

}

public boolean hasNext() {

}

public T next() {

}

}

}

ArraySet.java

42 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

}

public T next() {

}

}

}

ArraySet.java

43 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

}

}

}

ArraySet.java

44 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

T returnItem = items[wizPos];

}

}

}

ArraySet.java

45 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

T returnItem = items[wizPos];

wizPos += 1;

}

}

}

ArraySet.java

46 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

T returnItem = items[wizPos];

wizPos += 1;

return returnItem;

}

}

}

ArraySet.java

47 of 98

Completed ArraySet iterator Method

To support ugly iteration:

  • Add an iterator() method to ArraySet that returns an Iterator<T>.
  • The Iterator<T> that we return should have a useful hasNext() and next() method.

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() { wizPos = 0; }

public boolean hasNext() { return wizPos < size; }

public T next() {

T returnItem = items[wizPos];

wizPos += 1;

return returnItem;

}

}

public Iterator<T> iterator() {

return new ArraySetIterator();

}

48 of 98

Iterable

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

49 of 98

The Enhanced For Loop

Our code now supports “ugly” iteration, but enhanced for loop still doesn’t work.

The problem: Java isn’t smart enough to realize that our ArraySet has an iterator() method.

  • Luckily there’s an interface for that.

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

for (int i : aset) {

System.out.println(i);

}

$ javac IterationDemo

error: for-each not applicable to expression type

for (int i : aset) {

^

required: array or java.lang.Iterable

found: ArraySet<Integer>

50 of 98

For-each Iteration And ArraySets

To support the enhanced for loop, we need to make ArraySet implement the Iterable interface.

  • There are also some default methods in Iterable, not shown.

public class ArraySet<T> implements Iterable<T> {

...

public Iterator<T> iterator() { ... }

}

public interface Iterable<T> {

Iterator<T> iterator();

}

ArraySet<T>

Iterable<T>

51 of 98

Coding Demo: Iteration

public class ArraySet<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

T returnItem = items[wizPos];

wizPos += 1;

return returnItem;

}

}

}

ArraySet.java

52 of 98

Coding Demo: Iteration

public class ArraySet<T> implements Iterable<T> {

/** returns an iterator (a.k.a. seer) into ME */

public Iterator<T> iterator() {

return new ArraySetIterator();

}

private class ArraySetIterator implements Iterator<T> {

private int wizPos;

public ArraySetIterator() {

wizPos = 0;

}

public boolean hasNext() {

return wizPos < size;

}

public T next() {

T returnItem = items[wizPos];

wizPos += 1;

return returnItem;

}

}

}

ArraySet.java

53 of 98

The Iterable Interface

By the way, this is how Set works as well.

  • Source code for Iterable: Link, Set: Link, Collection: Link.

public interface Collection<E> extends Iterable<E> {

public Iterator<E> iterator();

}

public interface Iterable<T> {

Iterator<T> iterator(); ...

}

public interface Set<E> extends Collection<E> {

public Iterator<E> iterator();

}

Set<E>

Iterable<T>

Collection<E>

54 of 98

Iteration Summary

To support the enhanced for loop:

  • Add an iterator() method to your class that returns an Iterator<T>.
  • The Iterator<T> returned should have a useful hasNext() and next() method.
  • Add implements Iterable<T> to the line defining your class.

We’ll do this in the last part of project 1B.

55 of 98

Add a slide about autoboxing with an Integer vs. int example.

56 of 98

toString

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • toString
  • == vs. equals
  • Better toString (Bonus)
  • .of (Bonus)

57 of 98

Object Methods

All classes are hyponyms of Object.

  • String toString()
  • boolean equals(Object obj)
  • int hashCode()
  • Class<?> getClass()
  • protected Object clone()
  • protected void finalize()
  • void notify()
  • void notifyAll()
  • void wait()
  • void wait(long timeout)
  • void wait(long timeout, int nanos)

Won’t discuss or use in 61B.

Today

Coming later.

58 of 98

toString()

The toString() method provides a string representation of an object.

  • System.out.println(Object x) calls x.toString()
    • If you’re curious: println calls String.valueOf which calls toString

Set<Integer> javaset = new HashSet<>();

javaset.add(5);

javaset.add(23);

javaset.add(42);

System.out.println(javaset);

$ java JavaSetPrintDemo

[5, 23, 42]

59 of 98

toString()

The toString() method provides a string representation of an object.

  • System.out.println(Object x) calls x.toString()
  • The implementation of toString() in Object is the the name of the class, then an @ sign, then the memory location of the object.
    • See 61C for what the “memory location” really means.

$ java ArraySetPrintDemo

ArraySet@75412c2f

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

System.out.println(aset);

60 of 98

ArraySet toString

Let’s try implementing toString for ArraySet.

61 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

public String toString() {

}

}

ArraySet.java

62 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

}

}

ArraySet.java

63 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

}

}

ArraySet.java

64 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

for (T item : this) {

}

}

}

ArraySet.java

65 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

for (T item : this) {

returnString += item.toString();

}

}

}

ArraySet.java

66 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

for (T item : this) {

returnString += item.toString();

returnString += ", ";

}

}

}

ArraySet.java

67 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

for (T item : this) {

returnString += item.toString();

returnString += ", ";

}

returnString += "}";

}

}

ArraySet.java

68 of 98

Coding Demo: toString

public class ArraySet<T> implements Iterable<T> {

@Override

public String toString() {

String returnString = "{";

for (T item : this) {

returnString += item.toString();

returnString += ", ";

}

returnString += "}";

return returnString;

}

}

ArraySet.java

69 of 98

ArraySet toString

One approach is shown below.

  • Warning: This code is slow. Intuition: Adding even a single character to a string creates an entirely new string. Will discuss why at end of course.

@Override

public String toString() {

String returnString = "{";

for (int i = 0; i < size; i += 1) {

returnString += keys[i];

returnString += ", ";

}

returnString += "}";

return returnString;

}

Spoiler: It’s because Strings are “immutable”.

keys[i] might not be a string, but Java will automatically call toString so that you can add it to a string.

You can modify this code to avoid the extra comma at the end, if you want.

70 of 98

ArraySet toString

Much faster approach is shown below.

  • Intuition: Append operation for a StringBuilder is fast.
  • See the videos for more details about StringBuilder.

@Override

public String toString() {

StringBuilder returnSB = new StringBuilder("{");

for (int i = 0; i < size; i += 1) {

returnSB.append(items[i]);

returnSB.append(", ");

}

returnSB.append("}");

return returnSB.toString();

}

71 of 98

== vs. equals

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • toString
  • == vs. equals
  • Better toString (Bonus)
  • .of (Bonus)

72 of 98

Object Methods

All classes are hyponyms of Object.

  • String toString()
  • boolean equals(Object obj)
  • int hashCode()
  • Class<?> getClass()
  • protected Object clone()
  • protected void finalize()
  • void notify()
  • void notifyAll()
  • void wait()
  • void wait(long timeout)
  • void wait(long timeout, int nanos)

Won’t discuss or use in 61B.

Coming in another lecture soon.

Coming later.

73 of 98

Equals vs. ==

As mentioned in an offhand manner previously, == and .equals() behave differently.

  • == compares the bits. For references, == means “referencing the same object.”

Set<Integer> javaset = Set.of(5, 23, 42);

Set<Integer> javaset2 = Set.of(5, 23, 42);

System.out.println(javaset == javaset2);

$ java EqualsDemo

False

74 of 98

Equals vs. ==

As mentioned in an offhand manner previously, == and .equals() behave differently.

  • == compares the bits. For references, == means “referencing the same object.”

To test equality in the sense we usually mean it, use:

  • .equals for classes. Requires writing a .equals method for your classes.
    • Default implementation of .equals uses == (probably not what you want).
  • BTW: Use Arrays.equal or Arrays.deepEquals for arrays.

Set<Integer> javaset = Set.of(5, 23, 42);

Set<Integer> javaset2 = Set.of(5, 23, 42);

System.out.println(javaset.equals(javaset2));

$ java EqualsDemo

True

75 of 98

this: Address of Current Object

this is a reference to the current object. Example from lecture 2:

public Dog maxDog(Dog uddaDog) {

if (size > uddaDog.size) {

return this;

}

return uddaDog;

}

76 of 98

this: Address of Current Object

Naturally, can also use this to access your own instance variables or methods.

  • Unlike Python, where self is mandatory, using this is not mandatory.
  • Two code snippets below are exactly identical in behavior.

public Dog maxDog(Dog o) {

if (size > o.size) {

return this;

}

return o;

}

public Dog maxDog(Dog o) {

if (this.size > o.size) {

return this;

}

return o;

}

77 of 98

this

Naturally, can also use this to access your own instance variables or methods.

  • Unlike Python, where self is mandatory, using this is not mandatory.
  • If there’s ever a name conflict where a local variable has the same name as an instance variable (left), you must use this if you want to access the instance variable.

public Dog(int s) {

this.size = s;

}

public Dog(int size) {

this.size = size;

}

public Dog(int s) {

size = s;

}

public Dog(int size) {

size = size;

}

Does nothing!

Works correctly!

Works correctly!

Works correctly!

78 of 98

The Default Implementation of Equals

Below, we see the actual code for the default equals method in Object.java.

public class Object {

...

public boolean equals(Object obj) {

return (this == obj);

}

}

79 of 98

The Default Implementation of Equals

ArraySet<Integer> aset = new ArraySet<>();

aset.add(5);

aset.add(23);

aset.add(42);

System.out.println(aset);

ArraySet<Integer> aset2 = new ArraySet<>();

aset2.add(5);

aset2.add(23);

aset2.add(42);

System.out.println(aset.equals(aset2));

$ java EqualsDemo

False

Returns false because the default implementation of equals just uses ==.

80 of 98

instanceOf Demo (for hypothetical Dog equals method)

The instanceof keyword is very powerful in Java.

  • Checks to see if o is pointing at a Dog.�If no, returns false.
  • If yes, returns true and puts o in a new variable of type Dog called uddaDog.
  • Works correctly, even if o is null.

Let’s try to write ArraySet’s equals method.

@Override

public boolean equals(Object o) {

if (o instanceof Dog uddaDog) {

return this.size == uddaDog.size;

}

return false;

}

81 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

public boolean equals(ArraySet o) {

}

}

ArraySet.java

82 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(ArraySet o) {

}

}

ArraySet.java

Compiler error. Not actually overriding the equals method in the Object class.

83 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

}

}

ArraySet.java

84 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

}

}

}

ArraySet.java

85 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

86 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

// check sets are of the same size

if (oas.size != this.size) {

return false;

}

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

87 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

// check sets are of the same size

if (oas.size != this.size) {

return false;

}

// check that all of MY items are in the other array set

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

88 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

// check sets are of the same size

if (oas.size != this.size) {

return false;

}

// check that all of MY items are in the other array set

for (T x : this) {

}

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

89 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

// check sets are of the same size

if (oas.size != this.size) {

return false;

}

// check that all of MY items are in the other array set

for (T x : this) {

if (!oas.contains(x)) {

return false;

}

}

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

90 of 98

Coding Demo: equals

public class ArraySet<T> implements Iterable<T> {

@Override

public boolean equals(Object o) {

if (o instanceof ArraySet oas) {

// check sets are of the same size

if (oas.size != this.size) {

return false;

}

// check that all of MY items are in the other array set

for (T x : this) {

if (!oas.contains(x)) {

return false;

}

}

return true;

}

// o is not an arrayset, so return false

return false;

}

}

ArraySet.java

91 of 98

ArraySet equals

The code below is pretty close to what a standard equals method looks like.

@Override

public boolean equals(Object other) {

if (this == other) { return true; }

if (other instanceof ArraySet otherSet) {

if (this.size != otherSet.size) { return false; }

for (T x : this) {

if (!otherSet.contains(x)) {

return false;

}

}

return true;

}

return false;

}

Technically a raw type without a type placeholder like ArraySet<T>, but don't worry about it.

92 of 98

ArraySet equals

The code below is pretty close to what a standard equals method looks like.

@Override

public boolean equals(Object other) {

if (this == other) { return true; }

if (other instanceof ArraySet otherSet) {

if (this.size != otherSet.size) { return false; }

for (T x : this) {

if (!otherSet.contains(x)) {

return false;

}

}

return true;

}

return false;

}

Doesn't affect correctness, but saves us time if this and other reference the same object.

93 of 98

Historical Note: Old School Equals Methods

Equals methods written before March 2021 were ugly.

  • Lots of manual type checking, “casting”, and null checking.
  • See the CS61B 2021 slides.
  • You should avoid the old way (explicit casting).

@Override // OLD SCHOOL APPROACH. NOT PREFERRED IN 61B.

public boolean equals(Object o) {

if (o == null) { return false; }

if (this == o) { return true; } // optimization

if (this.getClass() != o.getClass()) { return false; }

ArraySet<T> other = (ArraySet<T>) o;

...

}

94 of 98

Summary

We built our own Array based Set implementation.

To make it more industrial strength we:

  • Added an exception if a user tried to add null to the set. (See videos.)
    • There are other ways to deal with nulls. Our choice was arguably bad.
  • Added support for “ugly” then “nice” iteration.
    • Ugly iteration: Creating a subclass with next and hasNext methods.
    • Nice iteration: Declaring that ArraySet implements Iterable.
  • Added a toString() method.
    • Beware of String concatenation.
  • Added an equals(Object) method.
    • Used instanceof to check the class of the passed object.�

95 of 98

Better toString (Bonus)

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

96 of 98

The Lazy Way

Can use the String.join method to convert list of strings into a single string.

@Override

public String toString() {

List<String> listOfItems = new ArrayList<>();

for (T x : this) {

listOfItems.add(x.toString());

}

return "{" + String.join(", ", listOfItems) + "}";

}

97 of 98

ArraySet.of (Bonus)

Lecture 10, CS61B, Fall 2024

Today’s Goal: ArraySet

Iteration

  • The Enhanced For Loop
  • iterator, next, hasNext
  • iterator, next, hasNext for ArraySet
  • Iterable

Object Methods

  • == vs. equals
  • toString
  • Better toString (Bonus)
  • .of (Bonus)

98 of 98

The of Method

We can write our own of method as follows:

  • Below stuff is a so-called “var arg”.
    • Object passed is an array.
    • Values filled out using comma separated syntax.

public static <Glerp> ArraySet<Glerp> of(Glerp... stuff) {

ArraySet<Glerp> returnSet = new ArraySet<Glerp>();

for (Glerp x : stuff) {

returnSet.add(x);

}

return returnSet;

}