COMP2511
Tutorial 8
Today
- Reminders
- Iterator pattern
- Generic Programming
- Concurrency
- Singleton Pattern
Reminders
- Assignment 2 is due on Friday Week 9 at 5pm
-
No lab marking in week 10
- Please ensure all your labs are marked by week 9
-
Sample exam with the sample environment during week 10 lab
- Highly recommend familiarising with the exam layout and environment
- Tutorial 10 is still on
Iterator Pattern
Iterator Pattern
Suppose:
- We have been given a
Graphclass used to model a collection of interconnected nodes - We can't access the implementation of the
Graphclass because- It will break encapsulation
- Given an instance of the
Graph, one possible use case is traverse it using breadth-first search - Iterator pattern allow clients to traverse the graph in a way without exposing the underlying implementation
Iterator Pattern
In Java:
-
Iterator<E>is an interface containing two methods to implement-
hasNext(): returns true if there are elements left to traverse through -
next(): move the iterator to the next element and return the element - Akin to a "pointer" sitting somewhere in the collection
-
-
Iterable<E>is an interface containing one method to implement- iterator(): returns an iterator of type Iterator<E>
-
Since ArrayList<E>implementsIterable<E>, callingiterator()on an instance will return an iterator to the front of the instance
-
- Classes that implement the interface can be iterated through using
for-range
- iterator(): returns an iterator of type Iterator<E>
List<Integer> myList = new ArrayList<>(List.of(1, 2, 3));
for (Integer x : myList) {
System.out.println(x);
}Iterator Pattern

public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
g
Iterator Pattern

public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}Iterator Pattern

public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}Iterator Pattern

public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}Iterator Pattern

public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}Iterator Pattern

public static void main(String[] args) {
Graph<Integer> g = new Graph<>();
... fill g with vertices and edges ...
Iterator<Integer> it = g.iterator();
Integer src = it.next();
while (it.hasNext()) {
System.out.println(it.next());
}
for (Integer x : g) {
System.out.println(x);
}
}
public class Graph<T> implements Iterable<T> {
... hidden data structures for the graph ...
... attributes and methods ...
public Iterator<T> iterator() {
returns iterator to "before" the
source node of the graph
}
}Generic Programming
Generic Programming
Style of programming that allow types to be used as parameters when defining methods, classes and interfaces
- Implement code once and it will work for a collection of different types
-
List<T>is parameterised by a type parameterT - This means
Tcan be substituted with any type likeInteger,String, etc
-
- Offer strong type checking at compile time
- Adding a S
tringinto anArrayList<Integer>will not compile
- Adding a S
List<Integer> myList = new ArrayList<>();
myList.add(42); // will work
myList.add("Hello world"); // will not compileWhat is it?
Why should you use it?
Generic Programming
public class Box<T, S> {
private T value1;
private S value2;
public Box(T v1, S v2) {
this.value1 = value1;
this.value2 = value2;
}
public void setValue(T v1, S v2) {
this.value1 = v2;
this.value2 = v2;
}
public T getValue1() {
return value1;
}
public S getValue2() {
return value2;
}
}
Basic Syntax
- The generic type parameters
TandSare placeholders for any arbitrary types - Each instance of a
Boxis
parameterised by 2 arbitrary typesTandS -
TandScan now be referred to within the definition of the class- Type of member variables
- Type of arguments for methods
- Return type of methods
Generic Programming
Inside src/stack, there are a series of stubs for a Stack class which takes in a generic type. There are a series of tests inside StackTest.java which currently fail
Implement the methods so that the tests pass, using an ArrayList to store the internal data structure
Generic Programming
public static Integer sumStack(Stack<? extends Integer> stack);
-
What does
<? extends T>and<? super T>mean?- Extends: parameterised type must be
Tor subclass ofT - Super: parameterised type must be
Tor superclass ofT
- Extends: parameterised type must be
-
What is the difference between
?andE?-
?cannot be used as the type of a local variable (wildcard)
-
Concurrency
Concurrency
Threads

- Sequence of instructions that the CPU can choose to execute at any given time (unpredictable)
- Different threads can be scheduled very closely to each other to give the illusion that they are running at the same time
Concurrency
Threads
Benefit:
- Generally improves the performance of a program
- Restaurants with only one employee acting as both the chef and the waiter will be less efficient than restaurants with dedicated chefs and waiters
Limitation:
- Multithreaded code is generally more difficult to reason about and implement correctly
Concurrency

Suppose Jim and Bo (threads) are accessing their shared bank account at the "same" time (transaction could be microseconds apart)
Concurrency
A person must read the current balance before depositing / withdrawing money from the account

Jim and Bo both see $20 in the bank account
Concurrency
So far so good!

Bo withdraws $10 from the account
Concurrency

Jim saw $20 in the bank account so he rightly withdraws $15
Uh..oh but we only had $20 to begin with :(
Concurrency
This is a very common problem when implementing multithread code known as a race condition
- Occurs when two or more threads attempt to read and write to a shared value at the "same" time
- Outcome is non-deterministic and dependent on the order in which threads are scheduled on the CPU

Concurrency
Solution: synchronise code that may read and write to a shared value

Idea is explored in more depth in COMP3231
Enforce that a read + (withdraw / deposit) must be completed before the next can begin
Singleton Pattern
Singleton Pattern
Creational design pattern that specifies that
- A class can only have one active instance
- Accessing the instance must be through a global access point
- Control access to some shared resource
- i.e. bank, database connection, etc
- Avoid initialisation overhead when only 1 copy of an instance is required
What is this?
Why use it?
Singleton Pattern

- The class holds a static instance of itself via composition
- All constructors are private to prevent arbitrary instances from being created
- Accessing the instance must be through the static method
getInstance - Class is only instantiated once when the
getInstanceis called for the first time
UML Diagram
Singleton Pattern

Let's refactor the code
- Change the system to use the singleton pattern
- Incorporate the Java synchronisation primitive to eliminate data races
The End
COMP2511 Tutorial 8
By matthewliu-2
COMP2511 Tutorial 8
- 94