Vous êtes sur la page 1sur 162

Univerité hassan ii

de casablanca
Ecole supérieure de technologie

Programmation
orientée objet

Java Avancé

Préparé par :
Larbi Hassouni

Threads En Java

Préparé par : HASSOUNI Larbi

HASSOUNI Larbi 2

Threads 1
Définitions
• Un programme est multitâche quand il lance
(ou peut lancer) l’exécution de plusieurs
parties de son code en même temps
• A un moment donné, il comporte plusieurs
points d’exécution liés aux différentes
parties qui s'exécutent en parallèle

HASSOUNI Larbi 3

Systèmes d’exploitation
• Tous les systèmes d'exploitation modernes
sont multitâches et ils permettent l’exécution
de programmes multitâches
• Sur une machine monoprocesseur cette
exécution en parallèle est simulée
• Si le système est préemptif, il peut à tout
moment prendre la main à un programme
pour la donner à un autre
• Sinon, un programme garde la main jusqu’à ce
qu’il la cède à un autre
HASSOUNI Larbi 4

Threads 2
Threads et processus
• Le multitâche s'appuie sur les processus ou les
threads (processus légers)
• Chaque processus a son propre espace
mémoire (espace où sont rangées les valeurs
des variables utilisées par le processus)
• Un processus peut lancer plusieurs threads qui
se partagent le même espace mémoire et
peuvent donc se partager des variables
• Un thread prend moins de ressources système
qu’un processus
HASSOUNI Larbi 5

Exemples de thread
• L’interface graphique de l’utilisateur lance un
thread pour charger une image et continue à
traiter les événements générés par les actions
de l’utilisateur
• Le serveur réseau qui attend les demandes de
connexions venant des autres machines lance
un thread pour traiter chacune des demandes
• La multiplication de 2 matrices (m, p) et (p, n)
peut être effectuée en parallèle par m  n
threads
HASSOUNI Larbi 6

Threads 3
Utilité du multitâche
• Sur une machine multiprocesseurs il permet
d’améliorer les performances en répartissant les
différentes tâches sur différents processeurs
• Par exemple, le calcul du produit de 2 matrices
peut être réparti en un nombre de tâches
parallèles égal au nombre de processeurs,
• La répartition des tâches sur les processeurs est
le plus souvent faite automatiquement par le
système qui offre le multitâche
HASSOUNI Larbi 7

Utilité du multitâche (2)


• Sur une machine monoprocesseur, il peut aussi être
intéressant d’utiliser le multitâche pour
– modéliser plus simplement (simulation par
exemple)
– profiter des temps de pose d’une tâche (attente
d’entrées-sorties ou d’une action de l’utilisateur)
pour exécuter d’autres tâches
– réagir plus vite aux actions de l’utilisateur en
rejetant une tâche longue et non-interactive dans
un autre thread (par exemple, chargement d’une
image ou lecture de données qui proviennent
d’un réseau)
HASSOUNI Larbi 8

Threads 4
Programme comportant 3 threads
Système à multi processeurs Système à un seul processeurs

HASSOUNI Larbi 9

Comment opèrent les threads

Considérons un programme qui consiste en 3 activités:

1. Lecture d’un certain nombre de bloc de données à partir


d’un fichier

2. Effectuer des calculs sur chaque bloc de données

3. Ecrire les résultats des calculs dans un autre fichier

Vous pouvez organiser le programme de deux façons


différentes comme le montre le schéma suivant.

HASSOUNI Larbi 10

Threads 5
HASSOUNI Larbi 11

Problèmes du multitâche

• Il est souvent plus difficile d'écrire un


programme multitâche
• Et surtout, il est difficile de déboguer un
programme qui utilise le multitâche

HASSOUNI Larbi 12

Threads 6
Java et le multitâche

• Java supporte l'utilisation des threads


• A l’inverse de la plupart des autres langages,
le programmeur n'a pas à utiliser des librairies
natives du système pour écrire des
programmes multitâches.

HASSOUNI Larbi 13

Définiton desThreads en Java

• A tout thread Java sont associés


– un objet qui détermine le code qui est exécuté
par le thread. Cet objet est une instance d'une
classe qui implémente l'interface Runnable.
– un objet qui « contrôle » le thread et le
représente auprès des objets de l’application ;
on l’appellera le « contrôleur de thread ».
Cet objet est une instance de la classe Thread.

HASSOUNI Larbi 14

Threads 7
Interface Runnable

q La classe de l’objet qui définit le code à


exécuter doit implémenter l’interface
Runnable

public interface Runnable {


void run();
} méthode qui contient
le code à exécuter par
le thread

HASSOUNI Larbi 15

Contrôleur de thread

• Le contrôleur d’un thread est un objet qui


– permet de contrôler l’exécution du thread (pour
le lancer en particulier)
– a des informations sur l’état du thread (son nom,
sa priorité, s’il est en vie ou non,…)
– est une instance de la classe Thread (ou une
classe fille)

HASSOUNI Larbi 16

Threads 8
Classe Thread

• Elle implémente l'interface Runnable (mais


la méthode run() ne fait rien)
• Une instance d’une classe fille de Thread
peut donc être à la fois un contrôleur de
thread et définir le code à exécuter

HASSOUNI Larbi 17

Classe Thread:
Constructeurs généralement utilisés
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r,String name)

HASSOUNI Larbi 18

Threads 9
Thread()Allocates a new Thread object.

Thread(Runnable target)Allocates a new Thread object.

Thread(Runnable target, String name)Allocates a new Thread object.

Thread(String name)Allocates a new Thread object.

Thread(ThreadGroup group, Runnable target)Allocates a new Thread object.

Thread(ThreadGroup group, Runnable target, String name)Allocates a new Thread object so that
it has target as its run object, has the specified name as its name, and belongs to the thread group
referred to by group.

Thread(ThreadGroup group, Runnable target, String name, long stackSize)Allocates a


new Thread object so that it has target as its run object, has the specified name as its name, and
belongs to the thread group referred to by group, and has the specified stack size.

Thread(ThreadGroup group, String name)Allocates a new Thread object.

HASSOUNI Larbi 19

2 façons de créer
un contrôleur de thread

• 1ère façon : créer une instance d’une classe fille


de la classe Thread ;
la classe fille doit redéfinir la méthode run()
• 2ème façon : utiliser le constructeur
Thread(Runnable) de la classe Thread :
1. créer un Runnable (le code qui sera
contrôlé par le contrôleur)
2. le passer au constructeur de Thread

HASSOUNI Larbi 20

Threads 10
Créer un contrôleur de thread avec
une classe fille de la classe Thread
class ThreadTache extends Thread {
. . .
public void run() {
// Code qui sera exécuté par le thread
. . .
}
}

ThreadTache threadTache = new ThreadTache(…);

HASSOUNI Larbi 21

Créer un contrôleur de thread


avec l'interface Runnable
class Tache implements Runnable {
. . .
public void run() {
// Code qui sera exécuté par le thread
. . .
}
}

Tache tache = new Tache(…);


Thread t = new Thread(tache) ;

HASSOUNI Larbi 22

Threads 11
Quelle façon utiliser ?

• Si on veut hériter d’une autre classe pour la


classe qui contient la méthode run(), on
est obligé de choisir la 2ème façon
(Thread(Runnable))
• Il est aussi plus simple d’utiliser la 2ème
façon pour partager des données entre
plusieurs threads
• Sinon, l’écriture du code est (légèrement)
plus simple en utilisant la 1ère façon
HASSOUNI Larbi 23

Principales méthodes de la classe Thread


