Programming concepts
1. Programming Concept
1.1. List and pointers
1.2. Abstract data type
1.3. Costruzione ed analisi di una classe Java per l'implementazione delle operazioni su una lista
lineare realizzata mediante array
1.3.1. Inserimento in testa, in coda, in un punto intermedio della lista; cancellazione di un
elemento
1.3.2. Confronto con java.util.ArrayList
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
1.3.3. Problema del dimensionamento dinamico dell'array sottostante alla lista
1.4. Costruzione ed analisi di una classe Java per l'implementazione delle operazioni su una lista
concatenata realizzata mediante allocazione dinamica dei nodi
LinkedListVsLinearListStudent.pdf
1.4.1. Inserimento in testa, in coda, in un punto intermedio della lista; cancellazione di un
elemento
1.4.2. Confronto con java.util.LinkedList
https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html
1.4.3. Ripasso sull’uso di Javadoc
(http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html e
http://stackoverflow.com/questions/8493352/how-to-make-documentation-withnetbeans-and-javadoc )
1.4.4. Creazione di una libreria e uso di una libreria in un progetto NetBeans:
https://netbeans.org/kb/docs/java/javase-intro.html
1.4.5. Deployment di applicazioni mediante file compressi jar:
https://netbeans.org/kb/articles/javase-deploy.html
Esercitazione 1: costruire il package it.cognome.ADT con le classi MyArrayList e MyLinkedList
che implementano l’interfaccia MyList. In particolare la classe MyArrayList implementa anche i
metodi privati squeeze() e enlarge() per la gestione della dimensione dell’array. Creare anche la
documentazione in formato Javadoc e creare un file di libreria in formato jar.
1.4.6. Ripasso sull’uso delle eccezioni:
http://www.tutorialspoint.com/java/java_exceptions.htm
http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
1.4.7. La classe Object (rivisitata)
Object as Superclass.pdf
https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html
Clonazione di oggetti
Uguaglianza tra oggetti
Hashcode di oggetti
Materiali: Object as Superclass.pdf
Esercitazione 2: Scrivere la classe:
public class Persona implements Cloneable {
private String nome;
private String cognome;
private Date dataN;
…
Con i metodi
@Override
public String toString() {…
@Override
public int hashCode() {…
@Override
public boolean equals(Object o) {…
@Override
public Object clone() throws CloneNotSupportedException {… //clonazione profonda
Scrivere anche la classe:
public class Studente extends Persona {
private static int contatore = 0;
private final int matricola;
….
Ridefinendo opportunamente i metodi toString, hashCode, equals, clone
Esercitazione 3: estendere il package it.cognome.ADT aggiungendo i seguenti punti:
1. Nell’interfaccia MyList:
a. Metodo equals()
b. Metodo hashCode()
2. Nelle classi (entrambe) MyArrayList e MyLinkedList:
Implementare equals(), hashCode(), toString(), clone(). Per l’implementazione riferirsi alla
documentazione delle API di Java:
equals(): https://docs.oracle.com/javase/8/docs/api/java/util/AbstractList.html#equalsjava.lang.Objectpublic boolean equals(Object o)
Compares the specified object with this list for equality. Returns true if and only if the specified object
is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists
are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In
other words, two lists are defined to be equal if they contain the same elements in the same order.
This implementation first checks if the specified object is this list. If so, it returns true; if not, it checks
if the specified object is a list. If not, it returns false; if so, it iterates over both lists, comparing corresponding pairs of elements. If any comparison returns false, this method returns false. If either iterator runs out of elements before the other it returns false (as the lists are of unequal length); otherwise it returns true when the iterations complete.
hashCode(): https://docs.oracle.com/javase/8/docs/api/java/util/List.html#hashCode-int hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the
following calculation:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
This ensures that list1.equals(list2) implies
that list1.hashCode()==list2.hashCode() for any two lists, list1 and list2, as required by
the general contract of Object.hashCode().
clone(): https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#clone-public Object clone()
Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
Overrides:
clone in class Object
Returns:
a clone of this ArrayList instance
toString(): https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html#toString-public String toString()
Returns a string representation of this collection. The string representation consists of a list of the
collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]").
Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to
strings as byString.valueOf(Object).
Overrides:
toString in class Object
Returns:
a string representation of this collection
Nota: le classi MyArrayList e MyLinkedList definite nel package it.cognome.ATD hanno come tipo
base oggetti di tipo String. Sostituire il tipo base con Studente (definito nell’esercitazione 2). Nelle
prossime lezioni vedremo come realizzare classi generiche.
1.4.8. Autoboxing e classi wrapper.
Materiali: Introduzione a OOP con Java parte 2 – par. 8.7
1.4.9. Confronto tra oggetti
Materiali: Introduzione a OOP con Java parte 2 – par. da 11.7 a 11.10
Esercitazione 4: Data la classe Persona dell’esercitazione 2, definire un ordinamento naturale in
base all’età (confrontare le date di nascita, sfruttando il compareTo() della classe java.util.Date).
Per la classe Persona definire anche due ordinamenti aggiuntivi, mediante due nested inner classes
di tipo Comparator. Il primo ordinamento è LexicographicalOrder che ordina le persone in base al
cognome e, a parità di cognome, in base al nome. Il secondo ordinamento aggiuntivo è
ShortestFullNameOrder che ordina le persone in base al numero complessivo di caratteri del
cognome e del nome (è “minore” la persona che ha un numero minore complessivo di caratteri tra
nome e cognome).
La classe Studente eredita gli ordinamenti definiti per la classe Persona e in aggiunta introduce un
ordinamento mediante un Comparator chiamato theYoungerTheBetter che ordina gli studenti in
base all’età e a parità d’età li ordina in base al numero di matricola.
 Testare gli ordinamenti creando una lista di Persona e una lista di Studenti (usando le liste
delle API di Java) ed effettuare gli ordinamenti utilizzando il metodo
Collections.sort(List<T> list, Comparator<? super T> c).
 Dopo aver ridefinito il tipo base di MyLinkedList (e analogamente di MyArrayList) in
Persona oppure in Studente, definire un metodo nella classe MyLinkedList (e
analogamente in MyArrayList) chiamato sort che implementa l’ordinamento naturale
della lista (richiamando il compareTo() degli oggetti di cui la lista è composta). Ad
esempio:
MyList lista = new MyLinkedList();
lista.add(new Persona("Maria", "De Zen", "31/02/1970"));
lista.add(new Persona("Piero", "Angela", "23/02/1935"));
//altri add…
lista.sort();//ordina la lista in base all’ordinamento
naturale – la lista di partenza è ordinata
 Definire un metodo nella classe MyLinkedList (e analogamente in MyArrayList) chiamato
sort(Comparator<T>
c) che accetta in input un oggetto di tipo
Comparator<Persona> che permette di usare gli ordinamenti aggiuntivi
LexicographicalOrder e ShortestFullNameOrder. Ad esempio:
lista.sort(new Persona.LexicographicalOrder()); //ordina la
lista usando l’ordinamento lessicografico
Nota: per implementare l’algoritmo di ordinamento utilizzare uno degli algoritmi di
ordinamento visti negli anni presedenti (ad esempio: insertion sort, bubble sort, etc.). Ad
esempio, nei seguenti link si trovano esempi di utilizzo di compareTo() e di Comparator
per implementare algoritmi di ordinamento:
https://www.daniweb.com/programming/software-development/threads/347069/insertionsort-method-using-comparable-array
http://www.cs.uofs.edu/~mccloske/courses/cmps144/java_comparator_sorting.html
1.5. Queues
1.5.1. FIFO concept:
https://en.wikipedia.org/wiki/Queue_(abstract_data_type)
1.5.2. Interfaccia Coda (accesso FIFO)
https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html
boolean offer(E e)
Inserts the specified element into this queue if it is possible to do so immediately without
violating capacity restrictions. When using a capacity-restricted queue, this method is generally
preferable toadd(E), which can fail to insert an element only by throwing an exception.
Parameters:
e - the element to add
Returns:
true if the element was added to this queue, else false
E poll()
Retrieves and removes the head of this queue, or returns null if this
queue is empty.
Returns:
the head of this queue, or null if this queue is empty
E peek()
Retrieves, but does not remove, the head of this queue, or
returns null if this queue is empty.
Returns:
the head of this queue, or null if this queue is empty
1.5.3. Coda circolare: http://www.mathcs.emory.edu/~cheung/Courses/171/Syllabus/8List/array-queue2.html
Altri riferimenti:
http://www.java-tips.org/java-se-tips/java.lang/linked-list-based-queue-implementation.html
http://www.java-tips.org/java-se-tips/java.lang/array-based-queue-implementation-injava.html
1.5.4. Confronto con java.util.LinkedList (che implementa java.util.Queue)
1.6. Stack
1.6.1. LIFO concept: https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
1.6.2. Implementazione con array; operazioni di push e pop
http://stackoverflow.com/questions/5552117/implementing-stack-using-linked-lists
http://www.vogella.com/tutorials/JavaDatastructures/article.html#list
1.6.3. Confronto con java.util.Stack
https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html
public E push(E item)
Pushes an item onto the top of this stack. This has exactly the same effect as:
addElement(item)
Parameters:
item - the item to be pushed onto this stack.
Returns:
the item argument.
public E pop()
Removes the object at the top of this stack and returns that object as the value of this function.
Returns:
The object at the top of this stack (the last item of
the Vector object).
Throws:
EmptyStackException - if this stack is empty.
public E peek()
Looks at the object at the top of this stack without removing it from the stack.
Returns:
the object at the top of this stack (the last item of
the Vector object).
Throws:
EmptyStackException - if this stack is empty.
1.7. Code particolari
1.7.1. Interfaccia java.util.Deque
https://docs.oracle.com/javase/8/docs/api/java/util/Deque.html
1.7.2. Classe java.util.ArrayDeque
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html
1.7.3. Coda di Priorità java.util.PiriorityQueue<>
https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html
http://docs.oracle.com/javase/tutorial/collections/implementations/queue.html
http://examples.javacodegeeks.com/core-java/util/priorityqueue/java-utilpriorityqueue-example/
Esercitazione 5: Progetto “Pronto soccorso”. Un esempio d'uso di code con priorità. Uso di
java.util.PriorityQueue per la gestione di un pronto soccorso in base al codice d'urgenza.
1.1. Concetto di mappa e di set
1.1.1. Rivedere gli esempi sulle mappe dell'anno precedente (introduzione a OOP con Java
parte 1 paragrafo 5.6)
1.1.2. Discussione dell’esempio tech-support-complete (dal libro Object First with Java)
1.1.3. http://www.mkyong.com/java/how-to-use-hashmap-tutorial-java/
1.1.4. Concetto di Hash Table: documento HashTable.pdf
1.1.5. java.util.Map<K,V>
1.1.6. java.util.HashMap<K,V>
1.1.7. Esempi d'uso di HashMap
1.1.8. ADT Set: concetto e esempi d'uso
1.1.9. java.util.Set<E>
1.1.10. java.util.HashSet<E>
1.1.11. Esercitazione 6: Scrivere un programma java che permetta di gestire una rubrica
telefonica. La lista dei contatti è realizzata mediante una HashMap in cui le chiavi sono
i numeri di telefono e i valori sono oggetti di tipo Persona. Modificare la classe Persona
in modo da inserire anche i campi telefono e email (entrambi di tipo String).
Fase1: Realizzare i metodi per:
1. L’inserimento di una coppia <telefono, Persona>
2. La cancellazione di una coppia <telefono, Persona>
3. La ricerca di una Persona di cui si conosce il numero di telefono
4. La ricerca del numero di telefono di una Persona di cui si conosce il Nome e
Cognome
5. La stampa di tutti i contatti ordinata in ordine lessicografico
Fase 2: strutturare la rubrica nel seguente modo:
6. Creare la classe Contatto con i campi ID (intero ad auto-incremento), cognome
(String), nome (String) , telefono (String) , email (String). Per la classe
Contatto fare l’override di equals(), hashCode(), toString(), compareTo()
[ordinamento naturale lessicografico prima sul cognome e poi, a parità di cognome,
sul nome], clone() (deep copy o shallow copy?). Creare anche due Comparator
come classi static nested nella classe Contatto:
Contatto.OrderByPhoneNumber e Contatto.OrderByEmail.
7. Creare la classe Rubrica con al suo interno:
Una LinkedList di tutti i contatti: contatti
Una HashMap: indicePerNumero,
Una HashMap: indicePerNome
Una HashMap: indicePerCognome.
Queste HashMap contengono le coppie <numero, Contatto>, <nome, Contatto > e
<cognome, Contatto > rispettivamente e permettono di creare tre indici per la
ricerca veloce per numero, per nome, per cognome.
Ogni volta che si inserisce un nuovo contatto nella rubrica si crea un nuovo oggetto
di tipo Contatto e si fanno gli inserimenti nella LinkedList contatti e nelle
HashMap di indicizzazione: in una si inserisce la coppia <numero, riferimento al
Contatto> e nelle altre la coppia <nome, riferimento allo stesso Contatto> e
<cognome, riferimento allo stesso Contatto>.
Attenzione: una HashMap non può contenere chiavi duplicate e dunque per gestire
gli indici occorre tener presente che più contatti potrebbero avere lo stesso
cognome, o lo stesso nome, o, addirittura, lo stesso numero di telefono. Per gestire
mappe con chiavi duplicate si può ricorrere a una struttura come la seguente:
http://stackoverflow.com/questions/1062960/map-implementation-with-duplicatekeys
/*
Adattato da http://stackoverflow.com/questions/18922165/how-to-includeduplicate-keys-in-hashmap
*/
package esempiohashmap;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.Iterator;
/**
*
* @author Gennaro
*/
public class MultipleKeysMap {
HashMap<String, LinkedList<String>> hashMap;
public MultipleKeysMap() {
hashMap = new HashMap<>();
}
private void addValues(String key, String value) {
//se key è presente nella mappa restituisco la lista di oggetti
con la stessa key
//altrimenti restituisco null
LinkedList tempList = hashMap.get(key);
if (tempList == null) {//devo creare la lista e inserirvi il
valore
tempList = new LinkedList();
tempList.add(value);
} else {//la lista esiste, devo solo aggiungervi il valore
tempList.add(value);
}
//inserisco la lista aggiornata in corrispondenza della chiave
hashMap.put(key, tempList);
}
public static void main(String... arg) {
// Add data with duplicate keys
MultipleKeysMap testMap = new MultipleKeysMap();
testMap.addValues("A", "a1");
testMap.addValues("A", "a2");
testMap.addValues("B", "b");
// View data.
Iterator it = testMap.hashMap.keySet().iterator();
LinkedList<String> tempList = null;
while (it.hasNext()) {
String key = it.next().toString();
tempList = testMap.hashMap.get(key);
if (tempList != null) {
for (String value : tempList) {
System.out.println("Key : " + key + " , Value : " +
value);
}
}
}
}
}
Nel nostro caso gli indici dovranno essere realizzati mediante mappe del tipo:
Map<String, LinkedList<Contatto>> indicePerNome = new HashMap<>()
8. Gestire i casi di cancellazione di un Contatto, di modifica del nome (o cognome) e
del numero di telefono.
9. Fornire anche il metodo che permette di fare la ricerca “globale” indifferentemente
tramite numero o tramite nome. Questo metodo accetta anche stringhe parziali
“parte del nome o del cognome” oppure “parte del numero” e nel caso di più
corrispondenze fornisce la lista di Contatti…
1.2. Recursion
1.2.1. Scrittura di programmi ricorsivi: calcolo del fattoriale, stringhe palindrome; stampa
cartelle del file system (esempi NetBeans: fileTreeDemo1 e fileTreeDemo2).
Analisi delle prestazioni di un algoritmo ricorsivo
Realizzazione di chiamate ricorsive (activation record sullo stack)
Risorsa: http://home.deib.polimi.it/caglioti/lez5.pdf (funzioni_ricorsive.pdf)
Esempi: torre di Hanoi
http://en.wikipedia.org/wiki/Tower_of_Hanoi
http://www.vogella.com/tutorials/JavaAlgorithmsTowersOfHanoi/article.html
http://simpledeveloper.com/towers-of-hanoi/
http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/13/hanoi.html
Esercizi sulla Ricorsione: Emulazione del programma tree della cmd di windows sulla
base della risorsa: “Esercizi sulla Ricorsione.pdf”
1.3. Grafi
Studiare quanto riportato nella dispensa “Grafi e programmazione.pdf”