TP sur les collections

Page Home (contact) Retour TPs

Support de cours


Collections et itérateurs, interfaces, tris

  1. Dans la classe Entreprise (simplifiée par rapport aux TPs précédents ; utilisez aussi cette classe simplifiée Employe) ajoutez une méthode iterEmployes qui retourne un itérateur pour obtenir tous les employés de l'entreprise. C'est simple, il suffit d'utiliser l'itérateur de la liste. Dans la méthode main de la classe TestEntreprise, utilisez cet itérateur pour afficher le total des salaires des employés de chacune des 2 entreprises.
  2. Faites les modifications pour qu'on puisse parcourir tous les employés d'une entreprise avec une boucle "for-each" : "for (Employe employe : entreprise) ..." (interface Iterable). Testez dans TestEntreprise en utilisant une boucle for-each pour calculer le total des salaires d'une des entreprises.
  3. Toujours dans la méthode main, faites afficher les noms des employés de l'une des entreprises, par ordre alphabétique de leur nom. Pour cela, vous modifierez la classe Employe pour qu'elle implémente l'interface Comparable. Vous donnerez l'ordre alphabétique des noms des employés comme ordre "naturel" des employés. Dans la méthode main vous copierez tous les employés dans une liste que vous trierez.
  4. Faites afficher les noms et salaires des employés de l'une des entreprises, classés par salaire décroissant, puis par salaire croissant. Pour cela,
    1. Créez une classe qui implémente l'interface Comparator pour comparer les employés par leur salaire. Le constructeur de cette classe a un paramètre de type boolean qui permet d'indiquer si on veut un tri croissant ou décroissant (sa valeur est true pour un tri croissant).
    2. Dans la méthode main, ajoutez tous les employés dans une liste des employés de l'entreprise et triez la liste avec ce comparateur.
    3. Triez les employés par ordre croissant des salaires en vous inspirant des exemples du cours qui utilisent la méthode static comparing de l'interface Comparator (à la place de la classe du a.).
  5. Faites afficher par ordre alphabétique les noms des employés des 2 entreprises réunies.

Correction :

Question 1
Question 2
Question 3
Question 4
Question 5


Une "base de données" d'articles

On part de l'exercice sur les articles vendus dans un commerce.

Dans un "vrai" commerce, les caractéristiques des articles seraient conservées dans une base de données. En attendant de savoir comment travailler en Java avec une base de données, vous allez enregistrer les articles dans une table de hachage (HashMap) dont les clés seront les références des articles et les valeurs seront les articles eux-mêmes.

Tout article du magasin a une référence qui l'identifie parmi les autres articles. Ensuite, les articles ne sont plus désignés que par leur référence (dans les factures ou bien dans les lots). Leurs caractéristiques (par exemple, leur prix unitaire), sont ensuite automatiquement récupérés depuis la table de hachage.

Où mettre cette table de hachage ? Aide. Comment les articles seront mis dans la table de hachage ? Aide.

Écrivez le code correspondant. Comme pour les autres TPs, créez un nouveau projet pour cet exercice.

Pour bien comprendre ce qui vous est demandé, lisez le code de cette classe TestFacture qui vous servira à tester. Remarquez comment la méthode ajouterLigne prend en paramètre une référence d'article, par exemple la String "s001" et plus un objet Article. De même un lot est créé en donnant la référence (de type String, pas Article) de l'article qui le compose.

Vous aurez donc des erreurs dans la classe TestFacture. Ne touchez pas à cette classe. Les erreurs seront corrigées en modifiant le code des classes Facture et Lot pour utiliser des références d'article de type String à la place des articles eux-mêmes. Par exemple, le constructeur de la classe Lot aura la signature
public Lot(String reference, String nom, String referenceArticle, int nb, int pourcentage)
à la place de
public Lot(String reference, String nom, Article article, int nb, int pourcentage).

Correction :

Toutes les classes

Map pour les lignes de facture

Cet exercice est optionnel.

Reprenez l'exercice précédent sur la facture qui utilise une map comme source de données.

La classe Facture utilise une classe Ligne pour représenter une ligne de facture. Pour cet exercice vous allez utiliser une map pour implémenter une ligne de la facture, à la place de la classe Ligne. Ligne contient une référence d'article et une quantité. Vous allez donc travailler avec une map de type Map<String, Integer> dont les clés sont les références d'article et les valeurs sont les quantités de ces articles. Vous allez enlever la classe Ligne et utiliser la map à la place. Une ligne de la facture sera de type Map.Entry<String, Integer>.

Vous devrez modifier seulement le code de Facture car l'implémentation d'une ligne de facture est cachée pour les classes autres que la classe Facture (les avantages de l'encapsulation...).

Pour vous aider voici le code des méthodes pour afficher la facture (vous devez comprendre ce code, en particulier la boucle for-each et le type Map.Entry qui a été étudié dans le cours) :

  /**
   * Affichage de la facture sous une forme plus lisible. Utilisation de printf
   * "comme dans le langage C" (pas étudié dans le cours).
   */
  public void afficheToi() {
    System.out.printf("Facture numéro %d ; Client : %s ; Date : %s %n",
            numero, client, date);
    System.out.printf("%7s | %6s | %22s | %10s | %10s %n",
            "Quant.", "Réf.", "Nom", "PU", "PT");
    for (Map.Entry<String, Integer> entree : lignes.entrySet()) {
      afficherLigne(entree);
    }
    System.out.printf("%35s Prix total facture : %10d", "", getPrixTotal());
    System.out.println();
  }

  private void afficherLigne(Map.Entry<String, Integer> entree) {
    Article article = Article.getArticle(entree.getKey());
    int quantite = entree.getValue();
    System.out.printf("%7d | %6s | %22s | %10d | %10d %n",
            quantite, article.getReference(),
            article.getNom(),
            article.getPU(), article.getPU() * quantite);
  }

Correction

Classe Facture


Trouverez-vous les erreurs ?

Erreur 1 : Voici une classe et une autre classe pour tester la première classe.

  1. Lancez le test. Pourquoi le fonctionnement est anormal ?
  2. Modifiez le code pour rétablir un fonctionnement normal.

Erreur 2 : Voici une classe Employe, et une classe TestEmploye dont la méthode main enlève tous les employés qui gagnent moins de 10.000.

  1. Lancez le test. Expliquez ce qui se passe.
  2. Cette question est optionnelle, ne la cherchez qu'après avoir fini toutes les autres questions de ce TP. Commentez les 2 lignes qui ajoutent Fred et Pierre. relancez l'exécution et expliquez ce qui est affiché.
  3. Modifiez le code du départ (avec Fred et Pierre) pour avoir un fonctionnement normal.

Correction :

Les classes pour l'erreur 1
Explications et code pour erreur 2


Itérateur

Dans la classe Etagere de cet exercice, ajoutez une méthode iterator qui renvoie un itérateur qui parcourt les livres d'une étagère.

La classe de l'itérateur sera une classe interne. Pour commencer implémentez seulement les fonctionnalités de base des méthodes hasNext et next de l'itérateur renvoyé et écrivez une méthode remove qui lève une NoSuchOperationException.

Si vous avez le temps (cette question est plus difficile), implémentez une méthode remove opérationnelle et la gestion des exceptions NoSuchElementException, IllegalStateException et ConcurrentModificationException (voir javadoc de Iterator et de ConcurrentModificationException : "if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.").

Correction :

Etagere.java


Pour ceux qui ont déjà fini...

Si vous voulez en savoir plus sur les collections, lisez le tutoriel d'Oracle à l'adresse http://download.oracle.com/javase/tutorial/collections/index.html


Retour TPs