public void run(): Contient le code à exécuter par le thread.
public void start(): Démarre l'exécution du thread (Le met dans l'état
runnable : Eligible pour l'execution). La JVM lance l'exécution de la
méthode run().
public void sleep(long miliseconds): Met le thread qui est en cours
d'éxécution dans l'etat endormi pour la durée spécifiée en
milliseconds (cesse de s'executer temporairement).
public void join(): Le thread qui est en cours d'execution et qui
envoie un message à un autre thread th pour exécuter join()
(th.join())se met en attente jusqu'à ce que th meurt.
public void join(long miliseconds): Le thread qui est en cours
d'execution attend qu'un thread meurt pendant une durée spécifiée
en millisecondes.

HASSOUNI Larbi 24

Threads 12
public int getPriority(): retourne la priorité du thread.

public int setPriority(int priority): changes la priorité du thread.

public String getName(): retourne le nom du thread.

public void setName(String name): change le nom du thread.


public Thread currentThread(): retourne une réference vers le
thread qui est en cours d'exécution.

public int getId(): retourne l'id du thread.


public Thread.State getState(): returne l'état du thread.

HASSOUNI Larbi 25

public boolean isAlive(): teste si le thread est toujours en vie.


public void yield(): Met le thread en cours d'exécution en état de
pause temporaire pour permettre à d'autres thread de priorité
égale ou supérieure de s'exécuter.
public boolean isDaemon(): teste si le thread est un thread
demons.
public void setDaemon(boolean b): marque le thread comme un
thread demons (b=true) ou utilisateur (b=false). Par défaut un
nouveau thread est un thread utilisateur.
public void interrupt(): interrompe un thread, plus exactement,
positionne le flag d'interruption d'un thread à l'état "ON".
public boolean isInterrupted(): teste si le thread a été
interrompu. Autrement dit, teste si son flag d'interruption est
positionné à "ON".
public static boolean interrupted(): idem que isInterrupted(),
mais c'est une méthode statique.
HASSOUNI Larbi 26

Threads 13
Etats d'un thread
A thread can be in one of the following states:
• NEW : A thread that has not yet started is in this state
• RUNNABLE : A thread in the runnable state is executing in the Java virtual machine
but it may be waiting for other resources from the operating system such as
processor.
• BLOCKED: A thread in the blocked state is waiting for a monitor lock to enter a
synchronized block/method or reenter a synchronized block/method after calling
object.wait.
• WAITING : A thread is in the waiting state due to calling one of the following
methods:
– Object.wait with no timeout
– Thread.join with no timeout
A thread in the waiting state is waiting for another thread to perform a particular
action. For example, a thread that has called Object.wait() on an object is waiting
for another thread to call Object.notify() or Object.notifyAll() on that object. A
thread that has called Thread.join() is waiting for a specified thread to terminate
HASSOUNI Larbi 27

TIMED_WAITING : A thread is in the timed waiting


state due to calling one of the following methods
with a specified positive waiting time:
•Thread.sleep
•Object.wait with timeout
•Thread.join with timeout

HASSOUNI Larbi 28

Threads 14
Cycle de vie d'un thread

Bloqué sleep()
new (BLOCKED) wait()
Thread()

notify()

Nouveau start() Eligible pour En


Thread l'exécution Exécution
(NEW) (RUNNABLE) (RUNNING)
yield()

exit()ou fin d'exécution


Mort
(DEAD)

HASSOUNI Larbi 29

Nom d’un thread

• Le nom permet de faciliter le repérage des


threads durant la mise au point.
• Pour donner un nom à un thread, on peut
utiliser l'un des constructeurs suivant :
 Thread(String name)
 Thread(Runnable r, String name)
• Ou utiliser la méthode :
public void setName(String name)

HASSOUNI Larbi 30

Threads 15
Lancer l’exécution d'un thread
La méthode start() de la classe Thread est utilisée pour lancer
un thread nouvellement créé. Elle effectue les operations
suivantes:
 Un nouveau thread démarre (avec une nouvelle
"callstack").
 Le thread passe de l'état "New" à l'état "Runnable".
Lorsque le thread est sélectionéé par le scheduler, sa méthode
run() se met en exécution en parallèle avec le code qui a lance
le thread.
Attention, une erreur serait d’appeler directement la méthode
run() : la méthode run() serait exécutée par le thread qui l’a
appelée et pas par un nouveau thread(Il n’ya pas création de
thread)
HASSOUNI Larbi 31

 Chaque thread lancé avec start possède sa propre


pile (call stack).
 Invoquer la méthode run() à partir du thread main(),
run() utilise la pile actuelle utilisée par le tread
main() plutôt que d'utiliser une nouvelle pile.

Invocation de run() à
Lancement des threads par start:
partir de main(): run() se
Chaque thread s'exécute avec une pile séparée
partage la même pile que
main()
HASSOUNI Larbi 32

Threads 16
Relancer un thread

Attention :
• On ne peut relancer un thread qui a déjà été lancé.
• Que l’exécution de la méthode run du thread soit
terminée ou non, si on relance un thread, on obtient
une java.lang.IllegalThreadStateException

HASSOUNI Larbi 33

Le "Scheduler" des threads en Java


• Le Scheduler des threads en java est la partie de la
JVM qui décide quel thread sera mis en exécution.
• Il n'y a pas de garantie sur le thread "runnable" qui
sera séléctioné par le Scheduler pour s'exécuter.
• Le Scheduler des threads utilise principalement deux
méthodes pour planifier l'exécution des threads :
– Planification "preemptive"
– "time slicing" ou quantum de temp.

HASSOUNI Larbi 34

Threads 17
Différence entre planification preemptive
et time slicing
• Sous la planification preemptive, le thread qui a la
plus haute priorité s'exécute jusqu'à ce qu'il se met
en état d'attente, ou se termine, ou un thread de
plus haute priorité rentre en existance.
• Sous "time slicing", un thread s'exécute pour une
parie du temps (quantum), puis rentre dans la queue
(ou pool) des treads runnable. Le scheduler
détermine par la suie quel thread se mettra en
exécution, en se basant sur la priorité et d'autres
facteurs.
HASSOUNI Larbi 35

Threads : Exemple 1
class Ecrit extends Thread{ public class TstThr1{
public static void main (String args[]){
public Ecrit (String texte, int nb, long attente){ Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ; e1.start() ;
e2.start() ;
} e3.start() ;
public void run (){ System.out.println(« Je suis la fonction main »);
}
try{ }
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ;
sleep (attente) ;
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
} HASSOUNI Larbi 36

Threads 18
Threads : Exemple 2
class Ecrit implements Runnable{ public class TstThr2{
public static void main (String args[]){
public Ecrit (String texte, int nb, long attente){ Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ;
Thread t1 = new Thread (e1) ; t1.start() ;
} Thread t2 = new Thread (e2) ; t2.start() ;
public void run (){ Thread t3 = new Thread (e3) ; t3.start() ;
try{ System.out.println(“Je suis la fonction main”);
}
for (int i=0 ; i<nb ; i++){ }
System.out.print (texte) ;
Thread.sleep (attente) ;
// attention Thread.sleep
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
}
HASSOUNI Larbi 37

Threads : Exemple 3
class Ecrit implements Runnable{ public class TstThr3{
public Ecrit (String texte, int nb, long attente){ public static void main (String args[]){
Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
this.texte = texte ; Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ; e1.start() ;
} e2.start() ;
public void start (){ e3.start() ;
Thread t = new Thread (this) ; System.out.println(« Je suis la fonction main »);
t.start() ; }
}
}
public void run (){
try{
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ;
Thread.sleep (attente) ;
}
}
catch (InterruptedException e) {
} // impose par sleep
}
private String texte ;
private int nb ;
private long attente ;
} HASSOUNI Larbi 38

Threads 19
Threads : Exemple 4
class Ecrit implements Runnable{ public class MyTstThr4{
public Ecrit (String texte, int nb, long attente){ public static void main (String args[]){
this.texte = texte ; Ecrit e1 = new Ecrit ("Salam\n", 10, 5) ;
Ecrit e2 = new Ecrit ("Hello\n", 12, 10) ;
this.nb = nb ; Ecrit e3 = new Ecrit ("Bonjour\n", 5, 15) ;
this.attente = attente ;
} Thread t1 = new Thread (e1) ; t1.start() ;
public void run (){ Thread t2 = new Thread (e2) ; t2.start() ;
try{ Thread t3 = new Thread (e3) ; t3.start() ;
for (int i=0 ; i<nb ; i++){
System.out.print (texte) ; try{
for(int i=0; i<5; i++){
Thread.sleep (attente) ; System.out.println("Fonction main");
// attention Thread.sleep Thread.sleep(100);
} }
} }
catch (InterruptedException e) { catch(InterruptedException e){
} // impose par sleep }
}
System.out.println("Je suis la fonction main");
private String texte ;
private int nb ; }
private long attente ; }
}

HASSOUNI Larbi 39

Types de Threads
• On distingue deux types de threads
– les threads utilisateur
– les démons
• La différence :
– la JVM fonctionne tant qu’il reste des threads
utilisateurs en exécution
– la JVM s’arrête s’il ne reste plus que des démons

HASSOUNI Larbi 40

Threads 20
Thread démons
(Daemon Thread)
• Un thread "Daemon" en java est un thread
fournisseur de service qui fournit des services au
thread utilisateur. Son cycle de vie dépend du cycle
de vie des threads utilisateurs.
• Lorsque tous les threads utilisateurs meurent, La JVM
termine automatiquement les threads démons.
• Il y a beucoup de threads démons qui s'exécutent
automatiquement (gc : garbage collector, finalize :
finalizer, …etc). (Pour voir tous les details, utilizer
l'utilitaire "jconsole")
HASSOUNI Larbi 41

Points à retenir sur les threads démons

• Un thread démons fournit un service à un thread


utilisateur pour supporter des tâches d'arrière plan.
• Il n'a aucun role sinon servir les threads utilisateurs.
C'est pour cette raison que la JVM termine
automatiquement un thread démons lorsque tous
les threads utilisateurs se terminent.
• Son cycle de vie depend des threads utilisateurs.
• Il a une faible priorité.

HASSOUNI Larbi 42

Threads 21
Threads démons
• La méthode:
void setDaemon(boolean on)
de la classe Thread permet d’indiquer que le
thread sera un démon (thread utilisateur par
défaut)
• Elle doit être appelée avant le démarrage du
thread par l’appel de start()

HASSOUNI Larbi 43

HASSOUNI Larbi 44

Threads 22
Threads demons et arret brutal
class Ecrit extends Thread import java.util.Scanner;
{ public Ecrit (String texte, long attente) public class Demons
{ this.texte = texte ; { public static void main (String args[])
this.attente = attente ; { Ecrit e1 = new Ecrit ("Salam\n", 5) ;
} Ecrit e2 = new Ecrit ("Hello\n", 10) ;
Ecrit e3 = new Ecrit ("Bonjour\n", 35) ;
public void run ()
e1.setDaemon (true) ; e1.start() ;
{ try e2.setDaemon (true) ; e2.start() ;
{ while (true) // boucle infinie e3.setDaemon (true) ; e3.start() ;
{ if (interrupted()) return ; int n = new Scanner(System.in).nextInt() ;
System.out.print (texte) ; // met fin au main, donc ici aux trois autres threads démons
sleep (attente) ; }
} }
}
catch (InterruptedException e)
{ return ; // on peut omettre return ici
}
}

private String texte ;


private long attente ;
}

HASSOUNI Larbi 45

Threads : Exemple 5 (1/2)


import java.io.IOException;
public class TryThread extends Thread {
public TryThread(String firstName, String secondName, long delay) {
this.firstName = firstName; // Store the first name
this.secondName = secondName; // Store the second name
aWhile = delay; // Store the delay
setDaemon(true); } // Thread is daemon
public static void main(String[] args) {
// Create three threads
Thread first = new TryThread(« Said ", « AOUITA ", 200L);
Thread second = new TryThread(« Younes ", « ELAYNAOUI ", 300L);
Thread third = new TryThread(« Nawal ", « MOUTAWAKIL ", 500L);
System.out.println("Press Enter when you have had enough...\n");
first.start(); second.start(); third.start(); // Start the third thread
try {
System.in.read(); // Wait until Enter key pressed
System.out.println("Enter pressed...\n");
} catch (IOException e) { // Handle IO exception
System.err.println(e); // Output the exception }
System.out.println("Ending main()");
return;
}
HASSOUNI Larbi 46

Threads 23
Threads : Exemple 5 (2/2)

// Method where thread execution will start


@Override
public void run() {
try {
while(true) { // Loop indefinitely...
System.out.print(firstName); // Output first name
sleep(aWhile); // Wait aWhile msec.
System.out.print(secondName + "\n"); // Output second name
}
} catch(InterruptedException e) { // Handle thread interruption
System.out.println(firstName + secondName + e); // Output the exception
}
}

private String firstName; // Store for first name


private String secondName; // Store for second name
private long aWhile; // Delay in milliseconds
}

HASSOUNI Larbi 47

Threads : Exemple 6 (1/2)


import java.io.IOException;
public class JumbleNames implements Runnable {
// Constructor
public JumbleNames(String firstName, String secondName, long delay) {
this.firstName = firstName; // Store the first name
this.secondName = secondName; // Store the second name
aWhile = delay; // Store the delay
}
// Method where thread execution will start
public void run() {
try {
while(true) {
System.out.print(firstName);
Thread.sleep(aWhile);
System.out.print(secondName+"\n");
}
} catch(InterruptedException e) {
System.out.println(firstName + secondName + e);
} }

HASSOUNI Larbi 48

Threads 24
Threads : Exemple 6 (2/2)
public static void main(String[] args) {
// Create three threads
Thread first = new Thread(new JumbleNames("Hopalong ", "Cassidy ", 200L));
Thread second = new Thread(new JumbleNames("Marilyn ", "Monroe ", 300L));
Thread third = new Thread(new JumbleNames("Slim ", "Pickens ", 500L));
// Set threads as daemon
first.setDaemon(true); second.setDaemon(true); third.setDaemon(true);
System.out.println("Press Enter when you have had enough...\n");
first.start(); // Start the first thread
second.start(); // Start the second thread
third.start(); // Start the third thread
try {
System.in.read(); // Wait until Enter key pressed
System.out.println("Enter pressed...\n");
} catch (IOException e) { // Handle IO exception
System.err.println(e); // Output the exception
}
System.out.println("Ending main()"); return;
}
private String firstName; private String secondName; private long aWhile;}
HASSOUNI Larbi 49

Dormir
• La méthode static de la classe Thread
public static void sleep(long millis)
throws InterruptedException
fait dormir le thread qui l'appelle un certain nombre
de millisecondes
• Si elle est exécutée dans du code synchronisé, le
thread ne perd pas le moniteur (au contraire de wait())
• La syntaxe est :
public static void sleep(int millis) throws InterruptedException

Exception
•InterruptedException -- Si le thread en cours est interrompu par un autre
thread, l’exception InterruptedException est lancée et son flag d’interruption est
initialisé.

HASSOUNI Larbi 50

Threads 25
Attente de la fin d’un thread
• Si dans un thread vous voulez attendre jusquà ce qu’un
autre thread meurt, vous pouvez appeler la méthode
join() pour le thread à attendre.
• La syntaxe est:
 threadAattendre.join(); : Le thread en cours attend
jusqu’à ce que threadAAttendre meurt;
 threadAattendre.join(long millis);
 threadAattendre.join(long millis, int nanos);
• La méthode join() peut lancer l’exception
InterruptedException si le thread en cours est interrompu
par un autre thread, par consequent vous devez mettre
dans un bloc try block et capter (catch) l’exception.
HASSOUNI Larbi 51

class FaitQuelqueChose implements Runnable {


// attribut propre au thread
protected String msg;

// constructeur
public FaitQuelqueChose(String msg) {
this.msg = msg;
}
// méthode d’exécution de la thread
public void run(){
System.out.println("run: (" + msg + ") début !");
try {
Thread.sleep(5000);
}
catch (Exception e) {}
System.out.println("run: (" + msg + ") milieu...");
try {
Thread.sleep(5000);
}
catch (Exception e) {}
System.out.println("run: (" + msg + ") fin !");
}
}
HASSOUNI Larbi 52

Threads 26
public class ThreadEx {
public static void main(String[] args) throws Exception {
System.out.println("main: demarre un");
Thread t1 = new Thread(new FaitQuelqueChose("un"));
t1.start();
try {
Thread.sleep(2500);
}
catch (Exception e) {}
System.out.println("main: demarre deux");

Thread t2 = new Thread(new FaitQuelqueChose("deux"));


t2.start();
System.out.println("main: attente fin execution...");
t1.join();
System.out.println("main: t1 est fini");
t2.join();
System.out.println("main: t2 est fini");
}
}
HASSOUNI Larbi 53

main: demarre un
run: (un) début !
main: demarre deux
main: attente fin execution...
run: (deux) début !
run: (un) milieu...
run: (deux) milieu...
run: (un) fin !
main: t1 est fini
run: (deux) fin !
main: t2 est fini

HASSOUNI Larbi 54

Threads 27
Exécution de ThreadEx
C:\>java MineThreadEx

main: demarre un main


run: (un) debut ! un
main: demarre deux
deux
main: attente fin
execution...
run: (deux) debut !
run: (un) milieu...
run: (deux) milieu...
run: (un) fin !
main: t1 est fini
run: (deux) fin !
main: t2 est fini
HASSOUNI Larbi 55

Passer la main

• La méthode static de la classe Thread


public static void yield()
permet de passer la main à un autre thread
de priorité égale ou supérieure
• Lorsqu’un thread exécute yield, il prend le
temps de voir s’il y a d’autres threads de
priorité égale ou supérieure qui sont en
attente. Si c’est le cas, la main est passée,
sinon le thread reprend son exécution
HASSOUNI Larbi 56

Threads 28
public class YieldingThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public YieldingThread() {
super("" + ++threadCount);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
yield();
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++)
new YieldingThread();
}
}
HASSOUNI Larbi 57

Interruption d'un thread

• Si un thread se trouve dans l'état endormie ou


d'attente(i.e. sleep() or wait() est invoquée),
l'appel de la méthode interrupt() sur le thread
met fin à l'etat endormi ou d'attente en
lançant l'exception InterruptedException.
• Si le thread ne se trouve dans un état endormi
ou d'attente, appeller la méthode interrupt()
n'interrompe pas le thread met place le flag
interrup du thread à l'état true.
HASSOUNI Larbi 58

Threads 29
Interruption de threads
class Ecrit extends Thread{ public class TstInter {
public Ecrit (String texte, long attente){ public static void main (String args[]) {
this.texte = texte ; Ecrit e1 = new Ecrit ("bonjour ", 5) ;
this.attente = attente ; Ecrit e2 = new Ecrit ("bonsoir ", 10) ;
} Ecrit e3 = new Ecrit ("\n", 35) ;
e1.start() ;
public void run (){
e2.start() ;
try{ e3.start() ;
while (true) { // boucle infinie System.out.println(«main : avant interruption e1 »);
if (interrupted()) return ; e1.interrupt() ; // interruption premier thread
System.out.print (texte) ; System.out.println ("\n** Arret premier thread **") ;
sleep (attente) ; System.out.println(«main : avant interruption e2 »);
} e2.interrupt() ; // interruption deuxième thread
e3.interrupt() ; // interruption troisième thread
}
System.out.println ("\n* Arret deux derniers threads *") ;
catch (InterruptedException e){ }
return ; // on peut omettre return ici }
}
}

private String texte ;


private long attente ;
}

HASSOUNI Larbi 59

Exécution de TstIntr

main : avant interruption e1

bonsoir bonjour
** Arret premier thread **
main : avant interruption e2

* Arret deux derniers threads *

HASSOUNI Larbi 60

Threads 30
Partage de données
entre plusieurs threads
• Le plus simple est de créer les threads
en utilisant une classe qui implémente
Runnable et de mettre les données
partagées comme variables static
de cette classe.

HASSOUNI Larbi 61

Synchronisation entre threads

HASSOUNI Larbi 62

Threads 31
Dans ce qui suit, nous allons discuter les capacités
basiques du langage Java pour gérer la synchronisation
entre les threads.
La librairie de concurrence fournie par les packages:
• java.util. concurrent,
• java.util.concurrent.atomic,
• java.util.concurrent.locks
Contient des classes qui implémente des facilités de
gestion des threads spécialisées,

HASSOUNI Larbi 63

Section critique
• L’utilisation de threads peut entraîner des
besoins de synchronisation pour éviter les
problèmes liés aux accès simultanés aux
variables
• En programmation, on appelle section critique
une partie du code qui ne peut être exécutée
en même temps par plusieurs threads sans
risquer de provoquer des anomalies de
fonctionnement
HASSOUNI Larbi 64

Threads 32
Exemple de problème
• Si x = 2, le code x = x + 1;
exécuté par 2 threads, peut donner en fin
d’exécution 3 ou 4 suivant l’ordre d’exécution :
1. T1 : lit la valeur de x (2)
2. T2 : lit la valeur de x (2)
3. T1 : calcul de x + 1 (3)
4. T2 : calcul de x + 1 (3)
5. T1 : range la valeur calculée dans x (3)
6. T2 : range la valeur calculée dans x (3)
• x contient 3 au lieu de 4 !

HASSOUNI Larbi 65

Synchronisation
• Il faut donc éviter l’exécution simultanée de
sections de code critiques par plusieurs threads

• Si plusieurs threads veulent exécuter en même


temps une section critique, on devra les
synchroniser pour qu’ils exécutent cette section
les uns après les autres

• En java les sections critiques sont représentées


par du code synchronisé sur un objet
HASSOUNI Larbi 66

Threads 33
Méthodes synchronized
class MyClass {
synchronized public void method1() {
// Code for the method...
}
synchronized public void method2() {
// Code for the method...
}
public void method3() {
// Code for the method...
}
}

HASSOUNI Larbi 67

HASSOUNI Larbi 68

Threads 34
Synchronisation de threads
class Nombres {
public void calcul() {
n++ ;
carre = n*n ;
}
public void affiche () {
System.out.println (n + " a pour carre " + carre) ;
}
private int n=0, carre ;
}

class ThreadCalcul extends Thread{ class ThreadAffiche extends Thread {


public ThreadCalcul (Nombres nomb){ public ThreadAff iche(Nombres nomb) {
this.nomb = nomb ; this.nomb = nomb ;
} }
public void run (){ public void run () {
try { try {
while (!interrupted()){ while (!interrupted()) {
nomb.calcul () ; nomb.affiche() ;
sleep (50) ; sleep (75) ;
} }
} }
catch (InterruptedException e) {} catch (InterruptedException e) {}
} }
private Nombres nomb ; private Nombres nomb ;
} HASSOUNI Larbi } 69

Synchronisation de threads
Import java.util.Scanner;
public class Synchronisation1 {
public static void main (String args[]) {
Nombres nomb = new Nombres() ;
Thread calc = new ThrCalc (nomb) ;
Thread aff = new ThrAff (nomb) ;
System.out.println ("Suite de carres - tapez retour pour arreter") ;
calc.start() ; >java NonSynchr1
aff.start() ; Suite de carres - tapez retour pour arreter
String s = new Scanner(System.in).nextLine(); 1 a pour carre 1
calc.interrupt() ; 2 a pour carre 4
aff.interrupt() ; 3 a pour carre 9
} 5 a pour carre 25
} 6 a pour carre 49
8 a pour carre 64
9 a pour carre 100
11 a pour carre 121
13 a pour carre 169
14 a pour carre 196
16 a pour carre 256
17 a pour carre 289
18 a pour carre 324
HASSOUNI Larbi 70

Threads 35
Synchronisation de threads
class Nombres{
public /* synchronized */ void calcul(){
n++ ;
try { Thread.sleep (100) ;}
catch (InterruptedException e) {}
carre = n*n ;
}
public /* synchronized */ void affiche (){
System.out.println (n + " a pour carre " + carre) ;}
private int n=0, carre ;
}
class ThreadCalcul extends Thread{ class ThreadAffiche extends Thread {
public ThreadCalcul (Nombres nomb){ public ThreadAffiche (Nombres nomb) {
this.nomb = nomb ; this.nomb = nomb ;
} }
public void run (){ public void run () {
try { try {
while (!interrupted()){ while (!interrupted()) {
nomb.calcul () ; nomb.affiche() ;
sleep (50) ; sleep (75) ;
} }
} }
catch (InterruptedException e) {} catch (InterruptedException e) {}
} }
private Nombres nomb ; private Nombres nomb ;
} HASSOUNI Larbi } 71

Synchronisation de threads
>java Synchr1a
import java.util.Scanner; Suite de carres - tapez retour pour arreter
public class Synchronisation2 { 1 a pour carre 0
public static void main (String args[]) { 1 a pour carre 0
Scanner stdin = new Scanner(System.in); 2 a pour carre 1
2 a pour carre 1
Nombres nomb = new Nombres() ; 3 a pour carre 4
Thread calcul = new ThreadCalcul (nomb) ; 3 a pour carre 4
Thread affiche = new ThreadAffiche (nomb) ; 4 a pour carre 9
4 a pour carre 9
System.out.println ("Suite de carres – 5 a pour carre 16
tapez retour pour arreter") ; 5 a pour carre 16
calcul.start() ; 6 a pour carre 25
affiche.start() ; 6 a pour carre 25
7 a pour carre 36
String s = stdin.nextLine(); 7 a pour carre 36
calcul.interrupt() ; 8 a pour carre 49
affiche.interrupt() ; 8 a pour carre 49
9 a pour carre 64
} 9 a pour carre 64
} 10 a pour carre 81
10 a pour carre 81
11 a pour carre 100
11 a pour carre 100
12 a pour carre 121
12 a pour carre 121
HASSOUNI Larbi 72

Threads 36
Synchronisation de threads
class Nombres {
public synchronized void calcul() {
n++ ;
carre = n*n ;
}
public synchronized void affiche () {
System.out.println (n + " a pour carre " + carre) ;
}
private int n=0, carre ;
}

class ThrCalc extends Thread{ class ThrAff extends Thread {


public ThrCalc (Nombres nomb){ public ThrAff (Nombres nomb) {
this.nomb = nomb ; this.nomb = nomb ;
} }
public void run (){ public void run () {
try { try {
while (!interrupted()){ while (!interrupted()) {
nomb.calcul () ; nomb.affiche() ;
sleep (50) ; sleep (75) ;
} }
} }
catch (InterruptedException e) {} catch (InterruptedException e) {}
} }
private Nombres nomb ; private Nombres nomb ;
} HASSOUNI Larbi } 73

Synchronisation de threads
import java.util.Scanner;
public class Synchr1 {
public static void main (String args[]) {
Scanner stdin = new Scanner(System.in); C:\>java Synchr1
Nombres nomb = new Nombres() ; Suite de carres - tapez retour pour arreter
1 a pour carre 1
Thread calc = new ThrCalc (nomb) ; 2 a pour carre 4
Thread aff = new ThrAff (nomb) ; 4 a pour carre 16
5 a pour carre 25
System.out.println ("Suite de carres – 6 a pour carre 36
tapez retour pour arreter") ; 8 a pour carre 64
9 a pour carre 81
calc.start() ; 11 a pour carre 121
aff.start() ; 12 a pour carre 144
14 a pour carre 196
String s = stdin.nextLine(); 15 a pour carre 225
calc.interrupt() ; 17 a pour carre 289
18 a pour carre 324
aff.interrupt() ; 20 a pour carre 400
} 21 a pour carre 441
23 a pour carre 529
} 24 a pour carre 576
26 a pour carre 676
27 a pour carre 729

HASSOUNI Larbi 74

Threads 37
Moniteur ou verrou d’un objet

• En Java, l’implémentation du code


synchronisé repose sur les moniteurs
(verrous) des objets
• Chaque objet Java possède un moniteur
• Un seul thread peut posséder le moniteur
d’un objet à un moment donné
• Si un autre thread veut acquérir le même
moniteur, il est mis en attente

HASSOUNI Larbi 75

Synchronisation avec les moniteurs

• Un thread t acquiert le moniteur d’un objet


en exécutant du code synchronisé sur cet
objet
• t rend le moniteur en quittant le code
synchronisé (ou en appelant la méthode
wait() de l’objet o)
• Il peut quitter le code synchronisé
normalement, ou si une exception est lancée
et non saisie
HASSOUNI Larbi 76

Threads 38
Synchronisation
• Aucun autre thread ne peut exécuter du code
synchronisé sur le même objet o tant que t exécute
le code synchronisé
• Si un autre thread veut exécuter du code synchronisé
sur o, il est mis en attente
• Lorsque t quitte le code synchronisé ou se met en
attente par o.wait(), un des threads en attente
peut redémarrer
• Les autres threads en attente auront la main à tour
de rôle (si tout se passe bien…)

HASSOUNI Larbi 77

Exemple
public class Compte {
private double solde;

public void deposer(double somme) {


solde = solde + somme;
}

public double getSolde() {


return solde;
}
}

HASSOUNI Larbi 78

Threads 39
Exemple (suite)
• On lance 3 threads du type suivant :
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
compte.deposer(1000);
}
}
};
• A la fin de l’exécution, on n’obtient pas nécessairement
300.000
• Il faut rendre deposer (et getSolde) synchronisée :
public synchronized
void deposer(double somme)
HASSOUNI Larbi 79

Synchronisation et performances
• L’exécution de code synchronisé nuit aux
performances
• Surtout s’il provoque des blocages entre
threads ; si pas de blocage, peu de perte de
performance
• Mais, de plus, du code synchronisé peut
empêcher des optimisations (inlining) au
moment de la compilation

HASSOUNI Larbi 80

Threads 40
Méthodes statiques

• Si on synchronise une méthode static,


on bloque le moniteur de la classe
• On bloque ainsi tous les appels à des
méthodes synchronisées de la classe (mais
pas les appels synchronisés sur une
instance de la classe)

HASSOUNI Larbi 81

Méthode synchronisée et héritage

• La redéfinition d’une méthode


synchronisée dans une classe fille peut ne
pas être synchronisée
• De même, la redéfinition d’une méthode
non synchronisée peut être synchronisée

HASSOUNI Larbi 82

Threads 41
wait et notify

HASSOUNI Larbi 83

Exécution conditionnelle
• Lorsqu’un programme est multi-tâche, la
situation suivante peut se rencontrer :
– Un thread t1 ne peut continuer son exécution
que si une condition est remplie
– Le fait que la condition soit remplie ou non
dépend d’un autre thread t2
• Par exemple, t1 veut utiliser le résultat d’un
calcul effectué par t2

HASSOUNI Larbi 84

Threads 42
Exécution conditionnelle (2)
• Une solution coûteuse serait que t1 teste la
condition à intervalles réguliers
• Les méthodes wait() et notify() de la
classe Object permettent de programmer
plus efficacement ce genre de situation

HASSOUNI Larbi 85

Schéma d’utilisation de wait-notify


• Cette utilisation demande un travail coopératif
entre les threads t1 et t2 :
1. Ils se mettent d’accord sur un objet commun
objet
2. Arrivé à l’endroit où il ne peut continuer que si la
condition est remplie, t1 se met en attente :
objet.wait();
3. Quand t2 a effectué le travail pour que la condition
soit remplie, il le notifie :
objet.notify();
ce qui débloque t1
HASSOUNI Larbi 86

Threads 43
Exemple d’utilisation de wait et notifyAll

HASSOUNI Larbi 87

class ThreadAjout extends Thread{

public ThreadAjout (Reserve r, int vol, int delai){


this.vol = vol ; this.r = r ; this.delai = delai ;}

public void run (){


try{
while (!interrupted()){
r.ajoute (vol) ;
sleep (delai) ;}}
catch (InterruptedException e) {}
}

private int vol ;


private Reserve r ;
private int delai ;
}

HASSOUNI Larbi 88

Threads 44
class ThreadPuise extends Thread{

public ThreadPuise (Reserve r, int vol, int delai){


this.vol = vol ; this.r = r ; this.delai = delai ;
}

public void run (){


try{
while (!interrupted()){
r.puise (vol) ;
sleep (delai) ; }
}
catch (InterruptedException e) {}
}

private int vol ;


private Reserve r ;
private int delai ;
}

HASSOUNI Larbi 89

import java.util.Scanner;
public class Synchro3{
public static void main (String args[]){
Reserve r = new Reserve () ;
ThreadAjout ta1 = new ThreadAjout (r, 100, 15) ;
ThreadAjout ta2 = new ThreadAjout (r, 50, 20) ;
ThreadPuise tp = new ThreadPuise (r, 300, 10) ;
System.out.println ("Suivi de stock --- Taper entree pour arreter ") ;
ta1.start () ; ta2.start () ; tp.start () ;
String s = new Scanner(System.in).nextLine();
ta1.interrupt () ; ta2.interrupt () ; tp.interrupt () ;
}
}
HASSOUNI Larbi 90

Threads 45
Besoin de synchronisation
• Le mécanisme d’attente-notification lié à un
objet met en jeu l’état interne de l’objet ;
pour éviter des accès concurrent à cet état
interne, une synchronisation est nécessaire
• Les appels:
-objet.wait()
-objet.notify()
-objet.notifyAll())
ne peuvent donc être effectués que dans du
code synchronisé sur objet
HASSOUNI Larbi 91

Méthode wait()
• public final void wait()
throws InterruptedException
• objet.wait()
– nécessite que le thread en cours possède le
moniteur de objet
– bloque le thread qui l’appelle, jusqu’à ce qu’un
autre thread appelle la méthode
objet.notify() ou objet.notifyAll()
– libère le moniteur de l’objet (l’opération « blocage
du thread – libération du moniteur » est atomique)

HASSOUNI Larbi 92

Threads 46
Méthode notifyAll()

• public final void notifyAll()


• objet.notifyAll()
– nécessite que le thread en cours possède le
moniteur de objet
– débloque tous les threads qui s’étaient bloqués sur
l’objet avec objet.wait()

HASSOUNI Larbi 93

Méthode notifyAll()
• Un seul des threads débloqués va récupérer le
moniteur ; on ne peut prévoir lequel
• Les autres devront attendre qu’il relâche le
moniteur pour être débloqués à tour de rôle,
mais ils ne sont plus bloqués par un wait
• En fait, souvent ils se bloqueront à nouveau
eux-mêmes (s’ils sont dans une boucle while
avec wait)

HASSOUNI Larbi 94

Threads 47
Méthode notify()
• objet.notify()
– idem notifyAll() mais
– ne débloque qu’un seul thread
• On ne peut prévoir quel sera le thread
débloqué et, le plus souvent, il vaut donc mieux
utiliser notifyAll()

HASSOUNI Larbi 95

Déblocage des threads

• Le thread débloqué (et élu) ne pourra


reprendre son exécution que lorsque le thread
qui l’a notifié rendra le moniteur de l’objet en
quittant sa portion de code synchronisé
• Le redémarrage et l’acquisition se fait dans une
opération atomique

HASSOUNI Larbi 96

Threads 48
notify perdus

• Si un notifyAll() (ou notify()) est


exécuté alors qu'aucun thread n'est en attente,
il est perdu : il ne débloquera pas les wait()
exécutés ensuite

HASSOUNI Larbi 97

Exemple avec wait-notify


• Les instances d’une classe Depot contiennent
des jetons
• Ces jetons sont
– déposés par un producteur
– consommés par des consommateurs
• Les producteurs et consommateurs sont des
threads

HASSOUNI Larbi 98

Threads 49
Exemple avec wait-notify
public class Depot {
private int nbJetons = 0;
public synchronized void donneJeton() {
try {
while (nbJetons == 0) {
wait();
}
nbJetons--;
}
catch (InterruptedException e) {}
}

HASSOUNI Larbi 99

Exemple avec wait-notify


public synchronized void recois(int n) {
nbJetons += n;
notifyAll();
}

HASSOUNI Larbi 100

Threads 50
Variante de wait

• Si on ne veut pas attendre éternellement


une notification, on peut utiliser une des
variantes suivantes de wait :
public void wait(long timeout)
public void wait(long timeout,
int nanos)
• Dans ce cas, le thread doit gérer lui-même
le fait de connaître la cause de son
déblocage (notify ou temps écoulé)

HASSOUNI Larbi 101

Moniteurs réentrants

• Un thread qui a acquis le moniteur d’un


objet peut exécuter les autres méthodes
synchronisées de cet objet ; il n’est pas
bloqué en demandant à nouveau le
moniteur

HASSOUNI Larbi 102

Threads 51
Affectations atomiques
• Il est inutile de synchroniser une partie de
code qui ne fait qu'affecter (ou lire) une valeur
à une variable de type primitif de longueur 32
bits ou moins (int, short, …)
• En effet, la spécification du langage Java
spécifie qu'une telle affectation ne peut être
interrompue pour donner la main à un autre
thread
• Mais, cette spécification n'assure rien pour les
affectations de double et de long !
HASSOUNI Larbi 103

Groupes de threads en Java


• Java fournit un moyen commode pour regrouper plusieurs threads dans
un seul objet. Ceci permet d'effectuer une même operation sur tous les
threads du même groupe, par un simple appel de méthode.
• Un groupe de threads peut avoir des groupes de threads enfants.
• Un groupe de thread est implémenté par la classe java.lang.ThreadGroup.
public class ThreadGroup extends Object implements
Thread.UncaughtExceptionHandler
• Constructeurs de la classe ThreadGroup
• La classe ThreadGroup possède uniquement deux constructeurs.
Constructeur Description

ThreadGroup(String name) Crée un groupe de threads avec le


nom spécifié.

ThreadGroup(ThreadGroup parent, Crée un groupe de threads, en


String name) spécifiant son groupe de threads
parent, et son nom.
HASSOUNI Larbi 104

Threads 52
Importantes méthodes de la classe ThreadGroup
• Il ya plusieurs méthodes dans la classe ThreadGroup. La liste ci-dessous
fournit les noms des plus importantes.
Méthode Description
Returns an estimate of the number of active
int activeCount() threads in this thread group and its
subgroups.
void destroy() Destroys this thread group and all of its
subgroups.
String getName() returns the name of this group.
ThreadGroup getParent() returns the parent of this group.
void interrupt() interrupts all threads of this group.
void list() prints information of this group to standard
console.
Called by the Java Virtual Machine when a
Void thread in this thread group stops because of
uncaughtException(Thread t, an uncaught exception, and the thread does
Throwable e) not have a specific
Thread.UncaughtExceptionHandler installed.

HASSOUNI Larbi 105

Exemple de code pour regrouper plusieurs threads.


ThreadGroup tg1 = new ThreadGroup("Group A");
Thread t1 = new Thread(tg1,new MyRunnable(),"one");
Thread t2 = new Thread(tg1,new MyRunnable(),"two");
Thread t3 = new Thread(tg1,new MyRunnable(),"three");
Les trois threads appartiennent au même groupe tg1 de nom
"Group A".
 tg1 représente l'objet groupe de threads,
 MyRunnable est une classe qui implémente l'interface
Runnable
 "one", "two" and "three" sont les noms des threads.
Maintenant, il est possible d'interrompre les trois threads par
une seule ligne de code.
Thread.currentThread().getThreadGroup().interrupt();
HASSOUNI Larbi 106

Threads 53
Exemple de programme utilisant ThreadGroup
public class ThreadGroupDemo implements Runnable{
@Override
public void run(){
while(!Thread.currentThread().interrupted()){
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args){
ThreadGroupDemo runnable = new ThreadGroupDemo();
ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");
Thread t1 = new Thread(tg1, runnable, "one");
t1.start();
Thread t2 = new Thread(tg1, runnable, "two");
t2.start();
Thread t3 = new Thread(tg1, runnable, "three");
t3.start();
System.out.println("Thread Group name : " + tg1.getName());
tg1.list();
tg1.interrupt();
}
}
HASSOUNI Larbi 107

Shutdown Hook
• The shutdown hook can be used to perform cleanup resource
or save the state when JVM shuts down normally or abruptly.
Performing clean resource means closing log file, sending
some alerts or something else. So if you want to execute some
code before JVM shuts down, use shutdown hook.
• When does the JVM shut down?
The JVM shuts down when:
 user presses ctrl+c on the command prompt
 System.exit(int) method is invoked
 user logoff
 user shutdown etc.

HASSOUNI Larbi 108

Threads 54
The addShutdownHook(Runnable r) method

The addShutdownHook() method of Runtime class is used to register the thread with the
Virtual Machine.
Syntax: public void addShutdownHook(Runnable r){}
The object of Runtime class can be obtained by calling the static factory method
getRuntime(). For example:
Runtime r = Runtime.getRuntime();

Factory method
The method that returns the instance of a class is known as
factory method.

HASSOUNI Larbi 109

Simple example of Shutdown Hook


class MyThread extends Thread{
public void run(){
System.out.println("shut down hook task completed..");
}
}
public class TestShutdown1{
public static void main(String[] args)throws Exception {
Runtime r=Runtime.getRuntime();
r.addShutdownHook(new MyThread());
System.out.println("Now main sleeping... press ctrl+c to exit");
try{Thread.sleep(3000);}catch (Exception e) {}
} }
Note: The shutdown sequence can be stopped by invoking the halt(int)
method of Runtime class.
HASSOUNI Larbi 110

Threads 55
Same example of Shutdown Hook by annonymous class:

public class TestShutdown2{


public static void main(String[] args)throws Exception {
Runtime r=Runtime.getRuntime();
r.addShutdownHook(new Runnable(){
public void run(){
System.out.println("shut down hook task completed..");
}
}
);
System.out.println("Now main sleeping... press ctrl+c to exit");
try{Thread.sleep(3000);}catch (Exception e) {}
}
}
HASSOUNI Larbi 111

Priorités

HASSOUNI Larbi 112

Threads 56
Principe de base
• Si plusieurs threads de même priorité sont en
exécution, on ne peut pas prévoir quel thread va
prendre la main
• S’ils sont en attente d’exécution, un thread de
plus grande priorité prendra toujours la main
avant un autre thread de priorité plus basse
• Cependant, il peut arriver exceptionnellement
qu’un thread continue son exécution alors que
des threads de priorité supérieure sont en attente
d’exécution

HASSOUNI Larbi 113

Niveaux de priorité
• Un nouveau thread a la même priorité que le
thread qui l’a créé
• En général, tous les threads ont la même priorité
(NORM_PRIORITY =5)
• Il faut faire appel à la méthode setPriority si
on veut modifier cette priorité par défaut
• Le paramètre de setPriority doit être
compris entre MIN_PRIORITY(1) et
MAX_PRIORITY(10)

HASSOUNI Larbi 114

Threads 57
Threads et exceptions

Threads et exceptions

• Si une exception n’est pas traitée (par un


bloc try-catch), elle interrompt
l’exécution du thread courant mais pas des
autres threads

• La méthode run ne peut déclarer lancer


une exception contrôlée car elle redéfinit
une méthode sans clause « throws »

HASSOUNI Larbi 116

Threads 58
Depuis Java 5, Il existe l'interface
UncaughtExceptionHandler qui contient une seule
méthode, uncaughtException(Thread t, Throwable e),
et qui permet de récupérer les exceptions non gérées
avant que le thread ne meure définitivement.

Vous pouvez alors définir votre propre gestionnaire


d'exceptions non gérées et informer vos threads que
celui-ci existe grâce à la méthode
setDefaultUncaughtExceptionHandler().
HASSOUNI Larbi 117

Nested Classes
Modifier and Class and Description
Type
static class Thread.State A thread state.
static interface Thread.UncaughtExceptionHandler Interface for
handlers invoked when a Thread abruptly
terminates due to an uncaught exception.
@FunctionalInterface
public static interface Thread.UncaughtExceptionHandler{
void uncaughtException(Thread t, Throwable e);
}

Method invoked when the given thread terminates due to


the given uncaught exception.
HASSOUNI Larbi 118

Threads 59
setUncaughtExceptionHandler
public void setUncaughtExceptionHandler(Thread.
UncaughtExceptionHandler eh)
Set the handler invoked when this thread abruptly terminates due to
an uncaught exception.
A thread can take full control of how it responds to uncaught
exceptions by having its uncaught exception handler explicitly set. If
no such handler is set then the thread's ThreadGroup object acts as
its handler.
Parameters:
eh : the object to use as this thread's uncaught exception handler.
If null then this thread has no explicit handler.

HASSOUNI Larbi 119

getUncaughtExceptionHandler
public Thread.UncaughtExceptionHandler getUnca
ughtExceptionHandler()
Returns the handler invoked when this thread abruptly
terminates due to an uncaught exception. If this thread has
not had an uncaught exception handler explicitly set then
this thread's ThreadGroup object is returned, unless this
thread has terminated, in which case null is returned.
Returns:
the uncaught exception handler for this thread

HASSOUNI Larbi 120

Threads 60
setDefaultUncaughtExceptionHandler
public
static void setDefaultUncaughtExceptionHandler(Thread.U
ncaughtExceptionHandler eh)
Set the default handler invoked when a thread abruptly terminates due to an
uncaught exception, and no other handler has been defined for that thread.
Uncaught exception handling is controlled first by the thread, then by the
thread's ThreadGroup object and finally by the default uncaught exception handler.
If the thread does not have an explicit uncaught exception handler set, and the
thread's thread group (including parent thread groups) does not specialize its
uncaughtException method, then the default handler's uncaughtException method
will be invoked.
Parameters:
eh - the object to use as the default uncaught exception handler. If null then there is
no default handler.

HASSOUNI Larbi 121

getDefaultUncaughtExceptionHandler
public
static Thread.UncaughtExceptionHandler getD
efaultUncaughtExceptionHandler()
Returns the default handler invoked when a thread abruptly
terminates due to an uncaught exception. If the returned
value is null, there is no default.
Returns:
the default uncaught exception handler for all threads

HASSOUNI Larbi 122

Threads 61
import java.lang.Thread.UncaughtExceptionHandler;

public class MyUncaughtExceptionHandler implements


UncaughtExceptionHandler{

public void uncaughtException(Thread t, Throwable e) {


System.out.println(t.getName() + ": Une exception de type
: " +e.getClass().getName());
}
}

HASSOUNI Larbi 123

import java.lang.Thread.UncaughtExceptionHandler;

public class MyUncaughtExceptionHandler2 implements


UncaughtExceptionHandler{

public void uncaughtException(Thread t, Throwable e) {


System.out.println("!!!!!!!! " + t.getName() + ":
!!!!!!!!Une exception de type : " +e.getClass().getName() );
}
}

HASSOUNI Larbi 124

Threads 62
import java.util.Random;
public class ThreadException extends Thread{
public ThreadException(String name){
setName(name);
setDefaultUncaughtExceptionHandler(new
MyUncaughtExceptionHandler());
}
public void run(){
Random rand = new Random();
while(true){
int cas = rand.nextInt(5);

switch(cas){
case 0 : int i = 10 / 0; break;
case 1 : Object str = "toto"; double d = (double) str;
break;
default :
System.out.println(getName() + ": aucune erreur...");
break;
} } }}

HASSOUNI Larbi 125

public class Main {


public static void main(String[] args){

for(int i = 0; i < 6; i++){


Thread t = new ThreadException("Thread-" + i);
if (i%2 == 0){
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler2());
}
t.start();
}
}
}

HASSOUNI Larbi 126

Threads 63
Utilisation de EXECUTORS

Bien à vous

HASSOUNI Larbi 127

Threads 64
Les flux d’entrée/sortie
En Java

Préparé par : Larbi HASSOUNI

• Traditionnellement les mécanismes


d’entrées/sorties des langages de programmation
permettent l’échange de données entre le
programme et la mémoire secondaire (disque) au
moyen de fichiers
• JAVA définit la notion de flux qui permet
l’échange d’informations entre le programme et
des entités de nature très différentes:
– les mémoires centrale ou secondaire
– Un autre programme en utilisant Pipe
– un ordinateur distant
– Etc.

L.HASSOUNI 2

Flux d'E/S 1
Flux (Streams)

• Un flux est un objet qui permet l’échange


de données entre un programme et un
dispositif d’entrée/sortie ou un fichier
– Si les données rentrent dans un programme, le
flux est appelé flux d’entrée (input stream)
– Si les données sortent du programme, le flux est
appelé flux de sortie (output stream),

L.HASSOUNI 3

keyboard
standard
input stream
CPU

standard
output MEM
monitor stream
terminal file
console input
stream
LOAD HDD
READ
Streams file
files output
stream
L.HASSOUNI SAVE
4
WRITE

Flux d'E/S 2
Flux d’entrée et de sortie standards
• Un flux d’entrée peut provenir du clavier ou d’un
fichier
– System.in est le flux d’entrée connecté au clavier
Scanner kb = new Scanner(System.in);

• Un flux de sortie peut être dirigé vers l’écran ou


un fichier
– System.out est le flux de sortie connecté à l’écran,
System.out.println("Output stream");

L.HASSOUNI 5

Comment est manipulé un fichier d’E/S en Java?


Un objet File encapsule les propriétés d’un fichier ou d’un chemin, mais ne contient pas les
méthodes pour lire/écrire les données à partir/dans le fichier.
Pour effectuer ces operations d’E/S, vous devez créer des objets en utilisant des classes
d’E/S appropriées.
Scanner input = new Scanner(new File("temp.txt"));
System.out.println(input.nextLine());

Program
Input stream
Input object
created from an 01011…1001 File
input class

Output object
created from an 11001…1011
File
output class
Output stream
PrintWriter output = new PrintWriter("temp.txt");
PrintWriter output =101");
output.println("Java new PrintWriter("temp.txt");
output.println("Java 101");
output.close();
L.HASSOUNI 6
output.close();

Flux d'E/S 3
Fichiers textes et fichiers binaires
• Les fichiers destinés à être lu par un humain et qui
peuvent être lus et écrits par un éditeur de texte
sont appelés fichiers textes
– Les fichiers textes sont ausi appelés fichier ASCII
puisque les données qu’ils contiennent utilisent le
schema d’encodage ASCII
– L’avantage des fichiers texte est qu’ils sont souvent
identiques sur tous les ordinateurs, par consequent on
peut les déplacer d’un ordinateur à l’autre

L.HASSOUNI 7

Fichiers textes et fichiers


binaires
• Les fichiers qui sont destinés à être lu par un
programme et qui consistent en une séquence de digits
binaires sont appelés fichiers binaires

– Les fichiers binaires sont destinés à être lus sur le même type
d’ordinateur, et avec le même langage de programmation
que celui sur lequel le fichier a été crée la première fois

– Un avantage des fichiers binaires c’est qu’ils sont plus


faciles à traiter que les fichiers textes

– Au contraire de la plupart des fichiers binaire créé par


d’autres langages, les fichiers binaires Java ont l’avantage
d’être indépendants de la plateforme.

L.HASSOUNI 8

Flux d'E/S 4
Fichiers textes et fichiers binaires
• Un programme source java est un fichier texte que vous pouvez
lire en utilisant un éditeur de texte.
• Par contre un fichier .class qui mémorise le bytecode de la
classe est un fichier binaire et est lu par la JVM.

• On peut imaginer un fichier texte comme une séquence de


caractères, et un fichier binaire comme une séquence de bits
• Par exemple, l’entier 199 est stocké comme une séquence de
trois caractères: '1', '9', '9' dans un fichier texte.
Par contre, dans un fichier binaire, le même entier est stocké
comme une valeur de type byte en format binaire (11000111 =
C7 en hexadécimal).

L.HASSOUNI 9

E/S binaire
Une E/S texte nécessite un encodage et un décodage.
Lorsqu’on écrit un caractère dans un fichier texte, la JVM
convertit le code Unicode en utilisant un encodage
spécifique au fichier qui depend de l’os utilisé et on
effectue l’operation inverse durant la lecture d’un
caractère.
Une E/S binaire ne nécessite pas cette conversion.
Lorsque vous écrivez un octet dans un fichier, l’octet
original est écrit tel quel dans le fichier et lorsque vous
lisez un octet à partir d’un fichier, l’octet exact tel quel
stocké dans le fichier est retourné.
10

Flux d'E/S 5
Text I/O program

The Unicode of Encoding/ The encoding of the character


(a) is stored in the file
the character Decoding
e.g. "199" 00110001 00111001 00111001
,
0x31 0x39 0x39

Binary I/O program

(b) A byte is read/written The same byte in the file

e.g. 199 00110111


,
0xC7

L.HASSOUNI 11

Classes d’E/S binaire


FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

La classe abstraite InputStream est la classe racine pour la lecture


des données binaire.
La classe abstraite OutputStream est la classe racine pour écrire des
données binaire.
L.HASSOUNI 12

Flux d'E/S 6
Classe <<interface>>
AutoCloseable
InputStream
Object
<<Interface>>
Closeable

<<abstract>>
InputStream

L.HASSOUNI 13

API InputStream(1)
int available()
Returns an estimate of the number of bytes that can be read (or
skipped over) from this input stream without blocking by the next
invocation of a method for this input stream.
void close()
Closes this input stream and releases any system resources
associated with the stream
void mark(int readlimit)
Marks the current position in this input stream.
boolean markSupported()
Tests if this input stream supports the mark and reset methods.
L.HASSOUNI 14

Flux d'E/S 7
API InputStream(2)
public abstract int read() throws IOException
Reads the next byte of data from the input stream. The value byte is returned as
an int in the range 0 to 255. If no byte is available because the end of the stream has
been reached, the value -1 is returned. This method blocks until input data is available,
the end of the stream is detected, or an exception is thrown. A subclass must provide an
implementation of this method.
Int read(byte[] b)
Reads some number of bytes from the input stream and stores
them into the buffer array b.
Void reset()
Repositions this stream to the position at the time
the mark method was last called on this input stream.

long skip(long n)
Skips over and discards n bytes of data from this input stream
L.HASSOUNI 15

Classe <<interface>>
AutoCloseable
OutputStream
Object
<<Interface>> <<Interface>>
Closeable Flushable

<<abstract>>
OutputStream

L.HASSOUNI 16

Flux d'E/S 8
API OutputStream
public void close()
Closes this output stream and releases any system resources associated with this stream.

public void flush()

Flushes this output stream and forces any buffered output bytes to be written out.

public void write(byte[] b)


Writes b.length bytes from the specified byte array to this output stream.
public void write(byte[] b, int off, int len)

Writes len bytes from the specified byte array starting at offset off to this output stream.

public abstract void write(int b)

Writes the specified byte to this output stream.

L.HASSOUNI 17

FileInputStream/FileOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

FileInputStream/FileOutputStream permettent la lecture/ecriture à


partir/dans des fichiers.
Toutes les méthodes des classes FileInputStream et
FileOuptputStream sont héritées à partir de leur superclasse.
L.HASSOUNI 18

Flux d'E/S 9
FileInputStream
Pour construire un objet FileInputStream, utilisez les
constructeurs suivants:
public FileInputStream(String filename)
public FileInputStream(File file)

L’exception java.io.FileNotFoundException peut être lancée si


vous cherchez à créer un objet FileInputStream avec un fichier
inexistant.

L.HASSOUNI 19

FileOutputStream
Pour construire un objet FileOutputStream, utilisez les constructeurs
suivants:

public FileOutputStream(String filename)


public FileOutputStream(File file)
public FileOutputStream(String filename, boolean append)
public FileOutputStream(File file, boolean append)

Si le fichier n’existe pas, un nouveau fichier sera crée.


Si le fichier existe déjà, les deux premiers constructeurs effacent son
contenu.
Pour consever le contenu du fichier et lui ajouter de nouvelles
données, utilisez les deux derniers constructeurs en donnant “true” au
paramètre “append”.
L.HASSOUNI 20

Flux d'E/S 10
package mypkg;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class My03FileInputStream {
public static void main(String[] args) {
String srcFile = "src\\pkg01\\My02ScannerPrintWriter.java";

try (FileInputStream fin = new FileInputStream(srcFile)) {


byte byteData;
while ((byteData = (byte) fin.read()) != -1) {
System.out.print((char) byteData); }
} catch (FileNotFoundException e) { ;
} catch (IOException e) { e.printStackTrace();
}
}
}

L.HASSOUNI 21

package pkg01;
import java.io.*;
public class My031FileOutputStream {
public static void main(String[] args) throws IOException
{
// Create an output stream to the file
FileOutputStream output = new FileOutputStream("temp.dat");
// Output values to the file
for (int i = 1; i <= 10; i++) output.write(i);
// Close the output stream
output.close();

// Create an input stream for the file


FileInputStream input = new FileInputStream("temp.dat");
// Read values from the file
int value;
while ((value = input.read()) != -1)
System.out.print(value + " ");
// Close the input stream
input.close();
}} L.HASSOUNI 22

Flux d'E/S 11
FilterInputStream/FilterOutputStream
FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

Filter streams

L.HASSOUNI 23

Filter streams sont utilisées pour filtrer les octets en vue


de réaliser certains objectifs.
La méthode read de la classe de base InputStream ne
permet de lire que des octets.
Une classe filter vous permet de lire des données de type
int, double, et String au lieu d’octets et caractères.
Les classes FilterInputStream et FilterOutputStream sont
les classes de base pour filtrer les données.
Pour traiter les données numériques de type primitifs,
utiliser DataInputStream et DataOutputStream pour
filtrer les octets.

L.HASSOUNI 24

Flux d'E/S 12
DataInputStream/DataOutputStream
DataInputStream lit les octets à partir du flux et les
convertit vers le type primitif approprié ou en String.

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

DataOutputStream convertit les valeurs de type


primitif ou String en octets puis écrit ces octets
dans le flux.
L.HASSOUNI 25

Méthodes de la classe DataInputStream

DataInputStream
extends FilterInputStream and
implements the DataInput interface.

L.HASSOUNI 26
26

Flux d'E/S 13
DataInputStream
DataInputStream extends FilterInputStream
and implements the DataInput interface.

InputStream java.io.DataInput

+readBoolean(): boolean Reads a Boolean from the input stream.


+readByte(): byte Reads a byte from the input stream.
FilterInputStream
+readChar(): char Reads a character from the input stream.
+readFloat(): float Reads a float from the input stream.
+readDouble(): float Reads a double from the input stream.
DataInputStream +readInt(): int Reads an int from the input stream.
+DataInputStream( +readLong(): long Reads a long from the input stream.
in: InputStream) +readShort(): short Reads a short from the input stream.
+readLine(): String Reads a line of characters from input.
+readUTF(): String Reads a string in UTF format.

L.HASSOUNI 27

Méthodes de la classe DataOutputStream

DataOutputStream
extends FilterOutputStream and
implements the DataOutput interface.

L.HASSOUNI 28
28

Flux d'E/S 14
DataOutputStream
DataOutputStream extends FilterOutputStream and implements the
DataOutput interface.
OutputStream java.io.DataOutput

+writeBoolean(b: Boolean): void Writes a Boolean to the output stream.


+writeByte(v: int): void Writes to the output stream the eight low-order bits
FilterOutputStream of the argument v.
+writeBytes(s: String): void Writes the lower byte of the characters in a string to
the output stream.
+writeChar(c: char): void Writes a character (composed of two bytes) to the
DataOutputStream output stream.
+DataOutputStream( +writeChars(s: String): void Writes every character in the string s, to the output
out: OutputStream) stream, in order, two bytes per character.
+writeFloat(v: float): void Writes a float value to the output stream.
+writeDouble(v: float): void Writes a double value to the output stream.
+writeInt(v: int): void Writes an int value to the output stream.
+writeLong(v: long): void Writes a long value to the output stream.
+writeShort(v: short): void Writes a short value to the output stream.
+writeUTF(s: String): void Writes two bytes of length information to the output
stream, followed by the UTF representation of
every character in the string s.
29
L.HASSOUNI

Carctères et Strings dans les E/S binaires

Un code Unicode consiste en deux octets.

La méthode writeChar(char c) écrit le code Unicode du caractère c

dans le flux de sortie.

La méthode writeChars(String s) écrit le code Unicode de chaque

caractère de la chaine s dans le flux.

L.HASSOUNI 30

Flux d'E/S 15
pourquoi UTF-8? Qu’est ce que UTF-8?
UTF-8 est une méthode de codification des caractères qui permet aux
systèmes d’utiliser à la fois le code ASCII et l’UNICODE de manière
efficace.

La plupart des systèmes d’exploitation utilisent le code ASCII.

Java utilise Unicode.

Le jeu de caractères ASCII est un sous ensemble du jeu de caractères


UNICODE.

Puisque la plupart des applications ont uniquement besoin du jeu de


caractères ASCII, représenter un caractère ASSCII sur 8 bits en un
caractère UNICODE sur 16 bits est un gaspillage d’espace disque.
L.HASSOUNI 31

UTF-8 est une méthode de codage qui permet de stocker un caractère


en utilisant 1, 2, ou 3 octets.

Les valeurs ASCII (<= 0x7F) sont stockées sur un octet.

Les valeurs Unicode qui sont inférieures à 0x7FF sont stockées sur
deux octets. Les autres valeurs Unicode sont codées sur 3 octets.

L.HASSOUNI 32

Flux d'E/S 16
Utilisation de DataInputStream/DataOutputStream
Les classes Data streams sont utilisées comme des enveloppes pour les
flux d’E/S pour filtrer les données dans le flux original.
Ils sont créés en utilisant les constructeurs ci-dessous:
public DataInputStream(InputStream instream)
public DataOutputStream(OutputStream outstream)

Les instructions ci-dessous créent deux objets data streams.


La première crée un ojet data stream pour le fichier in.dat;
La seconde crée un objet data stream pour le fichier out.dat.
DataInputStream infile =
new DataInputStream(new FileInputStream("in.dat"));
DataOutputStream outfile =
new DataOutputStream(new FileOutputStream("out.dat"));
33
L.HASSOUNI

L’ordre et le format

Attention: vous devez lire les données dans le même


ordre et en utilisant le même format utilisés lors de leur
écriture dans le fichier.

Par exemple, puisque les noms sont écrits en format


UTF-8 en utilisant la méthode writeUTF(), vous devez
lire les noms en utilisant la méthode readUTF()
correspondante.

L.HASSOUNI 34

Flux d'E/S 17
import java.io.*;
public class My04DataInputOutputStream {
public static void main(String[] args) throws IOException {
// Create an output stream for file temp.dat
DataOutputStream output =
new DataOutputStream(new FileOutputStream("grade.dat"));
// Write student test scores to the file
output.writeUTF("Moha");output.writeDouble(15.50);
output.writeUTF("Manolo");output.writeDouble(17.50);
output.writeUTF("Toto");output.writeDouble(12.00);
// Close output stream
output.close();

// Create an input stream for file temp.dat


DataInputStream input =
new DataInputStream(new FileInputStream("grade.dat"));
// Read student test scores from the file
System.out.println(input.readUTF() + " " + input.readDouble());
System.out.println(input.readUTF() + " " + input.readDouble());
System.out.println(input.readUTF() + " " + input.readDouble());
input.close();
}}
L.HASSOUNI 35

Détecter la fin du fichier


• Attention: si vous tentez de lire les données
au delà de la fin d’un fichier, l’exception
EOFException sera lancée.
• Comment tester la fin d’un fichier?
– vous pouvez utiliser input.available().
– input.available() = = 0 indique qu’on a atteint
la fin du fichier.

L.HASSOUNI 36

Flux d'E/S 18
package pkg01;
import java.io.*;
public class My05DetectEndOfFile {
public static void main(String[] args) {
try {
DataOutputStream output =
new DataOutputStream(new FileOutputStream("test.dat"));
output.writeDouble(4.5);
output.writeDouble(43.25);
output.writeDouble(3.2);
output.close();

DataInputStream input =
new DataInputStream(new FileInputStream("test.dat"));
while (true) {
System.out.println(input.readDouble());
}
}
catch (EOFException ex) { System.out.println("All data were
read"); }
catch (IOException ex) { ex.printStackTrace(); }
}
}
L.HASSOUNI 37

import java.io.*;
public class My06DetectEndOfFile2 {
public static void main(String[] args) {
try {
DataOutputStream output =new DataOutputStream(new
FileOutputStream("test.dat"));
output.writeDouble(4.5);
output.writeDouble(43.25);
output.writeDouble(3.2);
output.close();
DataInputStream input =new DataInputStream(new
FileInputStream("test.dat"));
while (input.available()>0) {
System.out.println(input.readDouble());
}
}
catch (EOFException ex) { System.out.println("All data were
read"); }
catch (IOException ex){ex.printStackTrace();}
} }
L.HASSOUNI 38

Flux d'E/S 19
Copier un Fichier
Ce cas d’étude développe un programme qui copie un fichier.
L’utilisateur doit fournir le nom du fichier source et celui du fichier
destination comme argument dans la ligne de commande

java Copy source target

le programme copie le fichier source dans le fichier destination et


affiche le nombre d’octets dans le fichier.
Si le fichier source n’existe pas le programme informe l’utilisateur
de son inexistence.
Si le fichier destination existe le programme informe l’utilisateur de
son existence.

39
L.HASSOUNI

public class M07CopyFile {


// Main method, args[0] for sourcefile , args[1] for target file
public static void main(String[] args) throws IOException {
// Check command-line parameter usage
if (args.length != 2) {
System.out.println( "Usage: java Copy srcFile targetfile");
System.exit(1);
}

// Check if source file exists


File sourceFile = new File(args[0]);
if (!sourceFile.exists()) {
System.out.println("Source file " + args[0] + " does not exist");
System.exit(2);
}

// Check if target file exists


File targetFile = new File(args[1]);
if (targetFile.exists()) {
System.out.println("Target file " + args[1] + " already exists");
System.exit(3);
}

L.HASSOUNI 40

Flux d'E/S 20
//Create an input stream
BufferedInputStream input =
new BufferedInputStream(new FileInputStream(sourceFile));

// Create an output stream


BufferedOutputStream output =
new BufferedOutputStream(new FileOutputStream(targetFile));

// Continuously read a byte from input and write it to output


int r, numberOfBytesCopied = 0;
while ((r = input.read()) != -1) {
output.write((byte)r);
numberOfBytesCopied++;
}

// Close streams
input.close(); output.close();

// Display the file size


System.out.println(numberOfBytesCopied + " bytes copied");
}
}

L.HASSOUNI 41

BufferedInputStream/BufferedOutputStream
réduisent le nombre d’accès au disque
Using buffers to speed up I/O

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

BufferedInputStream/BufferedOutputStream ne contiennent pas de


nouvelles méthodes. Toutes les methodes de
BufferedInputStream/BufferedOutputStream sont héritées des classes
InputStream/OutputStream . L.HASSOUNI 42

Flux d'E/S 21
Construction des objets
BufferedInputStream/BufferedOutputStream

// Create a BufferedInputStream
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int bufferSize)

// Create a BufferedOutputStream
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStreamr out, int bufferSize)

L.HASSOUNI 43

Serialisation: Object I/O


DataInputStream/DataOutputStream vous permettent d’effectuer des
E/S des valeurs de type primitifs et des strings.
ObjectInputStream/ObjectOutputStream vous permettent d’effectuer
les operations d’E/S pour les objets,

FileInputStream
DataInputStream
InputStream FilterInputStream
BufferedInputStream
ObjectInputStream
Object
FileOutputStream BufferedOutputStream

OutputStream FilterOutputStream DataOutputStream

ObjectOutputStream PrintStream

L.HASSOUNI 44

Flux d'E/S 22
Les classes ObjectInputStream/ObjectOutputStream peuvent être
utilisées pour lire/écrire des objets sérialisables.

DataInputStream/DataOutputStream vous permettent de lire/écrire


à partir/dans des flux d’E/S des données de type primitif ou des
strings.

ObjectInputStream/ObjectOutputStream vous permettent


d’effectuer des operations d’E/S pour des objets sérialisable aussi
bien que pour les données de type primitif ou les strings.

Puisque ObjectInputStream/ ObjectOutputStream contiennent


toutes les méthodes de DataInputStream/ DataOutputStream, vous
pouvez entièrement remplacer DataInputStream/DataOutputStream
avec ObjectInputStream/ObjectOutputStream.

L.HASSOUNI 45

Méthodes de la classe ObjectInputStream

ObjectInputStream
extends InputStream and
implements two interfaces
the ObjectInput interface and
the ObjectStreamConstants interface.

L.HASSOUNI 46
46

Flux d'E/S 23
ObjectInputStream
ObjectInputStream extends InputStream and
implements ObjectInput and ObjectStreamConstants.

java.io.InputStream ObjectStreamConstants

java.io.DataInput

java.io.ObjectInputStream java.io.ObjectInput

+ObjectInputStream(in: InputStream) +readObject(): Object Reads an object.

ObjectInputStream peut lire des objets, valeurs de type primitifs et strings.


L.HASSOUNI 47

Méthodes de la classe ObjectOutputStream

ObjectOutputStream
extends OutputStream and
implements two interfaces
the ObjectOutput interface and
the ObjectStreamConstants interface.

L.HASSOUNI 48
48

Flux d'E/S 24
ObjectOutputStream
ObjectOutputStream extends OutputStream and
implements ObjectOutput and ObjectStreamConstants.

java.io.OutputStream ObjectStreamConstants

java.io.DataOutput

java.io.ObjectOutputStream java.io.ObjectOutput

+ObjectOutputStream(out: OutputStream) +writeObject(o: Object): void Writes an object.

ObjectOutputStreampeut écrire des objets, des valeurs de type


primtifs et des strings.
49
L.HASSOUNI

Utilisation des Object Streams


You devez enveloper un objet
ObjectInputStream/ObjectOutputStream sur n’importe quel objet
InputStream/OutputStream en utilisant les constructeurs ci-dessous:

// Create an ObjectInputStream
public ObjectInputStream(InputStream in)

// Create an ObjectOutputStream
public ObjectOutputStream(OutputStream out)

L.HASSOUNI 50

Flux d'E/S 25
Exemple de programmes
package pkg01;
import java.io.Serializable;
class Personne implements Serializable {
private String nom ;
private String genre;
private double taille;
public Personne(String nom, String genre, double taille){
this.nom = nom;
this.genre = genre;
this.taille = taille; }

public void setNom(String nom) {


this.nom = nom;
}

@Override
public String toString() {
return "Nom: " + this.nom + ", Gendre: " + this.genre + ", Taille: " + this.taille;
}}L.HASSOUNI 51

Ecriture d'objet dans un fichier


package objectoutputstream;
import java.io.Serializable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class My07ObjectWrite {
public static void main(String[] args) {
Personne p1 = new Personne("Moha", "Male", 1.7);
Personne p2 = new Personne("Toto", "Male", 1.7);
Personne p3 = new Personne("Manolo", "Femelle", 1.4);
File fileObject = new File("person.ser");
try (ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream(fileObject))) {
oos.writeObject(p1);
oos.writeObject(p2);
oos.writeObject(p3);
} catch (IOException e) {e.printStackTrace(); }
}}

L.HASSOUNI 52

Flux d'E/S 26
Lecture d'objet à partir un fichier
package objectoutputstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class M09ObjectRead {
public static void main(String[] args) {
File fileObject = new File("person.ser");
try (ObjectInputStream ois = new ObjectInputStream(new
FileInputStream(fileObject))) {
Personne p1 = (Personne) ois.readObject();
Personne p2 = (Personne) ois.readObject();
Personne p3 = (Personne) ois.readObject();
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
} catch (Exception e) {e.printStackTrace(); }
}}
L.HASSOUNI 53

Ecriture types primitifs avec


ObjectOutputStream
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class My10ObjectOutputStreamPrimitifs {


public static void main(String[] args) throws IOException {
// Create an output stream for file object.dat
ObjectOutputStream output =
new ObjectOutputStream(new
FileOutputStream("objectprimitif.dat"));

// Write a string, double value, and object to the file


output.writeUTF("Moha");
output.writeDouble(85.5);
output.writeObject(new java.util.Date());

// Close output stream


output.close();
}} L.HASSOUNI 54

Flux d'E/S 27
Lecture types primitifs avec ObjectOutputStream
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class My11ObjectInputStreamPrimitifs {


public static void main(String[] args)
throws ClassNotFoundException, IOException {
// Create an input stream for file object.dat
ObjectInputStream input =
new ObjectInputStream(new FileInputStream("objectprimitif.dat"));

// Read a string, double value, and object from the file


String name = input.readUTF();
double score = input.readDouble();
java.util.Date date = (java.util.Date)(input.readObject());
System.out.println(name + " " + score + " " + date);

// Close input stream


input.close();
} }

L.HASSOUNI 55

• La méthode readObject() peut lancer l’exception


java.lang.ClassNotFoundException, parce que lorsque la JVM
restore l’objet, il commence d’abord par charger sa classe au
cas où elle n’a pas été chargée auparavent. Puisque
ClassNotFoundException est une exception controlee, la méthode
main declare qu’elle la lance.
• Un objet ObjectInputStream est crée pour lire à partir du fichier
object.dat.
• Vous devez lire le fichier dans le même ordre et format utilisés
lors de l’écriture.
• Puisque readObject() retourne un objet, on lui a appliqué un
opérateur cast pour le convertir en Date et l’assigner à une
variable Date.

L.HASSOUNI 56

Flux d'E/S 28
L’interface Serializable
• Pas n’importe quel objet peut être écrit dans un flux de sortie.
• Un objet qui peut être écrit dans un flux de sortie est dit
sérialisable.
• Pour qu’un objet soit sérialisable, il faut qu’il soit instance de
l’interface java.io.Serializable autrement dit sa classe doit
implementer Serializable.
• L’interface Serializable est une interface “marker” ou “tag”. Il
ne contient aucune méthode, par conséquent vous n’avez pas à
ajouter du code supplémentaire à votre classe qui l’implémente

L.HASSOUNI 57

• Une interface “Marker” est utilisé pour indiquer au


compilateur et à la JVM d’effectuer des opérations
supplémentaires sur ses objets instances.

• L’implémetation de l’interface Serializable active le


mécanisme de serialization qui consiste à automatiser le
processus de stockages des objets et tableaux.

L.HASSOUNI 58

Flux d'E/S 29
• Pour percevoir l’intérêt de cette automatisation de stockage
des objets, imaginez que vous devez stocker un ArrayList
d’objets.
• Pour accomplir cette tâche, vous devez stocker chaque
élément de la liste. Et chaque élément est un objet qui peut
contenir des attributs objets.
• Java vous évite de faire cette operation, qui peut être
compliquée et ennuyeuse, en fournissant un mécanisme
prédéfinie pour automatiser l’écriture des objets dans un
flux. Ce processu est désigné par “sérailisation d’objets”
qui est implémenté dans ObjectOutputStream.
• Le processus de lecture des objets est désigné par
“deserialization d’objet”, et est implémenté dans
ObjectInputStream.

L.HASSOUNI 59

• Plusieurs classes dans l’API Java implémentent l’interface


Serializable.

• Toutes les classes wrapper classes pour les valeurs de type


primif (Byte, Short, Integer, Long, Float, Double, Character
et Boolean), java.math.BigInteger, java.math.BigDecimal,
java.lang.String, java.lang.StringBuilder,
java.lang.StringBuffer, java.util.Date, et java.util.ArrayList
implementent java.io.Serializable.

• Essayer de stocker un objet non sérialisable causera le


lancement de l’exception NotSerializableException.

L.HASSOUNI 60

Flux d'E/S 30
• La sérialisation d’un objet consiste à stocker:
– le code de sa classe qui consiste en son nom et sa
“signature”;
– Les valeurs de ses variables d’instances de types primitfs.
– Des informations sur ses attributs de type objets.
• Les valeurs de ses variables static ne sont pas
stockées.
• Remarque1:
– Si un objet instance Serialisable contient un attribut non
sérialisable, l’objet est non sérialisable.
– Pour qu’il soit sériasable, il faut déclarer l’attribut non
sérialsable avec le mot clé « transient » pour signaler à
la JVM d’ignorer la valeur de tel attribut lors de la
sérialisation de l’objet,
L.HASSOUNI 61

• Considerons la classe ci-dessous:


public class C implements java.io.Serializable {
private int v1;
private static double v2;
private transient A v3 = new A();
}
class A { } // A is not serializable

Lorsqu’un objet instance de la classe C est sérialisé, seule la


valeur de v1 est sérialisée.
La variable v2 n’est pas sérialisée car elle est déclarée static;
Et la variable v3 n’est pas sérialisée car elle est marquée par
transient. Si v3 n’avait pas été marquée transient, l’excéption
java.io.NotSerializableException serait lancée.

L.HASSOUNI 62

Flux d'E/S 31
• Remarque2:

• Lorsqu’un objet est écrit pour la première fois, un


numéro de série est créé pour lui. La JVM écrit le
contenu complet de l’objet avec le numéro de série
dans le flux de sortie

• Lors des prochaines écritures du même objet, seul


son numéro de série est écrit,et lorsque les objects
sont lus, leurs références sont les mêmes
puisqu’un seul objet est crée dans la mémoire.

L.HASSOUNI 63

Serialisation de tableaux
• Un tableau est sérialisable si tous ses éléments
sont sérialisables.
• Un tableau entier peut être sérialsé dans un fichier
en utilisant la méthode writeObject de l’objet
ObjectOutputStraem.
• Un tableau entier peut être déserialisé en utilisant
la méthode readObject de l’objet
ObjectInputStream.
• L’exemple suivant stocke dans un fichier un
tableau de 5 entier et un tableau de 3 strings puis
les lits pour les afficher sur l’écran.
L.HASSOUNI 64

Flux d'E/S 32
package objectoutputstream;
import java.io.*;
public class My12ObjectStreamForArray {
public static void main(String[] args)
throws ClassNotFoundException, IOException {
int[] numbers = {1, 2, 3, 4, 5};
String[] strings = {"Maha", "Toto", "Manolo"};

//Ecriture des tableaux dans le fichier


try ( ObjectOutputStream output = new
ObjectOutputStream(new FileOutputStream("array.dat",
true));) {
output.writeObject(numbers);
output.writeObject(strings);
}

L.HASSOUNI 65

//Lecture des fichiers à partir du fichier


try ( ObjectInputStream input = new
ObjectInputStream(new FileInputStream("array.dat"));) {
int[] newNumbers = (int[])(input.readObject());
String[] newStrings = (String[])(input.readObject());
for (int i = 0; i < newNumbers.length; i++)
System.out.print(newNumbers[i] + " ");
System.out.println();
for (int i = 0; i < newStrings.length; i++)
System.out.print(newStrings[i] + " ");
}
}
}

L.HASSOUNI 66

Flux d'E/S 33
Exécuter les deux programmes qui suivent

package objectoutputstream;
import java.io.Serializable; import java.io.File;
import java.io.FileOutputStream; import java.io.IOException;
import java.io.ObjectOutputStream;
public class My13ObjectWrite {
public static void main(String[] args) {
Personne p1 = new Personne("Moha", "Male", 1.7);
Personne p2 = new Personne("Toto", "Male", 1.7);
Personne p3 = new Personne("Manolo", "Femelle", 1.4);
Personne p4 = new Personne("Moha", "Male", 1.7);
Personne p5 = p1; Personne p6 = p1;
File fileObject = new File("person.ser");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
fileObject))) {
oos.writeObject(p1); oos.writeObject(p2); oos.writeObject(p3);
oos.writeObject(p4); oos.writeObject(p5); oos.writeObject(p6);
System.out.println("p1 : " + p1); System.out.println("p2 : " + p2);
System.out.println("p3 : " + p3); System.out.println("p4 : " + p4);
System.out.println("p5 : " + p5); System.out.println("p6 : " + p6);
} catch (IOException e) { e.printStackTrace(); } }

L.HASSOUNI 67

package objectoutputstream; import java.io.File;


import java.io.FileInputStream; import java.io.ObjectInputStream;
public class My14ObjectRead {
public static void main(String[] args) {
File fileObject = new File("person.ser");
try (ObjectInputStream ois = new ObjectInputStream(new
FileInputStream(fileObject))) {
Personne p1 = (Personne) ois.readObject();
Personne p2 = (Personne) ois.readObject();
Personne p3 = (Personne) ois.readObject();
Personne p4 = (Personne) ois.readObject();
Personne p5 = (Personne) ois.readObject();
Personne p6 = (Personne) ois.readObject();
System.out.println("p1 : " + p1 + " p2 : " + p2);
System.out.println("p3 : " + p3 + " p4 : " + p4);
System.out.println("p5 : " + p5 + " p6 : " + p6);
System.out.println("===================");
p5.setNom("Habti");
System.out.println("p1 : " + p1 + " p4 : " + p4);
System.out.println("p5 : " + p5 + " p6 : " + p6);
} catch (Exception e) {e.printStackTrace();} }}

L.HASSOUNI 68

Flux d'E/S 34
Fichiers à accès directe
• Tous les flux que nous avons utiliés jusqu’à maintenant
sont connus comme des flux à “Lecture unique” (read-
only) ou à “Ecriture unique” (write-only).
• Le fichier externe qui correspond à ces flux est un
fichier séquentiel qui ne peut pas être mis à jour sans
créer un autre fichier.
• Il est souvent necessaire de modifier un fichier ou
d’insérer de nouveaux enregistrements dans un fichier.
• Java fournit la classe RandomAccessFile qui permet à
un fichier d’être lu ou écrit à une position aléatoire.
• Un fichier qui est ouvert en utilisant la classe
RandomAccessFile est reconnu sous le nom de fichier
à accès direct (random-access file).
L.HASSOUNI 69

Métodes de la classe RandomAccessFile

RandomAccessFile
extends n/a and
implements two interfaces
the DataInput interface and
the DataOutput interface.

L.HASSOUNI 70
70

Flux d'E/S 35
API RandomAccesFile(1)
Constructors
public RandomAccessFile(File file, String mode) throws
FileNotFoundException
Creates a random access file stream to read from, and
optionally to write to, the file specified by the File argument.
public RandomAccessFile(String name, String mode) throws
FileNotFoundException
Creates a random access file stream to read from, and
optionally to write to, a file with the specified name.

L.HASSOUNI 71

Constructeur de la classe RandomAccessFile

RandomAccessFile raf =
new RandomAccessFile("test.dat", "rw"); //autorise la
lecture et l’écriture

RandomAccessFile raf =
new RandomAccessFile("test.dat", "r"); //autorise la
lecture uniquement

L.HASSOUNI 72

Flux d'E/S 36
File Pointer
• Un fichier à accès direct consiste en une séquence d’octets.
• Il existe un marqueur special désigné par “pointeur de fichier” et
qui est positionné sur un de ces octets.
• Une operation de lecture ou écriture concerne l’octet sur lequel est
positionné le pointeur.
• Lorsqu’un fichier est ouvert, le pointeur du fichier est positionné
au debut sur le premier octet du fichier.
• Lorsque vous effectuez une operation de lecture ou d’écriture, le
pointeur avance pour pointer l’octet suivant.
• Par exemple, si vous lisez une valeur de type int en utilisant
readInt(), la JVM lit 4 octets à partir du fichier et le pointeur
avance de 4 positions pour pointer vers l’entier suivant.
L.HASSOUNI 73

file pointer

file byte byte … byte byte byte byte byte … byte byte byte byte byte (A) Before readInt()

file pointer

file byte byte … byte byte byte byte byte … byte byte byte byte byte (B) Before readInt()

L.HASSOUNI 74

Flux d'E/S 37
API RandomAccesFile(2)
Methods
Public void close()
Closes this random access file stream and releases any system resources
associated with the stream.
Public FileChannel getChannel()
Returns the unique FileChannel object associated with this file.

Public FileDescriptor getFD()


Returns the opaque file descriptor object associated with this stream.
Public long getFilePointer()
Returns the current offset in this file.
Public long length()
Returns the length of this file.

L.HASSOUNI 75

Public int read() : Reads a byte of data from this file.


Public int read(byte[] b)
Reads up to b.length bytes of data from this file into an array of
bytes.
Public int read(byte[] b, int off, int len)
Reads up to len bytes of data from this file into an array of bytes.

Public Boolean readBoolean() : Reads a boolean from this file.


Public byte readByte() : Reads a signed eight-bit value from this file.

Public readChar() : Reads a character from this file.


Public double readDouble() : Reads a double from this file.
Public float readFloat() : Reads a float from this file.

L.HASSOUNI 76

Flux d'E/S 38
Public void readFully(byte[] b)
Reads b.length bytes from this file into the byte array, starting at the current
file pointer.
Public void readFully(byte[] b, int off, int len)
Reads exactly len bytes from this file into the byte array, starting at the
current file pointer.
Public int readInt() : Reads a signed 32-bit integer from this file.
Public String readLine() : Reads the next line of text from this file.
Public long readLong() : Reads a signed 64-bit integer from this file.
Public short readShort() : Reads a signed 16-bit number from this file.
Public int readUnsignedByte() : Reads an unsigned eight-bit number from
this file.
Public int readUnsignedShort() : Reads an unsigned 16-bit number from
this file.
Public String readUTF() : Reads in a string from this file.

L.HASSOUNI 77

void seek(long pos)


Sets the file-pointer offset, measured from the beginning of this file, at
which the next read or write occurs.
void setLength(long newLength) : Sets the length of this file.
int skipBytes(int n)
Attempts to skip over n bytes of input discarding the skipped bytes.
void write(byte[] b)
Writes b.length bytes from the specified byte array to this file, starting
at the current file pointer.
void write(byte[] b, int off, int len)
Writes len bytes from the specified byte array starting at offsetoff to
this file.
void write(int b) : Writes the specified byte to this file.
void writeBoolean(boolean v)
Writes a boolean to the file as a one-byte value.
void writeByte(int v) : Writes a byte to the file as a one-byte value.
void writeBytes(String s)
Writes the string to the file as a sequence of bytes.
L.HASSOUNI 78

Flux d'E/S 39
void writeChar(int v)
Writes a char to the file as a two-byte value, high byte first.
void writeChars(String s)
Writes a string to the file as a sequence of characters.
void writeDouble(double v)
Converts the double argument to a long using thedoubleToLongBits method
in class Double, and then writes thatlong value to the file as an eight-byte
quantity, high byte first.
void writeFloat(float v)
Converts the float argument to an int using the floatToIntBitsmethod in
class Float, and then writes that int value to the file as a four-byte quantity,
high byte first.
void writeInt(int v) : Writes an int to the file as four bytes, high byte first.
void writeLong(long v) : Writes a long to the file as eight bytes, high byte first.
void writeShort(int v) : Writes a short to the file as two bytes, high byte first.
void writeUTF(String str)
Writes a string to the file using modified UTF-8 encoding in a machine-
independent manner.
L.HASSOUNI 79

Source: TestRandomAccessFile.java
import java.io.*;
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
// Create a random access file
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");

inout.setLength(0); // Clear the file to destroy the old contents if exists

// Write new integers to the file


for (int i = 0; i < 200; i++) inout.writeInt(i);

// Display the current length of the file


System.out.println("Current file length is " + inout.length());

// Retrieve the first number


inout.seek(0); // Move the file pointer to the beginning
System.out.println("The first number is " + inout.readInt());

// Retrieve the second number


inout.seek(1 * 4); // Move the file pointer to the second number
System.out.println("The
L.HASSOUNI second number is " + inout.readInt()); 80

Flux d'E/S 40
Source: TestRandomAccessFile.java
// Retrieve the tenth number
inout.seek(9 * 4); // Move the file pointer to the tenth number
System.out.println("The tenth number is " + inout.readInt());

// Modify the eleventh number


inout.writeInt(555);

// Append a new number


inout.seek(inout.length()); // Move the file pointer to the end
inout.writeInt(999);

// Display the new length


System.out.println("The new length is " + inout.length());

// Retrieve the new eleventh number


inout.seek(10 * 4); // Move the file pointer to the eleventh number
System.out.println("The eleventh number is " + inout.readInt());

inout.close();
}
} L.HASSOUNI 81

Compléter l'application ci-dessous pour gérer un fichier d'étudiants

package myrandomfile;
public class Etudiant {
private int num;
private String nom;
private String prenom;
private char genre;
private double note;
public int getNum() {return num;}
public void setNum(int num) {this.num = num;}
public String getNom() {return nom;}
public void setNom(String nom) {this.nom = nom;}
public String getPrenom() {return prenom;}
public void setPrenom(String prenom) {this.prenom = prenom;}
public char getGenre() {return genre;}
public void setGenre(char genre) {this.genre = genre;}
public double getNote() {return note;}
public void setNote(double note) {this.note = note;}
public String toString(){
return "[" + num + " , " + nom + " , " + prenom + " , " + " , " + note
+"]"; }}

L.HASSOUNI 82

Flux d'E/S 41
package myrandomfile;

import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Scanner;

public class GereRandomFile {


public static RandomAccessFile creFile(Scanner stdin) throws IOException{
String cheminFichier;
System.out.println("Donner le chemin du fichier : ");
cheminFichier = stdin.next();
RandomAccessFile raf = new RandomAccessFile(cheminFichier, "rw");
return raf;
}
public static void ecrireEtudiant(RandomAccessFile raf, Etudiant e)throws IOException{
raf.writeInt(e.getNum());
raf.writeUTF(e.getNom());
raf.writeUTF(e.getPrenom());
raf.writeDouble(e.getNote());
}

L.HASSOUNI 83

public static void SaisirInfoEtudiant(Etudiant e, Scanner stdin){


System.out.print("Num : "); e.setNum(stdin.nextInt());
System.out.print("Nom : "); e.setNom(stdin.next());
System.out.print("Prenom : "); e.setPrenom(stdin.next());
System.out.print("genre : "); e.setGenre(stdin.next().charAt(0));
System.out.print("Note : "); e.setNote(stdin.nextDouble());
}
public static void saisirNouveauxEtudiants(RandomAccessFile raf, Scanner
stdin) throws IOException{
Etudiant e = new Etudiant();
char rep;
raf.seek(raf.length());
do{
SaisirInfoEtudiant(e, stdin);
ecrireEtudiant(raf, e);
System.out.print("Une autre saisie(o/n) : ");
rep = stdin.next().charAt(0);
}while(Character.toLowerCase(rep) == 'o');
}

L.HASSOUNI 84

Flux d'E/S 42
public static void consultationSequentielle(RandomAccessFile raf){
try{
Etudiant e = new Etudiant();
raf.seek(0);
while(true){
e.setNum(raf.readInt());
e.setNom(raf.readUTF());
e.setPrenom(raf.readUTF());
e.setNote(raf.readDouble());
System.out.println(e);}
}catch(EOFException eof){
System.out.println("====Fin de lecture du fichier===");
}catch(IOException ioe){
System.out.println("????? Erreur d'entrée/Sortie????");
}}

public static void main(String[] args) throws IOException{


Scanner stdin = new Scanner(System.in);
RandomAccessFile raf;
System.out.println("----Création du fichier :\n");
raf = creFile(stdin);
saisirNouveauxEtudiants(raf, stdin);
consultationSequentielle(raf);
}}
L.HASSOUNI 85

Etudier la classe File

<<Interface>> <<interface>>
Object
Serializable Comparable<File>

File

public class File extends Object


implements Serializable, Comparable<File>
L.HASSOUNI 86

Flux d'E/S 43
Terminer la hiérachie de la Classe Reader

<<Interface>> <<interface>>
Object
Closeable Readable

Reader public abstract class Reader extends Object implements Readdable,


Closeable

BufferedReader CharArrayReader FilterReader

L.HASSOUNI 87

Terminer la hiérachie de la Classe Writer

<<Interface>> <<interface>> <<interface>>


Object
Closeable Appendable Flushable

Writer public abstract class Writer extends Object implements Appendable,


Closeable, Flushable

BufferedWriter CharArrayWriter FilterWriter

L.HASSOUNI 88

Flux d'E/S 44
Les Collections
en Java

Préparé par : Larbi HASSOUNI

Qu'est ce qu'une collection?


• Une collection est un simple objet qui regroupe un groupe d'objets.
• Chaque objet faisant partie de la collection est appelé élément de la
collection.
• Il existe plusieurs types de collections. Chacun implémente un type
particulier de structure de données.
• Chaque type de collection gère ses éléments de sa propre manière, et
utilise un type de stockage donné.
• Le Framework des collections consiste en un ensemble d'interfaces, des
classes qui implémentent ces interfaces, et des classes utilitaires pour
manipuler la plupart des types de ces collections.
• Toutes les interfaces et classes du Framework collection sont génériques.
• Toutes les classes collections sont stockées dans le package java.util

L. HASSOUNI 2

Collections 1
Hiérarchie du Framework des Collections

L. HASSOUNI 3

Hiérarchie des Collections

SortedSet TreeSet

Set AbstractSet HashSet LinkedHashSet

Collection AbstractCollection
Vector Stack

List AbstractList
ArrayList

AbstractSequentialList LinkedList
Deque

Queue AbstractQueue PriorityQueue

Interfaces Abstract Classes Concrete Classes

L. HASSOUNI 4

Collections 2
Interfaces et classes du Framework collection
• Une interface du Framework collection représente un type spécifique
de structure de données.
• L'interface List spécifie un objet collection de type liste. Les éléments
d'une liste peuvent se dupliquer.
• L'interface set spécifie un objet collection de type ensemble. Les
éléments d'un ensemble ne doivent pas se dupliquer.
• L'interface Queue permet de spécifier une file ou pile.
• L'interface Map spécifie un objet collection dont chaque élément est
une paire <clé, valeur> qui associe une clé à une valeur.

L. HASSOUNI 5

• L'avantage de spécifier une structure de données par une interface


est de permettre plusieurs implémentations différentes d'une même
structure.
• Le Framework des collections fournit des classes qui implémentent
ces interfaces.
• Il est recommandé d'utiliser une interface pour déclarer un objet
collection plutôt que la classe qui implémente l'interface.
• Par exemple pour déclarer un objet collection liste, il est recommandé
d'utiliser :
List <String> noms = new ArrayList<>();
Plutôt que:
ArrayList<String> noms = new ArrayList<>();

L. HASSOUNI 6

Collections 3
L'interface <<Collection>>
• L'interface Collection est la racine du Framework des collections. Elle
définit une collection générique.
• Le Framework des collections ne fournit pas de classes qui
implémente l'interface Collection.
• L'interface Collection définit le type collection le plus générique et
peut être passé comme paramètre aux méthodes.
• L'interface Collection déclare un ensemble de méthodes qui sont
héritées par tous les autres interfaces collections.

L. HASSOUNI 7

<<interface>>

API Collection Iterable<T>

<<interface>>
Méthode de l'interface Iterable Collection<T>

public default void forEach(Consumer<? super T> action)


Performs the given action for each element of the Iterable until
all elements have been processed or the action throws an
exception.
Iterator<T> iterator()
Returns an iterator over elements of type T.
default Spliterator<T> spliterator()
Creates a Spliterator over the elements described by
this Iterable.
L. HASSOUNI 8

Collections 4
API Collection
• Les méthodes de l'interface Collection peuvent être réparties en les
classes suivantes:
Opérations basiques
Opérations vrac
Opérations d'agregats
Opérations tableaux
Opérations de comparaison

Une classe qui implémente l'interface Collection doit lancer l'exception


UnsupportedOperationException (hérite de RunTimeException) pour les
méthodes optionnelles.

L. HASSOUNI 9

Méthodes pour opérations basiques


boolean add(E e)
Ensures that this collection contains the specified element (optional operation).

void clear()
Removes all of the elements from this collection (optional operation).
boolean contains(Object o)
Returns true if this collection contains the specified element.
boolean remove(Object o)
Removes a single instance of the specified element from this collection, if it is present (optional operation).
boolean isEmpty()
Returns true if this collection contains no elements.
int size()
Returns the number of elements in this collection.

L. HASSOUNI 10

Collections 5
package collectionbasicop;

import java.util.ArrayList;
import java.util.Collection;

public class OperationsBasiques {


public static void main(String[] args) {
Collection<String> noms = new ArrayList<>();

if(noms.isEmpty()){
System.out.println("Collection vide");
}else{
System.out.println("Collection non vide");
}

noms.add("Moha");
noms.add("Toto");
noms.add("Manolo");
noms.add("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());

L. HASSOUNI 11

noms.remove("Manolo");
System.out.println("Elements : " + noms + " Taille : " + noms.size());

if(noms.contains("Manolo")){
System.out.println("Manolo est contenu dans la liste");
}else{
System.out.println("Manolo n'est pas contenu dans la liste");
}
noms.remove("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.clear();
System.out.println("Elements : " + noms + " Taille : " + noms.size());
}
}
Résultats exécution:
Collectioon vide
Elements : [Moha, Toto, Manolo, Moha] Taille : 4
Elements : [Moha, Toto, Moha] Taille : 3
Manolo n'est pas contenu dans la liste
Elements : [Toto, Moha] Taille : 2
Elements : [] Taille : 0
L. HASSOUNI 12

Collections 6
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsBasiques {
public static void main(String[] args) {
Collection<String> noms = new ArrayList<>();
if(noms.isEmpty()){ System.out.println("Collectioon vide"); }
else{System.out.println("Collectioon non vide"); }
noms.add("Moha");
noms.add("Toto");
noms.add("Manolo");
noms.add("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.remove("Manolo");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
if(noms.contains("Manolo")){ System.out.println("Manolo est contenu dans la liste"); }
else{System.out.println("Manolo n'est pas contenu dans la liste"); }
noms.remove("Moha");
System.out.println("Elements : " + noms + " Taille : " + noms.size());
noms.clear();
System.out.println("Elements : " + noms + " Taille : " + noms.size());
}
}
L. HASSOUNI 13

Méthodes pour opérations vrac


boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection (optional operation).

boolean retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the specified collection (optional operation).
boolean containsAll(Collection<?> c)

Returns true if this collection contains all of the elements in the specified collection.

boolean removeAll(Collection<?> c)
Removes all of this collection's elements that are also contained in the specified collection (optional operation).

default boolean removeIf(Predicate<? super E> filter)


Removes all of the elements of this collection that satisfy the given predicate.

L. HASSOUNI 14

Collections 7
package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;

public class OperationsVrac {


public static void main(String[] args){

Collection<String> sportifs = new ArrayList<>();

Collection<String> footballeurs = new ArrayList<>();

Collection<String> joueursTennis = new ArrayList<>();

sportifs.add("Aouita");
sportifs.add("Moutawakkil");

footballeurs.add("Zaki");
footballeurs.add("Bouderbala");

joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
joueursTennis.add("Alami");
L. HASSOUNI 15

System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );

sportifs.addAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );

if(sportifs.containsAll(footballeurs)){
System.out.println("Les footballeurs sont inclus dans la liste des sportifs");
}

sportifs.retainAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );

sportifs.retainAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );

sportifs.addAll(footballeurs);
sportifs.addAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );

sportifs.removeIf((String e)->{return e.length()<6;});


System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
}} L. HASSOUNI 16

Collections 8
Exécution
Sportifs : [Aouita, Moutawakkil] NbSportifs : 2
Sportifs : [Aouita, Moutawakkil, Zaki, Bouderbala] NbSportifs : 4
Les ffotballeurs sont inclus dans la liste des sportifs
Sportifs : [Zaki, Bouderbala] NbSportifs : 2
Sportifs : [] NbSportifs : 0
Sportifs : [Zaki, Bouderbala, El Aynaoui, Arazi, Alami] NbSportifs : 5
Sportifs : [El Aynaoui, Arazi, Alami] NbSportifs : 3
Sportifs : [El Aynaoui] NbSportifs : 1

L. HASSOUNI 17

package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsVrac {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<String>();
Collection<String> footballeurs = new ArrayList<>();
Collection<String> joueursTennis = new ArrayList<String>();
sportifs.add("Aouita");
sportifs.add("Moutawakkil");
footballeurs.add("Zaki");
footballeurs.add("Bouderbala");
joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
joueursTennis.add("Alami");
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.addAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
if(sportifs.containsAll(footballeurs)){
System.out.println("Les ffotballeurs sont inclus dans la liste des sportifs");
}
sportifs.retainAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.retainAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.addAll(footballeurs);
sportifs.addAll(joueursTennis);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeAll(footballeurs);
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
sportifs.removeIf((String e)->{return e.length()<6;});
System.out.println("Sportifs : " + sportifs + " NbSportifs : " + sportifs.size() );
}}
L. HASSOUNI 18

Collections 9
Méthodes pour opérations de comparaison
boolean equals(Object o)
Compares the specified object with this collection for equality.

int hashCode()
Returns the hash code value for this collection.

package collectionbasicop;
import java.util.ArrayList;
import java.util.Collection;
public class OperationsComparaison {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();
Collection <String> joueursTennis = new ArrayList<>();
sportifs.add("El Aynaoui");
sportifs.add("Arazi");
sportifs.add("Alami");
joueursTennis.add("El Aynaoui");
joueursTennis.add("Arazi");
L. HASSOUNI 19

if(sportifs.equals(joueursTennis)){
System.out.println("sportifs = joueursTennis");
}else{
System.out.println("sportifs # joueursTennis");
} Exécution
joueursTennis.add("Alami"); sportifs # joueursTennis
if(sportifs.equals(joueursTennis)){ sportifs = joueursTennis
System.out.println("sportifs = joueursTennis"); 189160881
}else{ 189160881
System.out.println("sportifs # joueursTennis"); -1416950800
}
System.out.println(sportifs.hashCode());
System.out.println(joueursTennis.hashCode());
int tothc = 0;
for(String e : sportifs){
tothc += e.hashCode();
}
System.out.println(tothc);
}
}
L. HASSOUNI 20

Collections 10
package collectionbasicop; Exécution
import java.util.ArrayList; sportifs # joueursTennis
import java.util.Collection; sportifs # joueursTennis
public class OperationsComparaison2 { -1183176409
public static void main(String[] args){ -1874243739
Collection<StringBuilder> sportifs = new ArrayList<>(); -80390400
Collection <StringBuilder> joueursTennis = new ArrayList<>();
sportifs.add(new StringBuilder("El Aynaoui"));
sportifs.add(new StringBuilder("Arazi"));
sportifs.add(new StringBuilder("Alami"));
joueursTennis.add(new StringBuilder("El Aynaoui"));
joueursTennis.add(new StringBuilder("Arazi"));
if(sportifs.equals(joueursTennis)){System.out.println("sportifs = joueursTennis");}
else{System.out.println("sportifs # joueursTennis");}
joueursTennis.add(new StringBuilder("Alami"));
if(sportifs.equals(joueursTennis)){System.out.println("sportifs = joueursTennis");}
else{System.out.println("sportifs # joueursTennis");}
System.out.println(sportifs.hashCode());
System.out.println(joueursTennis.hashCode());
int tothc = 0;
for(StringBuilder e : sportifs){tothc += e.hashCode();}
System.out.println(tothc);
}}
L. HASSOUNI 21

Méthodes pour opérations tableaux


Object[] toArray()
Returns an array containing all of the elements in this collection.
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the
specified array.

L. HASSOUNI 22

Collections 11
Exécution
package collectionbasicop; El Aynaoui
import java.util.ArrayList; Arazi
import java.util.Collection; Alami
public class OperationsToArray { ================
public static void main(String[] args){ El Aynaoui
Collection<String> sportifs = new ArrayList<>(); Arazi
sportifs.add("El Aynaoui"); Alami
sportifs.add("Arazi");
sportifs.add("Alami");

Object[] objectArraySportifs = sportifs.toArray();


for(Object e : objectArraySportifs){System.out.println(e);}

System.out.println("==================================");
String[] stringArraySportifs = sportifs.toArray(new String[sportifs.size()]);
for(String e : stringArraySportifs){System.out.println(e);}

}
}

L. HASSOUNI 23

Méthodes pour opérations d'agrégats


default Stream<E> stream()

Returns a sequential Stream with this collection as its source.


default Stream<E> parallelStream()
Returns a possibly parallel Stream with this collection as its source.

Voir cours sur Java I/O

L. HASSOUNI 24

Collections 12
Méthodes pour parcourir (ou travaerser) une collection
Iterator<E> iterator()
Returns an iterator over the elements in this collection.

default Spliterator<E> spliterator()


Creates a Spliterator over the elements in this collection.

Pour parcourir une collection d'objets on peut procéder de


l'une des façons suivantes:
 Utiliser un Iterator
 Utiliser la boucle for-each
 Utiliser la méthode forEach().

L. HASSOUNI 25

Utilisation d'un Iterator

API Iterator
default void forEachRemaining(Consumer<? super E> action)
Performs the given action for each remaining element until all elements have been processed or the action throws an
exception.

boolean hasNext()
Returns true if the iteration has more elements.
E next()

Returns the next element in the iteration.

default void remove()


Removes from the underlying collection the last element returned by this iterator (optional operation).

L. HASSOUNI 26

Collections 13
• Une collection possède la méthode Iterator<E> iterator() qui lui
permet d'obtenir un objet Iterator pour parcourir tous les éléments
de la dite collection.
• Un objet Iterator peut exécuter les méthodes de l'interface Iterator.
• Ces méthodes, comme le montre le tableau API Iterator, sont :
• hasNext() : teste s'il y a un élément qui n'a pas été accédé.
• next() : retourne l'élément suivant de la collection. Nous devons toujours
exécuter next() après le succès d'un hasNext(), sinon next() lance l'exception
NoSuchElementException.
• Remove() : supprime l'élément de la liste qui vient d'être retourné par next().
Remove() doit être appelé une seule fois pour chaque appel de next().
Si la méthode remove() est appellee plus d'une fois pour un appel de next(),
ou avant le premier appel de next(), elle lance l'exception
IllegalStateException.
Le support de la methods remove() est optionnel. Remove() peut lancer
l'exception UnsupportedOperationException.

L. HASSOUNI 27

Parcours d'une collection : Iterator , hasNext() et next()


Exécution
package collectionbasicop;
Aouita
import java.util.ArrayList; Guerrouj
import java.util.Collection; Bidouane
import java.util.Iterator;

public class OperationsIterator {


public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();

sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");

Iterator<String> sportifsIterator = sportifs.iterator();


while(sportifsIterator.hasNext()){
String nom = sportifsIterator.next();
System.out.println(nom);
}
}
} L. HASSOUNI 28

Collections 14
Suppression d'éléments d'une collection : Iterator, remove()
package collectioniterator;
import java.util.ArrayList; Exécution
import java.util.Collection; Aouita
import java.util.Iterator; Guerrouj
public class CollectionIteratorRemove { Bidouane
public static void main(String[] args){ []
Collection<String> sportifs = new ArrayList<>();
• Remarque :
sportifs.add("Aouita");
sportifs.add("Guerrouj"); • Un Iterator est un objet à
sportifs.add("Bidouane"); une seule utilisation. Il ne
peut pas être réinitialisé
Iterator<String> sportifsIterator = sportifs.iterator(); pour parcourir la collection
while(sportifsIterator.hasNext()){ une nouvelle fois.
String nom = sportifsIterator.next(); • Pour parcourir la collection
System.out.println(nom); une nouvelle fois, il faut
sportifsIterator.remove(); créer un nouveau Iterator
} avec la méthode iterator()
System.out.println(sportifs); de l'objet collection.
}
}
L. HASSOUNI 29

Application d'une action sur chaque élément d'une collection


méthode forEachRemaining()
• La méthode forEachRemaining() de l'objet Iterator permet
d'appliquer une action sur chaque élément de la collection qui n'a pas
encore accédé.
• L'action est spécifiée comme un objet "instance" de l'interface
fonctionnel Consumer.
• Il est possible de passer une lambda expression comme argument de
la méthode forEachRemaining().

L. HASSOUNI 30

Collections 15
Parcours d'une collection avec la boucle for-each
package collectioniterator; Aouita
import java.util.ArrayList; Guerrouj
import java.util.Collection; Bidouane
import java.util.Iterator;

public class CollectionForEachLoop { Remarque:


public static void main(String[] args){ La boucle for-each a quelques
Collection<String> sportifs = new
limitations:
ArrayList<>();
 On ne peut pas commencer à
sportifs.add("Aouita"); partir du milieu de la collection
sportifs.add("Guerrouj");  On ne peut pas supprimer un
sportifs.add("Bidouane"); élément de la collection.
L'exécution de la méthode
for (String elt : sportifs){ remove() dans une boucle for-
System.out.println(elt); each lance l'exception
} ConcurrentModificationException
}
}
L. HASSOUNI 31

Exception ConcurrentModificationException
package collectioniterator;
java.util.ConcurrentModificationException
Aouita
Exécution

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.ConcurrentModificationException;
public class CollectionForEachLoopRemove {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();
sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");
try{
for (String elt : sportifs){
System.out.println(elt);
sportifs.remove(elt);
}
}catch(ConcurrentModificationException e){
System.out.println(e);
}
}
}
L. HASSOUNI 32

Collections 16
Application d'une action sur chaque élément d'une collection
iterator.forEachRemaining(action)
package collectioniterator;
Exécution
import java.util.ArrayList;
import java.util.Collection; Aouita
import java.util.Iterator; Guerrouj
Bidouane
public class CollectionIteratorForEachRemaining {
public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();

sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");

Iterator<String> sportifsIterator = sportifs.iterator();


sportifsIterator.forEachRemaining(System.out::println);
//sportifsIterator.forEachRemaining((String e)->System.out.println(e));

}
L. HASSOUNI 33
}

