Vous êtes sur la page 1sur 42

Institut National des Télécommunication et des Technologies

d'Information et de la Communication INT-TIC d'Oran Algérie

LE LANGAGE JAVA
Chapitre 5: Chaînes de caractères,
Tableaux, Collections
et Types Génériques en
Java
CHAÎNES DE CARACTÈRES
La classe String – Introduction

Pour manipuler les chaînes de caractères, Java


propose la classe String.

En java, une chaîne de caractères est un objet


(dans certains langages, un String n’est autre
qu’un tableau de caractères).

Java propose aussi les classes StringBuffer et


StringTokenizer avec des fonctionnalités
avancées.
CHAÎNES DE CARACTÈRES
La classe String – Instanciation

Les deux instructions suivantes d’instanciation sont


équivalentes :
String str = new String("Bonjour");
String str = "Bonjour";

On peut également créer un String à partir d’un


tableau de caractères :
char[ ] listeCaracteres = {'B', 'o', 'n', 'j', 'o', 'u', 'r'};
String str = new String(listeCaracteres);
CHAÎNES DE CARACTÈRES
La classe String – Instanciation

Un objet de la classe String, une fois défini, sa valeur


ne peut pas être modifiée.
En revanche, on peut lui attribuer une nouvelle
valeur comme suit :
String str = "Bonjour";
str = "nouveau texte";
En effet, la référence str ne référence plus l’objet
"Bonjour", mais un nouvel objet "nouveau texte".
CHAÎNES DE CARACTÈRES
La classe String – Comparaison

Soit l’instruction suivante : if (str1 == str2)…


cette instruction ne compare pas si les deux
chaines sont égales, mais si str1 et str2 pointent
sur le même objet.

Pour comparer si les deux chaînes str1 et str2


sont égales, on doit faire appel à une des
méthodes de la classe String, comme :
if (str1.equals(str2))… ou bien
if (str2.equals(str1))…
CHAÎNES DE CARACTÈRES
La classe String – Concaténation

L’opérateur + et la méthode concat permettent,


tous les deux, de concaténer des chaînes de
caractères :
String str1 = "Hello";
String str2 = "World";
String str3 = str1.concat(str2);
// donne HelloWord
String str4 = str1 + " " + str2;
// donne Hello Word
CHAÎNES DE CARACTÈRES
La classe String – Autres fonctionnalités

Extraction d’une sous-chaîne :


String substring (int debut, int fin)
String substring (int debut)
Longueur d’une chaînes :
int length ()

Conversion d’une chaîne :


String toLowerCase() //majuscule-minuscule
String toUpperCase() //minuscule-majuscule
CHAÎNES DE CARACTÈRES
La classe StringBuffer

Par rapport à un String, un StringBuffer est plus


flexible : on peut modifier son contenu.
StringBuffer () //construit une chaîne vide
d’une capacité 16 caractères
StringBuffer (int longueur) //construit une
chaîne vide de la capacité indiquée
StringBuffer (String str) //construit une
chaîne à partir du String str
CHAÎNES DE CARACTÈRES
La classe StringBuffer

La méthode append permet de rajouter à la


chaîne des expressions de différents types : char,
char[ ], double, float, int, long et String (c’est une
méthode surchargée).
StringBuffer st = new StringBuffer();
st.append("Cours");
st.append(" ");
st.append("de ");
st.append("Java");
//st contient donc "Cours de Java"
CHAÎNES DE CARACTÈRES
La classe StringBuffer

Capacité d’une chaîne :


int capacity ()
Nombre de caractères effectivement placés :
int length ()

Autres méthodes : setLength, insert, delete,


replace, …
CHAÎNES DE CARACTÈRES
La classe StringTokenizer

Elle permet de séparer une chaîne de caractères


en plusieurs moreceaux.
Exemple
String s = "Java est un langage Orienté Objet";
StringTokenizer st = new StringTokenizer(s);

System.out.println("Nombre de mots:" +
st.countTokens());
while (st.hasMoreTokens())
System.out.println(st.nextToken());
TABLEAUX
En Java, un tableau est un objet ayant un
nombre d’éléments fixe et pouvant contenir des
objets ou des types primitifs.

Toutefois, les tableaux en Java sont considérés


comme dynamiques car le nombre d’éléments :

– n’est pas un élément constitutif du type du


tableau, et n’a donc pas besoin d’apparaître dans
sa déclaration,

– n’est pris en compte qu’au moment de


l’exécution du programme, même s’il est connu
pendant la compilation,
TABLEAUX
Tableaux – Déclaration

Pour déclarer un tableau (d’entiers par exemple),


les deux syntaxes suivantes sont équivalentes,
même si la deuxième est plus « convenable »:

