---
# System prepended metadata

title: Les Collections

---

---
title: Les Collections
---

# XVI-	LES COLLECTIONS
## 1. Introduction
Pour gérer un ensemble d’éléments, java nous propose l'utilisation des tableaux. c'est ce qu'on a couvert précédemment dans le cours. 

Bien que simple à mettre en œuvre, cette solution n’est pas très souple. Son principal défaut tient au **caractère fixe de la taille d’un tableau**. 

S’il n’y a plus de place pour stocker des éléments supplémentaires, il faut créer un nouveau tableau plus grand et y transférer le contenu du tableau précédent. Cette solution, lourde à mettre en œuvre, est consommatrice de ressources.

En plus des tableaux, Java nous propose de nombreuses structures pour faciliter la gestion et la manipulation de grandes quantités d’informations. Elles sont regroupée sous le terme **collection**.

Les **collections** sont regroupées dans une vaste palette (**Framework**) d’interfaces et de classes: 
- Les interfaces décrivent les fonctionnalités disponibles 
- Les classes implémentent et fournissent réellement ces fonctionnalités

Suivant le mode de gestion des éléments souhaité, on utilisera la classe la plus adaptée. 

Cependant, les mêmes fonctionnalités de base doivent être accessibles quel que soit le mode de gestion (exemple : l'ajout d'éléments à une collection, la suppression ... etc. )

:::info
Pour assurer la présence de ces fonctionnalités indispensables dans toutes les classes, celles-ci ont été regroupées dans l’interface **Collection** qui est par la suite utilisée comme interface de base.
:::

Voici les avantages des collections: 

- **API cohérente**: l'API possède un ensemble d'interfaces de base telles que **Collection** ou **Map**, toutes les classes ( ArrayList , LinkedList , Vector , etc.) qui implémentent ces interfaces ont un ensemble commun de méthodes.
- **Réduit l'effort de programmation** : un programmeur n'a pas à se soucier de la conception de la collection, mais il peut plutôt se concentrer sur sa meilleure utilisation dans son programme. Par conséquent, le concept de base de la programmation orientée objet qui est l'abstraction a été mis en œuvre avec succès. 
- **Augmente la vitesse et la qualité du programme** : augmente les performances en fournissant des implémentations avec de hautes performances de structures de données et d'algorithmes utiles, car dans ce cas, le programmeur n'a pas besoin de penser à la meilleure implémentation d'une structure de données spécifique. Il peut simplement utiliser la meilleure implémentation pour augmenter considérablement les performances de son programme.

## 2. Hiérarchie de collection Framework
Le package **java.util** contient toutes les classes et interfaces requises par l'infrastructure de collections

La hiérarchie des interfaces et de classes est représentée sur le diagramme ci-dessous:

![](https://i.imgur.com/FuazeWf.png)

L'interface **Collection** (java.util.Collection) et l'interface **Map** (java.util.Map) sont les deux principales **interfaces racines** des classes de collection Java.

Toutes ces interfaces sont **génériques** afin de gérer des ensembles composés de n’importe quels types d’éléments tout en évitant les fastidieuses opérations de transtypage.

Pour chacune de ces interfaces, une ou plusieurs classes correspondantes sont disponibles. *Ce sont bien sûr celles-ci qui vont nous intéresser*

:::info
L'interface **Collection** étend l'interface **Iterable**. Par conséquent, toutes ses interfaces dérivées implémentent cette interface. 

La fonctionnalité principale de l'interface **Iterable** est de fournir un **Iterator** pour les collections. 
:::

## 3. La classe ArrayList
La classe **ArrayList** est une implémentation de l’interface **List**. 

Elle permet la gestion des éléments que l’on y place de manière quasi similaire à celle disponible avec un tableau, avec en plus l’**aspect dynamique**.

Elle ajuste automatiquement sa capacité à mesure que vous ajoutez et supprimez des éléments, sans que vous n’ayez rien à faire.

:::success
L'interface **List** est une collection **ordonnée** (**ses elements sont indexés, la première position est à l’index 0**) et elle peut contenir des éléments dupliqués. 
:::


List hérite les méthodes de l'interface Collection, l'interface List inclut des opérations comme la manipulation des éléments, la recherche, le parcours avec Iterator.

### Création
À la création d'un ArrayList, il est de mise de spécifier le type des objets qu'il contiendra
```java=
public static void main(String[] args) {
    // un ArrayList de chaînes de caractères
    ArrayList<String> semaine = new ArrayList<String>();

     // On peut typer l'objet par son interface
    List<String> mois = new ArrayList<String>();
    
        // on suppose ici que la classe Foobar a déjà été déclarée
    ArrayList<Foobar> liste = new ArrayList<Foobar>();
    
}
```
:::info
Pour des types primitifs, il faut utiliser les classes d'enrobage (**Wrapper**).
:::
 

Par exemple, pour un ArrayList de valeurs de type **int**, on utilise la classe d'enrobage **Integer**.
```java=
List<Integer> nombres = new ArrayList<Integer>();
```
### Ajouter des éléments
On utilise la méthode **add**, qui ajoute l'élément à la fin de la liste.
```java=
Foobar foo = new Foobar();
liste.add(foo);
```
Dans le cas des types primitifs, la conversion en une instance de la classe d'enrobage correspondante se fait automatiquement (c'est qu'on appelle l'**autoboxing**):
```java=
// ajoute un Integer
nombres.add(5);
```
Une version surchargée de cette méthode permet de choisir l’emplacement où les éléments sont placés.
```java=
liste.add(2,foo);
```
### Vérifier l'état de la liste
- Pour savoir si la liste est vide, on utlise la méthode **isEmpty**.
```java=
if(liste.isEmpty()){
    System.out.println("Liste vide");
}
```