API de l'interface fonctionnel Consumer<T>


@FunctionalInterface
public interface Consumer<T>

Représente une opération qui accepte un seul argument et ne retourne pas de résultat.
Comme tout interface fonctionnel, il peut être cible d'une affectation par une lambda expression
ou une référence de méthode "method reference".

API interface Consumer<T>


void accept(T t)
Performs this operation on the given argument.

default Consumer<T> andThen(Consumer<? super T> after)


Returns a composed Consumer that performs, in sequence, this operation followed by the after operation.34

L. HASSOUNI 34

Collections 17
Application d'une action sur chaque élément d'une collection
iterator.forEachRemaining(action)
package collectioniterator;

import java.util.ArrayList;
import java.util.Collection; Exécution
import java.util.Iterator;
Elt :Aouita Long : 6
public class CollectionIteratorForEachRemaining2 { Elt :Guerrouj Long : 8
public static void main(String[] args){ Elt :Bidouane Long : 8
Collection<String> sportifs = new ArrayList<>();

sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");

Iterator<String> sportifsIterator = sportifs.iterator();


sportifsIterator.forEachRemaining((String e)->
{System.out.println("Elt :" + e + "\tLong : "+e.length());});
}
}
L. HASSOUNI 35

Application d'une action sur chaque élément d'une collection