int tab[ ];
int[ ] tab;

Dans les deux cas, tab est une référence, et pour


le moment elle ne référencie rien.
TABLEAUX
Tableaux – Déclaration

Remarque : avec les déclarations précédentes,


on distingue deux cas de figure:

– soit il s’agit d’une variable d’instance, et dans


ce cas, tab aura été initialisé à null,

– soit il s’agit d’une variable locale, et dans ce


cas, tab est indéterminée. Mais il est toujours
possible de l’initialiser explicitement avec :
int[ ] tab = null;
TABLEAUX
Tableaux – Instanciation

Le tableau commence effectivement à exister lors


de son instanciation :
tab = new int[nombreElements];
où nombreElements est une expression, d’un type
entier, qui définit la taille du tableau.
Remarque : on peut instancier un tableau au
moment de sa déclaration :
int[ ] tab = new int[nombreElements];
TABLEAUX
Tableaux – Accès aux éléments
Une fois le tableau créé, on accède à ses élements
en utilisant la même syntaxe qu’en C :
tab[i]
où i est une expression entière dont la valeur doit
vérifier 0 ≤ i < nombreElements.

Note : Le nombre d’éléments est accessible via la


variable d’instance length (tab.length)
TABLEAUX
Tableaux – Contrôle de l’indice
Lors de l’accès à un élément d’un tableau (avec
tab[i]), Java contrôle toujours la validité de
l’indice.
Le système peut déclencher les exceptions
suivantes (cas d’erreurs les plus fréquents) :
– NullPointerException, pour indiquer que
tab=null, c’est-à-dire que la variable tab n’est pas
une référence valide (en clair, le plus souvent : le
tableau n’a pas encore été créé),
– ArrayIndexOutOfBoundsException, pour
indiquer que la condition 0 < i < tab.length n’est
pas satisfaite
TABLEAUX
Tableaux – Initialisation anonyme
Deux syntaxes permettent d’indiquer un ensemble
de valeurs devant remplir un tableau.
– initialiser le tableau au moment de sa déclaration
(comme en langage C):
int[] tab = { 1, 2, 4, 8, 16, 32, 64, 128, 256};
– créer un tableau rempli de valeurs, mais pas
forcément au moment de sa :
int[] tab;
...
tab = new int[] { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
TABLEAUX
Tableaux – Initialisation anonyme
Dans l’une comme dans l’autre, le nombre de valeurs
fournies détermine la taille du tableau.
La deuxième est particulièrement utile lorsqu’un
tableau ne sert qu’une seule fois.
Exemple : si la variable tab avait été déclarée et
construite dans l’unique but de figurer dans l’appel
d’une méthode (cela arrive) comme dans :
int tab[] = { 1, 2, 4, 8, 16, 32, 64, 128};
traiter(tab);
alors il aurait été plus simple de ne pas déclarer la
variable tab :
traiter(new int[] { 1, 2, 4, 8, 16, 32, 64, 128});
TABLEAUX
La classe java.util.Arrays
Elle contient différentes méthodes statiques
permettant de manipuler les tableaux, telles que les
méthodes de recherche et de tri.
Exemple
char[ ] tab = {'a', 'r', 'k', 'q', 'o', 's'};
Arrays.sort(tab); // tab={'a', 'k', 'o', 'q', 'r', 's'}
int res = Arrays.binarySearch(tab, 'k'); // res = 1
VECTEURS
Vecteurs – Introduction
Les tableaux en Java sont alloués
dynamiquement en ce sens que leur taille n’est
prise en compte qu’au moment de l’exécution,
quoiqu’il faut toujours la spécifier avant de
pouvoir les utiliser.
Lorsque la taille finale du tableau n’est pas
connue à l’avance, on préfère utiliser les
vecteurs (classe java.util.Vector). La taille d’un
vecteur varie en fonction des besoins.
En contrepartie, les vecteurs n’acceptent pas les
types primitifs : il faut les convertir en objets
(utiliser leurs enveloppes, wrappers en anglais).
VECTEURS
Vecteurs – Instanciation

Cette classe comporte différents constructeurs :


Vector vecteur = new Vector(); //créer un
//vecteur initialement vide
Vector vecteur = new Vector(50); //créer un
//vecteur initialisé à une certaine taille n fournie
//en argument, mais lorsqu’un dépassement de
//capacité intervient, la capacité augmentera de n
Vector vecteur = new Vector(100,10); //créer un
//vecteur initialisé à une certaine taille n avec un
//pas d’incrémentation si la capacité est dépassée
VECTEURS
Vecteurs – Méthodes
int capacity(); //taille du vecteur
int size(); //nombre d’éléments effectif
addElement(Object o); //insertion d’un objet
removeElementAt(int i); //suppression d’un élément à
//la position i
Object elementAt(int i); //obtention du ième élément
int indexOf(Object o); //obtention de l’index de l’objet o
setElementAt(Object o, int i); //remplacement de
//l’objet à l’index i par l’objet o
VECTEURS
Vector, ArrayList et LinkedList

L’API Java contient depuis la version 1.2 les


collections, dont la classe java.util.ArrayList. Elle
a quasiment le même rôle que Vector (héritée de la
version 1.0, elle a été maintenue pour des raisons
de compataibilité).

La classe java.util.LinkedList fait aussi partie des


collections. Elle utilise une liste chaînée pour
ranger les données. Elle peut être utilisée comme
une pile (il existe également la classe
java.util.Stack pour créer des piles).
DICTIONNAIRES (HASHTABLE)
La classe java.util.Hashtable permet de stocker
des valeurs en les associant à des identificateurs
appelés clés.
Les clés et les valeurs peuvent être des objets de
n’importe quel type.
Exemple
Hashtable monDictionnaire = new Hashtable();
monDictionnaire.put(new Integer(1), "Janvier");
monDictionnaire.put(new Integer(2), "Février");
monDictionnaire.put(new Integer(3), "Mars");

System.out.println(monDictionnaire.get(new Integer(2)));
//affichera "Février"
ENUMÉRATIONS ET ITÉRATEURS
L’interface java.util.Enumeration fournit deux
méthodes permettant de parcourir les éléments
d’un vecteur ou les clés et les valeurs d’un
dictionnaire.

Exemple
Vector vecteur = new Vector();

Enumeration e = vecteur.elements();
while ( e.hasMoreElements()) {
System.out.println(e.nextElement());
}
// La méthode elements() de Vector renvoie un objet e
// implémentant l’interface enumeration
ENUMÉRATIONS ET ITÉRATEURS
Remarques

– Après le premier appel de la méthode


nextElement(), l’énumération pointe sur le 1er
élement.

– Pour repositionner l’énumération au 1er


élément, il faut refaire appel à la méthode
element() qui renvoie une nouvelle énumération.

– En cas d’ajout ou de suppression des éléments,


il faut récupérer une nouvelle énumération (mise
à jour).
ENUMÉRATIONS ET ITÉRATEURS
L’interface java.util.Iterator se substitue à
l’interface java.util.Enumeration dans le cadre des
collections.

la méthode iterator() des collections renvoie un objet


implémentant l’interface Iterator :
Exemple Collection collection = new ArrayList();

Iterator it = collection.iterator();
while ( it.hasNext()) {
Object o = it.next();
System.out.println(o.toString());
it.remove(); // supprime l’élement courant
}
TYPES GÉNÉRIQUES
Soient les deux classes suivantes et leurs
instanciations respectives :
public class EnglobeurString { public class EnglobeurInt {
private String msg; private int n;
… // Constructeurs … // Constructeurs
public void add (String msg) { public void add (int n) {
this.msg = msg; this.n = n;
} }
public String get () { public int get () {
return this.msg; return this.n;
} }
} }

EnglobeurString myString = EnglobeurInt myInt =


new EnglobeurString (); new EnglobeurInt ();
TYPES GÉNÉRIQUES
La classe générique suivante récapitule les deux
classes :
public class Englobeur <T> {
private T t;
… // Constructeurs
public void add (T t) {
this.t = t;
}
public T get () {
return this.t;
}
}

Les types génériques ont été introduits en Java


depuis sa version 5.
TYPES GÉNÉRIQUES
Avec cette nouvelle classe, les deux objets myString
et myInt s’instancient de la manière suivante :
Englobeur <String> myString = new Englobeur <String> ();

Englobeur <int> myInt = new Englobeur <int> ();

et depuis la version 7 de Java :


Englobeur <String> myString = new Englobeur <> ();

Englobeur <int> myInt = new Englobeur <> ();

L’instanciation suivante est également possible :


Englobeur <float> myFloat = new Englobeur <> ();
TYPES GÉNÉRIQUES
Types Génériques et les Collections

Les types génériques ont été introduits en Java,


principalement, pour contourner quelques
problèmes rencontrés à l’exécution en manipulant
les collections.

Remarquons l’exemple suivant (utilisant la


collection ArrayList), avec ces deux versions, avec
et sans les types génériques :
TYPES GÉNÉRIQUES
public class CollectionAncienneVersion {
public static void main (String[] args) {

List maListe = new ArrayList(3);

maListe.add(new Integer(5));
maListe.add(new Integer(9));
maListe.add(new Integer(4));
maListe.add("une chaine de caractères");
// ce dernier élément est accepté, mais pose problème après
Iterator it = maListe.iterator();
while (it.hasNext()) {
Integer entierObjet = (Integer) (it.next());
// Erreur à l’exécution (pas à la compilation)
int entier = (int) entierObjet.intValue();
System.out.println(" valeur de l’entier : "+ entier);
}
}
}
TYPES GÉNÉRIQUES
public class CollectionNouvelleVersion {
public static void main (String[] args) {

List<Integer> maListe = new ArrayList<>(3);


maListe.add(new Integer(5));
maListe.add(new Integer(9));
maListe.add(new Integer(4));
// maListe.add("une chaine de caractères");
// cette instruction aurait déclenché une erreur dès la compilation
maListe.add(new Integer(2));
Iterator<Integer> it = maListe.iterator();
while (it.hasNext()) {
Integer entierObjet = it.next();
// Pas d’erreur à l’exécution
int entier = (int) entierObjet.intValue();
System.out.println(" valeur de l’entier : "+ entier);
}
}
}
TYPES GÉNÉRIQUES
Types Génériques et les Collections

Les types génériques permettent donc d’éviter des


erreurs de cast explicite, ne pouvant être
découverts qu’à l’exécution.

Ainsi, une collection instanciée pour stocker des


Integer n’accepte pas des objets d’autres types.

Avant la version 5, une collection acceptait


n’importe quel objet. C’était au programmeur de
gérer ces objets (par des transtypages explicites)
pendant leur extraction, et de faire en sorte qu’il
n’y ait pas d’erreur à l’exécution.
TYPES GÉNÉRIQUES
Méthodes Génériques
On peut définir une méthode générique dans une
classe de la façon suivante :
public class X {
public <T> void affiche(Englobeur<T> p){
System.out.println(p);
}

public static void main(String [] a){


Englobeur<String> ps = new Englobeur<>("msg");
Englobeur<int> pi = new Englobeur<>(5);
X x = new X();
x.affiche(ps);
x.affiche(pi);
}
}
TYPES GÉNÉRIQUES
Contraintes dans les types génériques
Soit la méthode générique suivante qui permet de calculer le
minimum d’un tableau :
public class X {
public static <T> T min (T[] tab){
if (tab==null || tab.length==0) return null;
T m = tab[0];
for (T elm : tab)
if (m.compareTo(elm) > 0) m = elm;
return m;
}
}

Cette méthode provoquera une erreur à la compilation. En effet, il


n’y a aucune garantie que le type T dispose de la méthode
compareTo,
TYPES GÉNÉRIQUES
Contraintes dans les types génériques
Solution : imposer une limite pour le paramètre de type T de la
façon suivante :
public class X {
public static <T extends Comparable> T min (T[] tab){
...
}
}

Le type T est restreint aux seules classes implémentant l’interface


Comparable.

La méthode min ne peut s’appliquer que sur des tableaux dont le


type de base implémente l’interface Comparable.
TYPES GÉNÉRIQUES
Contraintes dans les types génériques
syntaxe : <T extends Type_Limitant>

Type_Limitant peut être une classe ou une interface (le mot clé
extends est utilisé dans les deux cas).

Il est possible de définir plusieurs types limitant (séparés par des


&):
<T extends Comparable & Serializable>

Parmi les types limitant, on ne peut avoir qu’une seule classe


(comme pour l’héritage). Dans ce cas, la classe doit figurer en
première position.
TYPES GÉNÉRIQUES
Types génériques vs Héritage
Soient les objets ps et es (sachant que Etudiant hérite de Personne ) :
ArrayList <Personne> ps = ...
ArrayList <Etudiant> es = ...

ps = es; // provoque une erreur de compilation


// ArrayList <Etudiant> n’est pas une sous classe de
// ArrayList <Personne>

En effet, si cela était possible, nous aurions :


ps.set (0, new Personne ());
Etudiant e = es.get (0); // ce qui provoquera une erreur
TYPES GÉNÉRIQUES
Types génériques vs Héritage
De même, la méthode suivante :
public void affiche(List<Object> list){
for (Object o : list)
System.out.println(o);
}
ne peut afficher qu’une liste de Object.

List<Personne> ps = ...
affiche (ps); // provoque une erreur de compilation
TYPES GÉNÉRIQUES
Types génériques vs Joker « ? »
En utilisant les joker (?) :
public void affiche (List<?> list){
for (Object o : list)
System.out.println(o);
}

On peut donc utiliser cette méthode pour afficher n’importe quelle liste :
affiche (new ArrayListe <Object>);
affiche (new ArrayListe <Personne>);

On également utiliser des types limitant :


public void affiche (List<? extends Personne> list){
for (Personne p : list)
System.out.println(p);
}

Vous aimerez peut-être aussi