diff --git a/Makefile b/Makefile index 4d81dd08ae6f3e4d6cdbe6457f016e3e42058358..1ba44acdcb2435c1a07de62463e80b736fb7f675 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ pdfs = $(foreach f,$(wildcard $(1)/*.md),$(patsubst %.md,%.pdf,$(f))) MODEL_PARALLELOGRAM = $(call graphs,$(foreach i,0 1 2 3,parallelogram$(i))) INHERITANCE_GRAPHS = $(call graphs,classesTree exceptionsTree) +IMPLEMENTATION_GRAPHS = $(call graphs,arrayList implementations linkedList newCellArrayList newCellLinkedList) SLIDES = $(call pdfs,Slides) WORKSHEET = $(call pdfs,Worksheet) @@ -16,6 +17,7 @@ Course.pdf: Course.md $(MODEL_PARALLELOGRAM) Slides/Class1.pdf: $(MODEL_PARALLELOGRAM) figures/helloworld.tex Slides/Class3.pdf: $(INHERITANCE_GRAPHS) +Slides/Class4.pdf: $(IMPLEMENTATION_GRAPHS) Slides/%.pdf: Slides/%.md pandoc --toc --slide-level=3 -t beamer $< -o $@ diff --git a/Slides/Class4.md b/Slides/Class4.md index 0f0f3aeb518e34a1e4c32dbd90fa8c6685654ee1..289d8f1d37c3a4ede4453870481393ba3814c7e7 100644 --- a/Slides/Class4.md +++ b/Slides/Class4.md @@ -436,20 +436,205 @@ for(int i = 0; i < newArray.length; i++) { ## Simple containers +### Implementing interfaces + +{height=80px} + +One interface, several implementations. + ### Two implementations -### Appending +#### List + +- a set of functionalities +- a contract to prove a class can act as a list + +:::columns +::::column + +#### ArrayList + +\vspace{0.5cm} + + + +- an array larger than the number of elements +- an index to remember where it stops + +:::: +::::column + +#### LinkedList + +\vspace{0.5cm} + + + +- a "head": the element in the current cell +- a "queue": the pointer to the rest of the list + +:::: +::: + +### Getting element at index `i` + +:::columns +::::column + +#### ArrayList + +\vspace{0.5cm} + +- check the bounds: $O(1)$ +- return cell `i`: $O(1)$ + +$\Rightarrow O(1)$ + +:::: +::::column + +#### LinkedList + +\vspace{0.5cm} + +does `i == 0 ` ? + +- if yes, get the head: +- otherwise, get the `i-1`\textsuperscript{th} element of the queue + +$\Rightarrow O(n)$ + +:::: +::: + +### Prepending + +:::columns +::::column + +#### ArrayList + +\vspace{0.5cm} + + + +- create a new array large enough: $O(n)$ +- write the new element: $O(1)$ +- copy all the other elements after: $O(n)$ + +$\Rightarrow O(n)$ + +:::: +::::column + +#### LinkedList + +\vspace{0.5cm} + + + +- create a new cell with the new element pointing to the existing list: $O(1)$ + +$\Rightarrow O(1)$ + +:::: +::: + +### Performance comparison + +**So which one is best ?** + +- if frequent random access is needed: `ArrayList` +- if frequent modification is needed: `LinkedList` + +$\Rightarrow$ No "one-size-fits-all", implementation should match the use + +## Associating values to keys + +### A common need + +- "white pages", phone books… +- Domain Name System +- looking up users in a table by their ID +- retrieving + +```Java +interface Map<K, V> { + … + V get(Object k); +} +``` + +### Association list + +:::columns +::::column + +```Java +class Pair<K, V> { + … +} +``` + +:::: +::::column + +```Java +class ArrayList<T> { + … +} +``` + +:::: +::: + +\begin{center} +$\downarrow$ +\end{center} -### Growing +```Java +class PhoneBook<K, V> { + private ArrayList<Pair<K, V>> records; + PhoneBook (int initialSize) { + this.records = new ArrayList<>(initialSize); + } +} +``` -## Associating values to values +### Retrieving a number from a key -### Pairs list +```Java +… +V get(Object k) { + for(Pair<K, V> record: this.records) { + if(record.getKey().equals(k)) { + return record.getValue(); + } + } + return null; +} +``` -**Need:** +- must walk the phonebook until found +- on average, `this.records.size() / 2` +- $\Rightarrow O(n)$ ### HashMaps +#### A clever implementation + +- uses `.hashCode()` on the key: $O(1)$ +- keeps a separate association list for each hash value +- each list as long as the number of collisions (if `.hashCode` is good, then + few): $O(c)$ +- (see birthday problem) + +#### Consequences + +- fast access +- fast insertion +- resizing costs when it gets too full (initial capacity / load factor) + :::columns ::::column :::: diff --git a/graphs/arrayList.gv b/graphs/arrayList.gv new file mode 100644 index 0000000000000000000000000000000000000000..f568935c54ca327656dedba9122b3907ff43b57a --- /dev/null +++ b/graphs/arrayList.gv @@ -0,0 +1,3 @@ +digraph arrayList { + Array [ shape="record", label="Cell0|Cell1|Cell2|(empty)|(empty)" ]; +} diff --git a/graphs/implementations.gv b/graphs/implementations.gv new file mode 100644 index 0000000000000000000000000000000000000000..9b0bedad0b99778dbc3314e498feb756629d443b --- /dev/null +++ b/graphs/implementations.gv @@ -0,0 +1,7 @@ +digraph implementations { + rankdir=BT; + Interface [shape="square"]; + Implementation1 -> Interface; + Implementation2 -> Interface; + Implementation3 -> Interface; +} diff --git a/graphs/linkedList.gv b/graphs/linkedList.gv new file mode 100644 index 0000000000000000000000000000000000000000..b0fe0bc0afe5996714d0dadb93ffd63af0b06d8c --- /dev/null +++ b/graphs/linkedList.gv @@ -0,0 +1,5 @@ +digraph linkedList { + rankdir=LR; + Cell0 -> Cell1; + Cell1 -> Cell2; +} diff --git a/graphs/newCellArrayList.gv b/graphs/newCellArrayList.gv new file mode 100644 index 0000000000000000000000000000000000000000..2a334b622a9f1549adda38339ad6ab4de0504421 --- /dev/null +++ b/graphs/newCellArrayList.gv @@ -0,0 +1,6 @@ +digraph newCellArrayList { + rankdir="LR"; + New [label="New cell", shape="square"]; + Array [ shape="record", label="{Cell0|Cell1|Cell2|(empty)|(empty)}" ]; + New -> Array [style="dashed"]; +} diff --git a/graphs/newCellLinkedList.gv b/graphs/newCellLinkedList.gv new file mode 100644 index 0000000000000000000000000000000000000000..3b576d389f6b25530b07df0424990fc208fcd193 --- /dev/null +++ b/graphs/newCellLinkedList.gv @@ -0,0 +1,7 @@ +digraph linkedList { + rankdir=LR; + New [label="New cell"]; + New -> Cell0 [style="dashed"]; + Cell0 -> Cell1; + Cell1 -> Cell2; +}