Méthode forEach(Consumer action) de l'interface Iterable

L'interface Iterable contient une nouvelle méthode forEach(Consumer


action) qui permet de parcourir une collection tout en appliquant une
action sur chaque élément.
La méthode forEach() est disponible dans chaque type de collection qui
hérite de l'interface Collection.

L. HASSOUNI 36

Collections 18
package collectioniterator;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionForEach {


public static void main(String[] args){
Collection<String> sportifs = new ArrayList<>();

sportifs.add("Aouita");
sportifs.add("Guerrouj");
sportifs.add("Bidouane");

sportifs.forEach(System.out::println);
System.out.println("==============================");
sportifs.forEach((String e)->{System.out.println("Elt :" + e +
"\tLong : "+e.length());});
}
}

L. HASSOUNI 37

<<interface>>
Iterable<T>
Collection List
<<interface>>
• Une Liste est une collection non ordonnée d'objets Collection<T>
définie par l'interface List du framework Collection.
• Une liste peut avoir des éléments duppliqués. <<interface>>
Elle peut aussi stocker plusieurs valeurs null. List<T>

• L'interface List hérite de l'interface Collection et ajoute


de nouvelle méthodes pour permettre l'accès aux
éléments en utilisant un indice.
• Il est possible d'ajouter un élément à la fin d'une liste ou
à n'importe quelle position spécifiée par un indice.
• L'indice du 1er element d'une liste a la valeur zéro.
L. HASSOUNI 38

