1 of 59

Announcements

This is the last lecture specifically devoted to Java syntax.

  • Starting Wednesday we’ll enter Phase 2: Data Structures!

Once you’ve digested this lecture you’ll know everything you need for project 1C.

2 of 59

Announcements

The new textbook is up.

  • Chapter summary (example) replaces the previous “study guides”.
  • The textbook will very closely follow lecture videos.
  • Thanks to Sherry Fan for leading the charge.

If you notice any accessibility concerns in this videos, the textbook, or other course materials, please email cs61b@berkeley.edu ASAP and we’ll get it taken care of.

3 of 59

Announcements

Bargaining begins today regarding a side letter about EECS/Data courses staffing. You're all welcome to attend or listen in. Me and DeNero will be there.

When: 3:10pm-5pm Monday, Feb 13

Where: 310 Soda Hall

Zoom: https://berkeley.zoom.us/j/95216694463

You can expect that we'll debrief about the town hall (recording), review the data release, discuss issues DeNero raised in my video about course staffing, and hopefully come up with a shared plan for how to make progress on the concerns raised in the town hall (which include course access in addition to staffing shortages).

4 of 59

The End of Java

4

Lecture 12

CS61B, Spring 2023 @ UC Berkeley

Josh Hug and Justin Yokota

5 of 59

Today’s Goal: ArraySet

Lecture 12, CS61B, Spring 2023

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)

6 of 59

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, comparison, and toString.

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

S.add("Tokyo");

S.add("Beijing");

S.add("Lagos");

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

S.add("São Paulo");

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

s = set()

s.add("Tokyo")

s.add("Beijing")

s.add("Lagos")

s.add("Tokyo") # no effect

s.add("São Paulo")

print("Tokyo" in s)

$ java SetExample

true

$ python set_example.py

True

7 of 59

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.

8 of 59

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.

9 of 59

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.

10 of 59

The Enhanced For Loop

Lecture 12, CS61B, Spring 2023

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)

11 of 59

The Enhanced For Loop

Java allows us to iterate through Lists and Sets using a convenient shorthand syntax sometimes called the “foreach” 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);

}

12 of 59

The Enhanced For Loop

Java allows us to iterate through Lists and Sets using a convenient shorthand syntax sometimes called the “foreach” 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 : S) {

^

required: array or java.lang.Iterable

found: ArraySet<Integer>

13 of 59

iterator, next, hasNext

Lecture 12, CS61B, Spring 2023

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)

14 of 59

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?

15 of 59

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.

for (int x : javaset) {

System.out.println(x);

}

public Iterator<E> iterator();

Set.java:

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

int x = seer.next();

System.out.println(x);

}

“Nice” iteration.

“Ugly” iteration.

16 of 59

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:

17 of 59

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

}

18 of 59

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

}

19 of 59

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

}

20 of 59

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

}

21 of 59

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

}

22 of 59

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

23

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

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

}

23 of 59

How Iterators Work

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

5

23

42

javaset:

42

$ java IteratorDemo.java

5

23

42

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

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

}

24 of 59

How Iterators Work

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

5

23

42

javaset:

False

$ java IteratorDemo.java

5

23

42

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

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

}

25 of 59

iterator, next, hasNext for ArraySet

Lecture 12, CS61B, Spring 2023

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)

26 of 59

The Secret of the Enhanced For Loop yellkey.com/may

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?

for (int x : javaset) {

System.out.println(x);

}

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

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

}

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

27 of 59

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?

for (int x : javaset) {

System.out.println(x);

}

Iterator<Integer> seer

= javaset.iterator();

while (seer.hasNext()) {

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

}

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

28 of 59

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

}

29 of 59

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

}

30 of 59

Iterable

Lecture 12, CS61B, Spring 2023

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)

31 of 59

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

...

}

$ javac IterationDemo

error: for-each not applicable to expression type

for (int i : aset) {

^

required: array or java.lang.Iterable

found: ArraySet<Integer>

32 of 59

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 interface Iterable<T> {

Iterator<T> iterator();

}

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

...

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

}

ArraySet<T>

Iterable<T>

33 of 59

The Iterable Interface

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

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

Set<E>

Iterable<T>

public interface Iterable<T> {

Iterator<T> iterator(); ...

}

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

public Iterator<E> iterator();

}

Collection<E>

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

public Iterator<E> iterator();

}

34 of 59

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 project 1C.

35 of 59

toString

Lecture 12, CS61B, Spring 2023

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)

36 of 59

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.

37 of 59

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]

38 of 59

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.

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

aset.add(5);

aset.add(23);

aset.add(42);

System.out.println(aset);

$ java ArraySetPrintDemo

ArraySet@75412c2f

39 of 59

ArraySet toString

Let’s try implementing toString for ArraySet.

40 of 59

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

41 of 59

ArraySet toString

Much faster approach is shown below.

  • Intuition: Append operation for a StringBuilder is fast.

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

}

42 of 59

== vs. equals

Lecture 12, CS61B, Spring 2023

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)

43 of 59

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.

44 of 59

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

45 of 59

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

46 of 59

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;

}

47 of 59

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 (this.size > o.size) {

return this;

}

return o;

}

public Dog maxDog(Dog o) {

if (size > o.size) {

return this;

}

return o;

}

48 of 59

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 size) {

this.size = size;

}

public Dog(int s) {

size = s;

}

public Dog(int s) {

this.size = s;

}

public Dog(int size) {

size = size;

}

Does nothing!

Works correctly!

Works correctly!

Works correctly!

49 of 59

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

}

}

50 of 59

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

51 of 59

instanceOf Demo

The instanceof keyword is very powerful in Java.

  • Checks to see if o’s dynamic type is Dog (or one of its subtypes).
  • Casts o into a variable of static type Dog called uddaDog.
  • Works correctly, even if o is null.
  • Note: 61B TAs just learned this syntax this semester (new Java feature).

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;

}

52 of 59

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;

}

53 of 59

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.
  • Some of TAs and AIs were taught this old way. You should avoid the old way (explicit casting), but I prefer the new instanceof way.

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

}

54 of 59

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.
    • 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.
    • Make sure to deal with null and non-ArraySet arguments!
    • Used getClass to check the class of the passed object. Use sparingly.�

55 of 59

Better toString (Bonus)

Lecture 12, CS61B, Spring 2023

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)

56 of 59

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) + "}";

}

57 of 59

ArraySet.of (Bonus)

Lecture 12, CS61B, Spring 2023

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)

58 of 59

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;

}

59 of 59

Citations