- Pour savoir combien d'éléments elle contient (**sa taille**), on utilise la méthode **size**
```java=
System.out.println("La liste contient " + liste.size() + " éléments");
```

### Manipuler les éléments
- Pour vérifier si un élément est contenu dans la liste, on utilise la méthode **contains**
```java=
if(liste.contains(foo)){
    System.out.println("Objet trouvé!");
}
```

- Pour trouver la position d'un élément, on utilise la méthode **indexOf**. Cette méthode retourne **-1** si non trouvé.
```java=
System.out.println(
    "L'objet est à la position " + liste.indexOf(foo));
```

- Pour obtenir (sans le retirer) un élément situé à une position donnée, on utilise la méthode **get**.
```java=
// obtient le 6e élément
Foobar f = liste.get(5);
```
- Pour retirer un élément de la liste, on utilise la méthode **remove**. 
```java=
liste.remove(foo);
```
Si le même objet est plusieurs fois dans la liste, c'est la première occurence qui est supprimée.

### Parcourir une liste

Le mécanisme d'itération permet de parcourir séquentiellement tous les éléments d'une liste, de manière uniforme et efficace. 

Le parcours des éléments de la liste est possible avec une boucle **for**, **for each** ou en utilisant l’objet **Iterator** fourni par la méthode **iterator()** de la classe **Arraylist**.

- **Avec une boucle for** 
```java=
public static void main (String[] args){
     // Création d'une collection de type List
    List<String> couleurs =   ArrayList<String>();

    // Ajout des éléments
    couleurs.add("Bleu");
    couleurs.add("Rouge");
    couleurs.add("vert");
    
    // boucle for
    for (int i = 0; i < couleurs.size(); i++) {
          // Récupération de l'element à l'aide de la méthode get et son index
          System.out.println(couleurs.get(i));
    }
}
```
- **Avec la boucle for-each**

La boucle **for-each** (appelée **boucle for avancée**) a été intégrée depuis Java 5. Elle est utilisée pour parcourir les tableaux ainsi que les collections d'objets.

La boucle **for-each** est utilisée afin de prendre une par une les valeurs de la liste et la stocker à son tour dans la variable locale avant de la manipuler en se servant de cette variable.

```java=
public static void main (String[] args){
    // Création d'une liste grâce à la méthode staticasList de Arrays
    List<String> couleurs = Arrays.asList("Bleu", "Rouge", "vert");
    
    // Pour tout élément str de couleurs
    for (String str : couleurs) {
      System.out.println(str);
    }
}
```

- **Avec un Iterator** 

En Java, toute collection possède une méthode **iterator()** qui retourne un itérateur permettant d'accéder aux éléments un par un en **avançant** dans la collection. 
    
Initialement, l'itérateur **est placé avant le premier élément**. A chaque accès, le prochain élément est retourné et l'itérateur avance à l'élément suivant.

Les deux méthodes principales d'un itérateur sont :