Collections 19
Méthodes spécifiques à une liste(1)
void add(int index, E element)
Inserts the specified element at the specified position in this list (optional operation).

boolean addAll(int index, Collection<? extends E> c)


Inserts all of the elements in the specified collection into this list at the specified position (optional
operation).
E get(int index)

Returns the element at the specified position in this list.

int indexOf(Object o)
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain
the element.

int lastIndexOf(Object o)
Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain
the element.
L. HASSOUNI 39

Méthodes spécifique à une liste(2)


ListIterator<E> listIterator()
Returns a list iterator over the elements in this list (in proper sequence).

ListIterator<E> listIterator(int index)


Returns a list iterator over the elements in this list (in proper sequence), starting at the specified position in the list.

E remove(int index)
Removes the element at the specified position in this list (optional operation).

boolean removeAll(Collection<?> c)
Removes from this list all of its elements that are contained in the specified collection (optional operation).

E set(int index, E element)


Replaces the element at the specified position in this list with the specified element (optional operation).

List<E> subList(int fromIndex, int toIndex)


Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
L. HASSOUNI 40

Collections 20
Méthodes spécifique à une liste(3)
default void replaceAll(UnaryOperator<E> operator)
Replaces each element of this list with the result of applying the operator to that element.

default void sort(Comparator<? super E> c)


