-
Alice Brenon authored9f2815aa
- Advanced Objects
- Enumerations
- Need
- String ?
- A possible solution
- The enum types
- Advanced example
- Type variables
- Remember containers ?
- Methods signatures
- An "input"
- Generics
- May appear
- in classes
- in methods
- Wildcards
- Remark
- Bounds
- extends
- super
- Useful with interfaces
- Example
- A little bit of functional programming why not ?
- Functional interfaces
- A key distinction
- Regular values
- Functions
- But what if we want to…
- Interfaces !
- Representing a function
- Lambda expressions
- Concept
- From the \textlambda-calculus
- Syntax
- Literal values
- Method reference
- Example
- Use cases
- "Canned computations"
- Higher-order operations
- Complexity
- Simple containers
- Implementing interfaces
- Two implementations
- List
- ArrayList
- LinkedList
- Getting element at index i
- ArrayList
- LinkedList
- Prepending
- ArrayList
- LinkedList
- Performance comparison
- Associating values to keys
- A common need
- Association list
- Retrieving a number from a key
- HashMaps
- A clever implementation
- Consequences
title: IST-4-JAV Java Programming
subtitle: Class 4 - New heights
author: Alice BRENON `<alice.brenon@liris.cnrs.fr>`
date: 2021-10-19
header-includes:
\usepackage{fdsymbol}
\usepackage{textgreek}
\usepackage{bclogo}
\usepackage{hyperref}
\usepackage{color}
\definecolor{yellow}{RGB}{255, 127, 0}
\definecolor{greyblue}{RGB}{58, 103, 183}
\hypersetup{
colorlinks,
linkcolor = yellow,
urlcolor = greyblue
}
\usetheme{Frankfurt}
\usecolortheme{seahorse}
Advanced Objects
Enumerations
Need
class PureBreedCat extends DomesticCat {
String breed;
…
}
String
?
- for user: what are the possible values ?
- possible errors (case, typos…)
- need to validate input
- (\Rightarrow what to do with unexpected values ?)
\Rightarrow type too "large"
A possible solution
:::columns ::::{.column width=40%}
need a finite number of values that are
- unique
- easy to compare
- associated to names
\Rightarrow constants of any integral type will do !
:::: ::::{.column width=60%}
final static byte SIAMESE = 0;
final static byte CHARTREUX = 1;
final static byte SAVANNAH = 2;
…
:::: :::
\vspace{0.5cm}
- 1 and 2 are fixed !
- 3 and 4 remain : (
enum
types
The - fixed set of symbolic constants
- introduced by
enum
instead ofclass
- names separated by
,
(ended by;
) - it's a class like any other ! (fields, methods)
enum CatBreed {
SIAMESE, CHARTREUX, SAVANNAH
}
CatBreed breed = CatBreed.SIAMESE;
breed == CatBreed.SAVANNAH; // false
Advanced example
- optional constructor can't be
public
- all values are constructed statically
- properties can be initialized
enum BreedType {
NATURAL, MUTATION, HYBRID
}
enum CatBreed {
SIAMESE (BreedType.MUTATION),
CHARTREUX (BreedType.NATURAL),
SAVANNAH (BreedType.HYBRID);
private BreedType type;
CatBreed (BreedType type) { this.type = type; }
BreedType getBreedType() { return this.type; }
}
Type variables
Remember containers ?
List<Integer>
List<Double>
List<String>
List<List<String>>
…
- a "family" of classes (infinite)
- work on any type
Methods signatures
List<Integer> ints = new ArrayList<>();
List<String> strings = new ArrayList<>();
for(int i = 0; i < 10; i++) {
ints.add(i);
strings.add(Integer.toString(i));
}
\rightarrow what is the signature of .add
?
An "input"
void add(Integer n) // ??
void add(String s) // ??
- type of their methods depend on the type context
- \rightarrow need to be named in the class declaration
- "input" of a class, like arguments are the inputs of a function
- type variables
Generics
- an identifier (any variable name)
- inside the "diamond"
<>
- usually a single letter:
-
N
\rightarrow "number" type -
K
\rightarrow "key" in an association -
V
\rightarrow "value" in an association -
T
\rightarrow any type
-
- multiple parameters are comma separated
<K, V>
May appear
in classes
class Box<T> {
…
}
in methods
as the last modifier, just before the return type
public <T> List<T> preview(List<T> full, int size);
Wildcards
- the "unknown type"
- no name \Rightarrow strictly less powerful (!)
- syntax:
?
Remark
-
List<Integer>
isn't a subtype ofList<Object>
- but it's a subtype of
List<?>
! - \Rightarrow allows to get supertypes !
Bounds
:::columns ::::column
extends
- any type that derives from the given type
- useful on covariant operations
- works for generic types
<? extends Integer>
:::: ::::column
super
- any type which the given type derives from
- useful on contravariant operations
- (only for wildcards ! not generics)
<? super Integer>
:::: :::
Useful with interfaces
- conditions on input types
- like variables: reusing the name in the same formula makes the types equal
- hypothesis used in the implementation
- can be combined with
&
:
<T extends Comparable & Number>
Example
sorting requires ordered elements:
<T extends Comparable<T>> List<T> sort(List<T> elems);
A little bit of functional programming why not ?
Functional interfaces
A key distinction
:::columns ::::{.column width=49%}
Regular values
- data: raw types, objects…
- can be created dynamically
- can be stored
- passed to functions
::::
::::{.column width=1%}
\rule{.1mm}{.4\textheight}
::::
::::{.column width=49%}
Functions
- structural unit
- (similar to loops)
- no dynamic handling
:::: :::
But what if we want to…
- store a function into a variable ?
- associate it to a key ? (menus…)
- pass it to another function ?
- use concurrency (threads) ?
boolean isEven(int n) {
return n % 2 == 0;
}
someList.filter(isEven); // Error: cannot find symbol
Interfaces !
- classes can have (several !) methods
- passing an object is a way to pass its methods
- only need a convention to find the method
\rightarrow it's called an interface !
interface MyFunctionType {
int run(List<Integer> primes);
}
Representing a function
- special case: interface with only one method to implement
- the class is a simple "wrapper" around it
- conventional name to find it
- (can have other methods but only 1 abstract)
\rightarrow it's called a functional interface !
Example
@FunctionalInterface
public interface Predicate<T> {
public boolean test(T t);
}
Lambda expressions
Concept
:::columns ::::column
From the \textlambda-calculus
- Alonzo Church (1930s)
- base of many languages: Lisp, Ocaml, Haskell…
- the set of terms T contain:
- atoms: constants C, variables V
- abstractions: \{\lambda x.t \ \forall v \in V, t \in T\}
- applications: \{(t\ u) \ \forall t, u \in T\}
:::: ::::column
- like functions (arguments mapped to a value)
- one-liner
- anonymous
\Rightarrow function literals
:::: :::
Syntax
assuming
-
(a, b, …)
is a tuple of n variables (parentheses optional when 1 only) -
e
is an expression -
b
is a block ending with areturn
statement
(a, b, …) -> e
(a, b, …) -> { b }
are values for a given functional interface
Example
(n, m) -> n+m
x -> {System.out.println(x); return -x;}
Literal values
What about their types ?
- no "arrow" types in Java so can't really be written "
int -> String
" - the
@FunctionalInterface
are perfect for the job ! - (mind the conceptual gap)
@FunctionalInterface
public interface Endofunction<T> {
T apply(T t);
}
Endofunction<Integer> succ = n -> n+1;
Method reference
- what about existing functions ?
- (can be wrapped into a \textlambda, but boring:
n -> someObject.someMethod(n)
- can't handle regular functions except to apply them
- but you can refer to a method with
::
Example
class PartialSum {
private int firstNumber;
PartialSum (int initialValue) {
this.firstNumber = initialValue;
}
public int plus(int secondNumber) {
return this.firstNumber + secondNumber;
}
}
PartialSum two = new PartialSum(2);
Endofunction<Integer> add2 = two::plus;
Use cases
"Canned computations"
- multi-threading (computations in parallel):
Thread
- asynchronous computations:
Future<T>
- (all implement
Runnable
)
Higher-order operations
- no variables, lighter to read
- "add seven to all the elements in this array"
int[] newArray = new int[initialArray.length];
for(int i = 0; i < newArray.length; i++) {
newArray[i] = initialArray[i] + 7;
}
- map, reduce, iter…
Complexity
Simple containers
Implementing interfaces
One interface, several implementations.
Two implementations
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
:::: :::
i
Getting element at index :::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
- finding the selected action in a menu
interface Map<K, V> {
…
V get(Object k);
}
Association list
:::columns ::::column
class Pair<K, V> {
…
}
:::: ::::column
class ArrayList<T> {
…
}
:::: :::
\begin{center} \downarrow \end{center}
class PhoneBook<K, V> {
private ArrayList<Pair<K, V>> records;
PhoneBook (int initialSize) {
this.records = new ArrayList<>(initialSize);
}
}
Retrieving a number from a key
…
V get(Object k) {
for(Pair<K, V> record: this.records) {
if(record.getKey().equals(k)) {
return record.getValue();
}
}
return null;
}
- 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)