- **hasNext()** qui retourne true s'il reste des éléments dans l'itération.
- **next()** qui retourne le prochain élément et avance dans l'itération. S'il n'y a plus d'élément, une **NoSuchElementException** est levée.
```java=
public static void main (String[] args){
     // Création d'une collection de type List
    List<String> couleurs = Arrays.asList("Bleu", "Rouge", "vert");
    
    // Crée un nouvel itérateur sur la liste, initialisé AVANT le 1er élément
    Iterator<String> it = couleurs.iterator();
    
    //Tant qu'il reste des éléments
    while (it.hasNext()) {
        
      // Récupère le prochain élément et avance
      String str = it.next();
        
      System.out.println(str);
    }
}
```

## 4. La classe HashSet
**HashSet**  implémente l'interface **java.util.Set**. 

La classe **HashSet** crée une collection d'objets **non-ordonée** qui utilise une **table de hachage** pour le stockag qui est un très bon atout pour les haute performances, mais il ne garantie pas l'ordre d'insertion des éléments.

Une table de hachage stocke les valeurs en leurs donnant une clé unique pour les identifier. Une clé ne peut pas être associée à deux valeurs contrairement à HashMap.

Une collection de type **Set** est la représentation du modèle mathématique des ensembles en java. 

l'interface **Set** hérite les méthodes de l'interface **Collection** et ajoute la propriété de l'interdiction des éléments en double qui doivent exister qu'une seule fois.

:::success
Une collection de type **Set** ne permet pas l'ajout de doublons ni l'accès direct à un élément de la collection.
:::
### Création
À la création d'un HashSet, il est de mise de spécifier le type des objets qu'il contiendra
```java=
public static void main(String[] args) {
    // un HashSet de chaînes de caractères
    HashSet<String> hset = new HashSet<String>();

     // On peut typer l'objet par son interface
     Set<String> mois = new HashSet<String>();
}
```
:::info
Pour des types primitifs, il faut utiliser les classes d'enrobage (**Wrapper**).
:::

### Ajouter des éléments
On utilise la méthode **add**
```java=
    //ajouter des éléments
    hset.add("hôtel");
    hset.add("motel");
    hset.add("fondouk");
    hset.add("ressort");;
```
L'invocation de la méthode add() avec en paramètre un élément déjà présent dans la collection n'aucun effet.

### Vérifier l'état d'un set
- Pour savoir si l'ensemble (Set) est vide, on utlise la méthode **isEmpty**.
```java=
if(hset.isEmpty()){
    System.out.println("Set vide");
}
```

- Pour savoir combien d'éléments il contient (**sa taille**), on utilise la méthode **size**
```java=
System.out.println("Le set contient " + hset.size() + " éléments");
```

### Manipuler les éléments
- Pour vérifier si un élément est contenu dans le set, on utilise la méthode **contains**
```java=
//tester l'existance
System.out.println(hset.contains("motel"));
```
- Pour retirer un élément de le set, on utilise la méthode **remove**. 
```java=
//supprimer l'objet motel
hset.remove("motel");
```

### Parcourir les éléments d'un set
- **Avec la boucle for-each**
```java=
public static void main (String[] args){
     //parcourir HashSet
     for(String valeur:hset){
        System.out.println(valeur);
     }
}
```
- **Avec un Iterator** 
Il est possible d’utiliser un Iterator pour parcourir les éléments d'un set.
```java=
public static void main (String[] args){
   
    // Crée un nouvel itérateur sur le set, initialisé AVANT le 1er élément
    Iterator<String> it = hset.iterator();
    
    //Tant qu'il reste des éléments
    while (it.hasNext()) {
        
      // Récupère le prochain élément et avance
      String str = it.next();
        
      System.out.println(str);
    }
}
```
## 5. La classe HashMap (Cartes)
https://programmation-orientee-objet.pages.ensimag.fr/poo/resources/fiches/08-Collections/#dictionnaires-map

https://programmation-orientee-objet.pages.ensimag.fr/poo/resources/fiches/08-Collections/#dictionnaires-map

https://www.jmdoudoux.fr/java/dej/chap-collections.htm

http://www.codeurjava.com/2015/06/linterface-map-de-java.html

https://www.geeksforgeeks.org/arraylist-in-java/?ref=lbp

https://developpement-informatique.com/article/260/hashmap-en-java---java.util.hashmap