Sorts this list according to the order induced by the specified Comparator.

L. HASSOUNI 41

ArrayList vs LinkedList
• ArrayList et LinkedList sont deux classes du Framework Collection qui implémentent
l'interface List.
• Une ArrayList est stokée dans un tableau dynamique.
• Une LinkedList est stockée sous forme de liste chaînée.
• Une ArrayList offre de meilleures performances lorsqu'on accède fréquemment aux
éléments de la liste. L'accès aux éléments se fait plus rapidément puisqu'une ArrayList
est sauvegardée dans un tableau.
• L'ajout et la suppression d'un élément d'une ArrayList se fait plus lentement à moins que
l'opération ne s'effectue à la fin de la liste, ceci parce qu'une ArrayList doit effectuer une
copie de tableau interne pour garder les éléments en séquence.
• Une LinkedList offre de meilleures performances qu'une ArrayList pour les opérations
d'ajout et de suppression à partir du milieu de la liste. Cependant, une LinkedList est plus
lente pour accéder aux éléments à moins que ça se passe en tête de la liste.

L. HASSOUNI 42

Collections 21
package ListExemples;

import java.util.ArrayList;
import java.util.List;
public class ListExemple01 {
public static void main(String[] args) {
List<String> langages = new ArrayList<>();
langages.add("C");
langages.add("C++");
langages.add("Java");

System.out.println("Langages: " + langages);

int nbElt = langages.size();


System.out.println("Nb Elts: " + nbElt);

for (int i = 0; i < nbElt; i++) {


String element = langages.get(i);
System.out.println("Index=" + i + ", Element=" + element);
}
L. HASSOUNI 43

List<String> subList = langages.subList(1, 2);


System.out.println(subList);
langages.remove("Java");
System.out.println("Langages : " + langages);
langages.add(0, "Java");
System.out.println("Langages : " + langages);

List<String>langWeb = new ArrayList<>();


langWeb.add("HTML");
langWeb.add(1, "CSS");
langWeb.add("JavaScript");
Exécution
langages.addAll(2, langWeb); Langages: [C, C++, Java]
System.out.println("LangagesWeb : " + langWeb); Nb Elts: 3
System.out.println("Langages : " + langages); Index=0, Element=C
Index=1, Element=C++
} Index=2, Element=Java
} [C++]
Langages : [C, C++]
Langages : [Java, C, C++]
LangagesWeb : [HTML, CSS, JavaScript]
Langages : [Java, C, HTML, CSS, JavaScript, C++]

L. HASSOUNI 44

Collections 22
<<interface>>
Parcours d'une liste avec ListIterator Iterator<T>

• L'interface List offre une méthode listIterator() qui permet


d'obtenir un Objet "instance" de l'interface ListIterator qui offre <<interface>>
ListIterator<T>
plus de possibilité que Iterator pour parcourir une liste.
ListIterator hérite de Iterator.
• Un ListIterator peut parcourir la liste dans les deux directions du
premier au dernier élément, ou du dernier au premier élément.
• La méthode next() avance d'un élément vers l'avant, et la
méthode previous() recule d'un élément vers l'arrière.
• Si vous utilisez next() suivi de previous(), l'iterator reste à la
même position.

ListIterator<String> iteratorGlobal = list.listIterator();


ListIterator<String> iteratorPartiel = list.listIterator(5);
L. HASSOUNI 45

API ListIterator : méthodes ajoutées dans ListIterator


void add(E e)
Inserts the specified element into the list (optional operation).

boolean hasPrevious()
Returns true if this list iterator has more elements when traversing the list in the reverse direction.

int nextIndex()
Returns the index of the element that would be returned by a subsequent call to next().

E previous()
Returns the previous element in the list and moves the cursor position backwards.

int previousIndex()
Returns the index of the element that would be returned by a subsequent call to previous().

Void set(E e)
Replaces the last element returned by next() or previous() with the specified element (optional operation).
L. HASSOUNI 46

Collections 23
Parcours d'une liste dans les deux directions avec ListIterator
package ListExemples;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListListIterator {
public static void main(String[] args) {
List<String> langagesFonctionnels = new ArrayList<>();
langagesFonctionnels.add("Lisp");
langagesFonctionnels.add("Prolog");
langagesFonctionnels.add("Clojure");
langagesFonctionnels.add("Haskel");
System.out.println("Langages: " + langagesFonctionnels);
ListIterator<String> iteratorGlobal = langagesFonctionnels.listIterator();

System.out.println("==Parcourir la liste en avant==");


while (iteratorGlobal.hasNext()) {
int index = iteratorGlobal.nextIndex();
String element = iteratorGlobal.next();
System.out.println("Index=" + index + ", Element=" + element);
}
L. HASSOUNI 47

System.out.println("\n==Parcourir la liste en arière==");


while (iteratorGlobal.hasPrevious()) {
int index = iteratorGlobal.previousIndex();
String element = iteratorGlobal.previous();
System.out.println("Index=" + index + ", Element=" + element);
}
}
}

Langages: [Lisp, Prolog, Clojure, Haskel]


Exécution ==Parcourir la liste en avant==
Index=0, Element=Lisp
Index=1, Element=Prolog
Index=2, Element=Clojure
Index=3, Element=Haskel

==Parcourir la liste en arière==


Index=3, Element=Haskel
Index=2, Element=Clojure
Index=1, Element=Prolog
Index=0, Element=Lisp
L. HASSOUNI 48

Collections 24
La partie qui suit est en cours
de modification

L. HASSOUNI 49

Exercice : Que fait ce programme?

L. HASSOUNI Page 50

Collections 25
L. HASSOUNI Page 51

Collection Queue (File)


• Une queue est une collection d'objets sur laquelle les operations peuvent
être effectuées uniquement aux deux extrémités début (head) et fin(tail).
• Dans une queue simple, les objets sont ajoutés à la fin et retires du début.
On dit que c'est une queue FIFO (First In First Out)
• Le Framework Collections de Java supporte plusieurs types de queue.
Une Queue simple qui autorise l'insertion des éléments à la fin et leur retrait de
début. (Queue FIFO)
Une Queue à priorité qui attribute à chaque élément une priorité et permet à
l'élément qui a la forte priorité d'être retiré en premier.
Une Queue à délai qui attribute un délai à chaque élément et qui n'autorise le retrait
d'un élément qu'après le délai qui lui est associé.
Une Queue à double Entreé/Sortie qui permet d'ajouter et de retirer les données à
partir des deux extrémités de la file.

L. HASSOUNI 52

Collections 26
Linterface Set
• un Set est une collection non ordonnée
• Il ne contient pas des éléments en double

• La collection ne garde pas trace de l’ordre dans lequel les éléments


ont été ajoutés
• Par conséquent, un set peut effectuer ses opérations plus efficacement
qu’une collection ordonnée,

Les classes HashSet et TreeSet implémentent l’interface Set.

L. HASSOUNI Page 53

Sets
• HashSet: Stocke les données dans une table de hachage (Hash
Table)
• TreeSet: Stocke les données dans un arbre Binaire
• Les implementations arrangent ses
éléments de manière à rendre efficace
les opérations d’ajout et de retrait.

Les implémentations de Set arrangent les


éléments de manière à rendre leur
localisation rapide

L. HASSOUNI Page 54

Collections 27
Concept de table de hachage (Hash Table)

• Une “hash table” est une petite collection


d’éléments qui se partagent les mêmes
caractéristiques.
• Elle est généralement basée sur un calcul
mathématique effectué sur le contenu des éléments
et dont le résultat est un entier
• Pour être stocké dans une “hash table”, les éléments
doivent contenir une méthode appellee
“hashCode”qui calcule ce résultat entier

L. HASSOUNI Page 55

Méthode hashCode
• La méthode hashCode calcule un entier à partir des attributs de
l’élément
• Si plusieurs éléments ont le même hash code, ils sont stockés dans une
Linked list.

• Les éléments doivent aussi avoir une méthode “equals” pour


controller si deux éléments sont égaux comme:
• String, Integer, Point, Rectangle, Color, et toutes les classes collection

Set<String> names = new HashSet<String>();

L. HASSOUNI Page 56

Collections 28
Concept d’arbre binaire (Tree)
• Les éléments sont gardés dans un ordre trié
• Les noeuds ne sont pas rangés dans un ordre linéaire, mais
dans une structure d’arbre.
• Pour utiliser un TreeSet, il doit être possible de comparer les
éléments et de determiner lequel est “plus grand”

L. HASSOUNI Page 57

TreeSet
• Utiliser TreeSet pour les classes qui implémentent l’interface
Comparable
• String et Integer, par exemple
• Les noeuds sont rangés dans un format “d’arbre binaire” pour que chaque
noeud “parent” ait au plus deux noeuds enfants.
• Le noeud de gauche a toujours une valeur inférieure
• Le noeud de droite a toujours une valeur supérieure

Set<String> names = new TreeSet<String>();

L. HASSOUNI Page 58

Collections 29
Iterators et Sets
• Iterators sont aussi utilisés pour traiter les Sets
• hasNext retourne true s’il ya un élément suivant
• next retourne une référence vers la valeur de l’élément suivant
• add ne peut pas utilisé avec un iterator pour TreeSet et HashSet
Iterator<String> iter = names.iterator();
while (iter.hasNext())
for (String name : names)
{
{
String name = iter.next();
// Do something with name
// Do something with name
}
}
• Noter que les éléments ne sont pas retrouvés dans l’ordre de leur
insertion.
• Ils sont retrouvés dans l’ordre dans lequel ils rangés dans le Set:
• Ordre aléatoire pour un HashSet
• Ordre trié pour un TreeSet

L. HASSOUNI Page 59

Comment travailler avec les Sets (1)

L. HASSOUNI Page 60

Collections 30
Comment travailler avec les Sets(2)

L. HASSOUNI Page 61

SpellCheck.java (1)

L. HASSOUNI Page 62

Collections 31
SpellCheck.java (2)

L. HASSOUNI Page 63

Astuce de programmation
 Pour mainpuler les structures de données, il est
recommandé d’utiliser des références vers des types
interface
 Il est considéré comme meilleur style de programmation de
stocker une reference à un HashSet ou TreeSet dans une
variable de type Set.

• De cette façon, vous avez à changer uniquement une ligne si vous


décidez de changer hashSet avec TreeSet ou l’inverse.

Set<String> words = new HashSet<String>();

L. HASSOUNI 64

Collections 32
Les Maps
• Une Map permet d’associer un ensemble de clés à une
collection d’objets.
• Les classes HashMap et TreeMap implémentent toutes les
deux l’interface Map.

• Utiliser un Map pour chercher un objet en utilisant une clé.

L. HASSOUNI Page 65

Maps
Key Value Key Value

Map<String, Color> favoriteColors = new HashMap<String, Color>();

L. HASSOUNI Page 66

Collections 33
Paires (clé, Valeur) dans une Maps
• Chaque clé est associée à une valeur

Map<String, Color> favoriteColors = new HashMap<String, Color>();


favoriteColors.put("Juliet", Color.RED);
favoriteColors.put(“Romeo", Color.GREEN);
Color julietsFavoriteColor = favoriteColors.get("Juliet");
favoriteColors.remove("Juliet");

L. HASSOUNI Page 67

Utilisation des Maps

L. HASSOUNI Page 68

Collections 34
Itération avec les Maps
• Pour effectuer une itération avec une Map, utiliser la
méthode keySet pour obtenir la liste des clés:

Set<String> keySet = m.keySet();


for (String key : keySet)
{
Color value = m.get(key);
System.out.println(key + "->" + value);
}

Pour retrouver toutes les valeurs dans une Map, effectuer une
iteration sur l’ensemble des clés et retrouver la valeur qui correspond
à chaque clé.

L. HASSOUNI Page 69

MapDemo.java

L. HASSOUNI Page 70

Collections 35
Fonctions de hachage
• Le hachage peut être utilisé pour retrouver rapidement les
éléments d’un ensemble, sans procéder à une recherche linéaire
en parcourant tous les éléments.
• Une méthode hashCode calcule et retourne une valeur entière:
le code de hachage (hash code).
• Il est souhaitable que la méthode hashCode génère des codes de
hachage differents pour deux objets différents
• Puisque le hachage est si important, la classe Object possède la méthode
hashCode qui calculie un code de hachage pour n’importe quell objet x.

int h = x.hashCode();

L. HASSOUNI Page 71

Calcul des Hash Codes


• Pour placer les objets instances d’une classe dans un
HashSet ou utiliser les objets comme clés dans un
HashMap, la classe doit redéfinir la méthode hashCode.
• Une bonne méthode hashCode produit des codes de
hachage différents pour des objets différents.
• Elle doit être aussi efficace (Minimum de collisions)
• Un exemple simple pour une String peut être:

int h = 0;
for (int i = 0; i < s.length(); i++)
{
h = h + s.charAt(i);
}

L. HASSOUNI Page 72

Collections 36
Calcul des Hash Codes

• Avec cette méthode, une String et sa permutation (tel que "eat" et "tea")
auront le même code de hachage
• La classe String de la librairie Java définit la méthode hashCode comme suit:

final int HASH_MULTIPLIER = 31;


int h = 0;
for (int i = 0; i < s.length(); i++)
{
h = HASH_MULTIPLIER * h + s.charAt(i);
}

L. HASSOUNI Page 73

Exemples de Strings et HashCodes


• La classe String implémente une bonne méthode hashCode
• Il est possible que deux ou plusieurs objets aient le même code de
hachage : ceci est désigné par collision
• Une méthode hashCode doit minimiser le nombre de
collisions

L. HASSOUNI Page 74

Collections 37
Calcul du Hash Code d’un objet
• Vous devez avoir une bonne méthode hashCode pour
stocker efficacement vos objets
• Redéfinissez la méthode hashCode dans votre classe en
combinant les hash codes des variables d’instance, puis
combinez ces hash codes en utilisant un nombre premier
comme multiplicateur de hachage.

public int hashCode()


{
int h1 = name.hashCode();
int h2 = new Double(area).hashCode();
. . .
final int HASH_MULTIPLIER = 29;
int h = HASH_MULTIPLIER * h1 + h2;
return h;
}

name et area sont des variables d’instance


L. HASSOUNI Page 75

Piles, files et files prioritaires

• Les piles et les files sont des listes spécialisées


• Ne permettent l’ajout et le retrait des éléments qu’à partir
des extémités

Insertion Retrait Opération


Pile Au sommet A partir du List in, first out (LIFO)
sommet
File A la fin A partir de la First in, first out (FIFO)
tête
Liste prioritaire Par priorité La tâche la Liste de tâches avec
moins priorités
prioritaire

L. HASSOUNI Page 76

Collections 38
Listes, files et files prioritaires

• Piles sont utilisées pour réaliser les opérations du type “Annuler” (La dernière
operation en premier)

• files sont utilisées pour gérer les files comme la queue de clients d’une
banque ou d’un magasin

• Files prioritaires pour gérer des tâches avec priorités (suppriment les tâches
moins urgentes en premier).

L. HASSOUNI Page 77

Utilisation d’une pile

Stack<String> s = new Stack<String>();


s.push("A");
s.push("B");
s.push("C");
// The following loop prints C, B, and A
while (s.size() > 0)
{
System.out.println(s.pop());
L. HASSOUNI } Page 78

Collections 39
Utilisation des Files et Files prioritaires

L. HASSOUNI Page 79

Files prioritaires
• Une file prioritaire collecte des éléments dont chacun a
une priorité.
• Exemple: Une collection de tâches, dont chacune a une
priorité (des tâches plus urgentes que d’autres)
• Ce n’est pas une liste FIFO
PriorityQueue<WorkOrder> q = new PriorityQueue<WorkOrder>();
q.add(new WorkOrder(3, "Shampoo carpets"));
q.add(new WorkOrder(1, "Fix broken sink"));
q.add(new WorkOrder(2, "Order cleaning supplies"));

Priorité Tâche
• Les objets qui ont une faible priorité(1) sont enlevés en
premier.

WorkOrder next = q.remove(); // removes “Fix broken sink”

L. HASSOUNI Page 80

Collections 40
Applications des piles et files

• Equilibrage des parenthèses


• Pour équilibrer les parenthèses, il suffit d’ajouter 1 chaque fois
qu’on trouve une parenthèse ouvrante et soustraire 1 chaque
fois qu’on trouve une parenthèse fermante.

L. HASSOUNI Page 81

Applications des piles et files


• Une pile peut être utilisée pour garder trace de la
“profondeur” des parenthèses:
Lorsqu’on trouve une parenthèse ouvrante, on l’empile (push).
Lorsqu’on trouve une parenthèse fermante, on la dépile (pop).
Si les parenthèses ouvrrante et fermante ne correspondent pas
les parenthèses ne sont pas équilibrées , Sortir
A la fin de l’expression,
Si la pile est vide
Les parentheses sont équilibrées
Sinon
Les parentheses ne sont pas équilibrées.

L. HASSOUNI Page 82

Collections 41
Exemple d’utilisation de la pile
• L’exemple ci-dessous est une expression mathématique qui
utilise trois types de parenthèses

L. HASSOUNI Page 83

Expressions en notation polonaise


• Les premières calculatrices utilisaient la notation
polonaise qui peut être facilement implémentées en
utilisant une pile

• Il n’ya pas besoins de parenthèses si vous rencontrez


en premier les deux opérandes, puis l’opérateur:

Expression algébrique Notation polonaise


(3 + 4) x 5 3 4 + 5 x
(3 + 4) x (5 + 6) 3 4 + 5 6 + x

L. HASSOUNI Page 84

Collections 42
Evaluation des expressions en notation polonaise

Si on rencontre un nombre
empilez le dans la pile
Sinon si on rencontre un opérateur
dépiler deux valeurs de la pile
les combinez avec l’opérateur
empilez le résultat dans la pile
Sinon si on arrive à la fin de l’expression
dépiler et afficher le résultat.

L. HASSOUNI Page 85

Calculatrice avec notation polonaise


• Evaluation de l’expression: 3 4 5 + x

L. HASSOUNI Page 86

Collections 43
Calculator.java (1)

L. HASSOUNI Page 87

Calculator.java (2)

L. HASSOUNI Page 88

Collections 44
Evaluation des expressions algébriques
• Peut être réalisée en utilisant deux piles:
1) Une 1ère pile pour les nombres
2) Un 2ème pile pour les Opérateurs et parenthèses
• Premier Exemple: 3 + 4

L. HASSOUNI Page 89

• Second Exemple: 3 x 4 + 5

• Doit respecter la priorité (multiplier avant additionner)

L. HASSOUNI Page 90

Collections 45
Expressions et priorité (1)
• Troisième Exemple: 3 + 4 x 5

• Garder les opérateurs dans la pile jusqu’à ce qu’ils soient


prêts à être évalués.

L. HASSOUNI Page 91

Expressions et priorité (2)


• Troisème Exemple: 3 + 4 x 5

• Evaluer les 2 nombres au sommet avec l’opérateur du


sommet
• Empiler le résultat au sommet de la pile
• Evaluer jusqu’à ce que la pile des opérateurs soit vide

L. HASSOUNI Page 92

Collections 46
Expressions avec Parenthèses (1)
• Quatrième Exemple: 3 x ( 4 + 5 )

• Si on trouve une parenthèse ouvrante (, ne pas évaluer.


• Si on trouve une parenthèse fermante ), évaluer

L. HASSOUNI Page 93

Expressions avec Parenthèses(2)


• Quatrième Exemple: 3 x ( 4 + 5 )

• N’empilez pas ) dans la pile – evaluer maintenant


• Ignorer (

L. HASSOUNI Page 94

Collections 47
Algorithme
If you read a number
Push it on the number stack.
Else if you read a (
Push it on the operator stack.
Else if you read an operator op
While the top of the stack has a higher precedence than op
Evaluate the top.
Push op on the operator stack.
Evaluate the Top:
Else if you read a )
Pop two numbers off the
While the top of the stack is not a (
Evaluate the top. number stack.
Pop the ). Pop an operator off the
Else if there is no more input operator stack.
While the operator stack is not empty Combine the numbers with
Evaluate the top. that operator.
Push the result on the
number stack.
L. HASSOUNI Page 95

Etapes à suivre pour choisir une Collection


1) Determiner comment vous retrouvez les valeurs
• Les valeurs sont retrouvé en uilisant leur position qui est un entier.
Utiliser une ArrayList
• Aller à l’étape deux, puis terminer
• Les valeurs sont retrouvé en utilisant une clé qui ne fait pas partie de
l’objet
• Utiliser une Map.
• Peu importe la manière utilisée pour retrouver les valeurs. Celles-ci sont
toujours retrouvés en vrac “in bulk”, en parcourant la collection et
traitant chaque valeur
2) Determiner les types des éléments ou les types clé/valeur
• Pour une List ou Set, un seul type celui des éléments
• Pour une Map, Deux types celui de la clé et de la valeur

L. HASSOUNI Page 96

Collections 48
Etapes pour choisir une Collection
3) Determiner si l’ordre des élement ou des clés importe
• Les éléments ou clés doivent être triés
• Uiliser une TreeSet ou TreeMap. Aller à l’étape 6
• Les élements doivent être rangés dans le même ordre dans
lequel ils ont été insérés
• Votre choix est maintenant limité à LinkedList ou ArrayList
• L’ordre des éléments n’importe pas
• Si vous avez choisi une Map à l’étape1, utilisez une HashMap et allez
à l’étape 5

L. HASSOUNI Page 97

Etapes pour choisir une Collection


4) Pour une collection, determiner quelles sont les
opérations qui doivent être rapides
• La recherche des éléments doit être rapide
• Uiliser un HashSet et aller à l’étape 5

• L’ajout et le retrait des éléments au debut ou au milieu


doivent être rapide
• Utiliser une LinkedList

• L’insertion est toujours effectuée à la fin, ou la collection


contient peu d’éléments et la rapidité de l’opération n’a pa
d’importance
• Utilser une ArrayList.

L. HASSOUNI Page 98

Collections 49
Etapes pour choisir une Collection

5) Pour HashSet et Map, decidez si vous avez besoin d’implémenter les


méthodes equals et hashCode
• Si vos éléments ne les contiennent pas, vous devez les implementer vous
même.
6) Si vous utilisez une TreeSet, decidez s’il faut disposer d’un
comparator
• Si la classe des éléments ne le fournit pas, implémentez l’interface
Comparable dans la classe des éléments.

L. HASSOUNI Page 99

API

Collections 50
Stack : API
Class Stack<E>
•java.lang.Object
•java.util.AbstractCollection<E>
•java.util.AbstractList<E>
•java.util.Vector<E>
•java.util.Stack<E>

•All Implemented Interfaces:


Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess

L. HASSOUNI Page 101

public class Stack<E> extends Vector<E>

The Stack class represents a last-in-first-out (LIFO) stack of objects. It


extends class Vector with five operations that allow a vector to be treated
as a stack. The usual push and pop operations are provided, as well as a
method to peek at the top item on the stack, a method to test for whether
the stack is empty, and a method to search the stack for an item and
discover how far it is from the top.

When a stack is first created, it contains no items.

A more complete and consistent set of LIFO stack operations is provided


by the Deque interface and its implementations, which should be used in
preference to this class. For example:

Deque<Integer> stack = new ArrayDeque<Integer>();

L. HASSOUNI 102

Collections 51
Constructor and Description
Stack() : Creates an empty Stack.
Methods
Modifier and Type Method and Description
boolean empty()Tests if this stack is empty.
E peek()Looks at the object at the top of this stack without
removing it from the stack.
E pop()Removes the object at the top of this stack and
returns that object as the value of this function.
E push(E item)Pushes an item onto the top of this stack.

int search(Object o)Returns the 1-based position where an


object is on this stack.

L. HASSOUNI 103

Map
Nested Classes
Modifier and Type Interface and Description
static interface Map.Entry<K,V>A map entry (key-value pair).

L. HASSOUNI 104

Collections 52
Map Methods(1)
Modifier and Type Method and Description
void clear()Removes all of the mappings from this map (optional operation).
default V compute(K key, BiFunction<? super K,? super V,?
extends V> remappingFunction)Attempts to compute a mapping for the
specified key and its current mapped value (or null if there is no current
mapping).
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)If
the specified key is not already associated with a value (or is mapped to null),
attempts to compute its value using the given mapping function and enters it
into this map unless null.
default V computeIfPresent(K key, BiFunction<? super K,? super V,?
extends V> remappingFunction)If the value for the specified key is present and
non-null, attempts to compute a new mapping given the key and its current
mapped value.
boolean containsKey(Object key)Returns true if this map contains a mapping for the
specified key.
boolean containsValue(Object value)Returns true if this map maps one or more keys to
the specified value.
L. HASSOUNI 105

Map Methods(2)
Set<Map.Entry<K,V>> entrySet()Returns a Set view of the mappings contained in this map.
boolean equals(Object o)Compares the specified object with this map for equality.
default void forEach(BiConsumer<? super K,? super V> action)Performs the given action for
each entry in this map until all entries have been processed or the action throws
an exception.
V get(Object key)Returns the value to which the specified key is mapped, or nullif
this map contains no mapping for the key.
default V getOrDefault(Object key, V defaultValue)Returns the value to which the
specified key is mapped, ordefaultValue if this map contains no mapping for the
key.
int hashCode()Returns the hash code value for this map.
boolean isEmpty()Returns true if this map contains no key-value mappings.
Set<K> keySet()Returns a Set view of the keys contained in this map.
default V merge(K key, V value, BiFunction<? super V,? super V,?
extends V> remappingFunction)If the specified key is not already associated
with a value or is associated with null, associates it with the given non-null
value.
L. HASSOUNI 106

Collections 53
Map Methods(3)
V put(K key, V value)Associates the specified value with the specified key in this map (optional
operation).
void putAll(Map<? extends K,? extends V> m)Copies all of the mappings from the specified map
to this map (optional operation).
default V putIfAbsent(K key, V value)If the specified key is not already associated with a value (or is
mapped to null) associates it with the given value and returnsnull, else returns the current
value.
V remove(Object key)Removes the mapping for a key from this map if it is present (optional
operation).
default boolean remove(Object key, Object value)Removes the entry for the specified key only if it is currently
mapped to the specified value.
default V replace(K key, V value)Replaces the entry for the specified key only if it is currently mapped
to some value.
default boolean replace(K key, V oldValue, V newValue)Replaces the entry for the specified key only if
currently mapped to the specified value.
default void replaceAll(BiFunction<? super K,? super V,? extends V> function)Replaces each entry's value
with the result of invoking the given function on that entry until all entries have been
processed or the function throws an exception.
int size()Returns the number of key-value mappings in this map.
Collection<V> values()Returns a Collection view of the values contained in this map.
L. HASSOUNI 107

Bien à vous
A terminer

Collections 54

Vous aimerez peut-être aussi