Cours-Gratuit
  • Accueil
  • Blog
  • Cours informatique
home icon Cours gratuits » Cours informatique » Cours programmation » Cours JAVA » Exercices JAVA »

Articles similaires

  • Exercice piles d'entiers - structures de données abstraites
  • Exercices java programmes - condition - moyenne d'une classe - Tables de vérité
  • Exercice polymorphisme JAVA Tour de carte
  • Exercice JAVA masquage (shadowing) et héritage
  • Série d'exercices Java sur la programmation orienté objet POO
  • Exercice java algorithme programme jeu de puissance 4
  • Java VS Python : Quel langage est le meilleur ?
  • Exercice opération sur les tableaux JAVA
  • Exercice JAVA palindrôme - string
  • Exercice JAVA opérateur infixé et postfixé
  • Exercice Java : Programme de gestion de ligne d'autocar
  • Exercice JAVA modularisation - erreurs fréquentes dans les méthodes

Documents similaires

  • Développons en Java avec Eclipse

  • Accès aux bases de données SQL Server en Java

  • Cours pour commencer le JAVA

  • Application Java sur le système de gestion d’hôpital

  • Mini projet calculatrice avec JAVA

  • Cours de langage Java avancé : les types génériques

  • Apprendre à Programmer avec Java étape par étape

  • Application client serveur de chat avec JAVA

Exercice liste chainée générique JAVA - Structures de données abstraites

Rédigé par GC Team, Publié le 17 Août 2010, Mise à jour le Lundi, 31 Août 2020 16:27
Participez au vote ☆☆☆☆☆★★★★★
But:
Ecrivez une liste chaînée générique capable de stocker des objets de n'importe quel type
Thème:
Structures de données abstraites, class Object
Fichiers:
ListeChaineeDouble.java, MoyenneListe.java

 

La classe ListeChaineeDouble de l'exercice 1 de la série 12 n'est pas "générique" : la liste chainée implémentée ne permet de stocker que des doubles.
Transformez le code des fichiers ListeChaineeDouble.java et MoyenneListe.java de sorte à parer à cet inconvénient.

Indications: Avant la version JDK 5.0 de Java, la seule façon de mettre en oeuvre la généricité consistait à utiliser la classe Object. Comme toute classe dérive de cette classe, et donc hérite de son type, il est possible de stocker dans un objet de type Object n'importe quel autre type d'objets. C'est cette façon de procéder que vous aller utiliser dans cet exercice.

Question: Citez un problème lié à cette façon de mettre en oeuvre la généricité.


 

Fichiers:

ListeChainee.java, MoyenneListe2.java

 

ListeChainee.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
class ListeChainee {

    private Noeud debut = null;
    private Noeud fin = null;
    private Noeud courant = null;

    //constructeurs
    public ListeChainee() {};

    public ListeChainee(Object valeur) {
        courant = new Noeud(valeur);
        fin = courant;
        debut = courant;
    }

    /** ajouter un élément à la liste */
    public void ajouterElement(Object valeur) {
        // on crée un nouvel élément de la liste
        // contenant le double <valeur>
        Noeud nouvelleFin = new Noeud(valeur);

        if (debut == null) {
            //c'est le tout premier élément de la liste
            // i.e. la liste était vide
            debut = nouvelleFin;
            fin = nouvelleFin;
        courant = nouvelleFin;
        } else {
            // la liste contenait déjà des éléments
            fin.setSuivant(nouvelleFin);
            fin = nouvelleFin;
        }
    }

    /** tester si l'élément courant n'est pas null */
    public boolean aCourant() {
        return (courant != null);
    }

    // retourner la valeur de l'élément courant de la liste
    public Object valeur() {
        if (aCourant()) {
            return (courant.getValeur());
        } else {
            return null;
        }
    }

    /** retourner le premier élément de la liste */
    public Noeud premier() {
        courant = debut;
        if (debut == null) {
            return null;
        } else {
            return debut;
        }
    }

    /** retourner l'élément suivant dans la liste */
    public Noeud suivant() {
        if (courant != null) {
            courant = courant.getSuivant();
        }

        if (courant == null) {
            return null;
        } else {
            return courant;
        }
    }
}

class Noeud {
    /** la valeur stockée */
    private Object valeur; 
    /** la référence à l'élément suivant de la liste */
    private Noeud suivant;

    public Noeud(Object valeur) {
        this.valeur = valeur;
        suivant = null;
    }

    public Object getValeur() {
        return valeur;
    }

    public void setValuer(Object newValeur) {
        valeur = newValeur;
    }

    public Noeud getSuivant() {
        return suivant;
    }

    public void setSuivant(Noeud newSuivant) {
        suivant = newSuivant;
    }

}

MoyenneListe2.java

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class MoyenneListe2 {

  public static void main(String[] args) {
        ListeChainee notes = new ListeChainee();

        /* Notre liste chaînée est programmée pour contenir
           des "Object"s.
           Si on veut travailler avec des valeurs numériques, il
           serait donc normalement nécessaire de stocker dans la 
           liste, des objets de type Double (qui sont des Objects)
           et non pas de type double (qui ne sont pas des Objects).
           Bref, il faudrait "emballer" nos doubles dans des Doubles:

           notes.ajouterElement(new Double(2.0));

           C'est en fait comme cela qu'il faut procéder dans toutes 
           les version de Java antérieures à la 1.5.
           Dans Java 1.5, le compilateur fait automatiquement 
           l'emballage/déballage pour vous, 
           (c'est ce qu'on appelle l'"autoboxing").
           Ec ceci nous permet d'écrire sans souci le code suivant:
        */
        notes.ajouterElement(2.0);
        notes.ajouterElement(1.0);
        notes.ajouterElement(6.0);
        notes.ajouterElement(5.5);

        notes.premier(); // on se positionne au début
        // de la liste
        // (notes.courant pointe sur le 1er noeud)

        double moyenne = 0.0;
        int n = 0;
        // tant que notes.courant n'est pas null
        // on avance dans le liste en calculant
        // la somme des notes
        while (notes.aCourant()) {
            // notes.valeur() donne le double stocké dans
            // notes.courant
          Double note = (Double)notes.valeur();
          if (note == null){
            note = Double.NaN; // Double.NaN est définie dans
                               // la classe Double et signifie
                               // "Not a Number"
          }
          moyenne += note.doubleValue();
          // En utilisant à nouveau l'autoboxing (JDK 5.0),
          // on peu écrire la ligne précédente comme suit:
          // moyenne += note;
          notes.suivant();
          n++;
        }

      System.out.println("La moyenne est: " + moyenne / n);
    }

}

 

 

Citez un problème lié à cette façon de mettre en oeuvre la généricité:

Les structures de données génériques codées de cette façon sont moins efficaces que leurs contreparties spécialisées : chaque accès à une donnée nécessite un transtypage entre le type effectif de l'objet et Object.

Ces transtypage ne peuvent évidemment pas se faire au moment de la compilation car le type effectif de la donnée n'est connu qu'au moment de l'exécution. Pour chaque opération de transtypage, l'interpréteur doit vérifier la compatibilité de type des objets lors de l'exécution.
Par exemple, si un String est stocké comme élément d'une structure de données et que l'on cherche à le transtyper en Integer, la machine virtuelle Java va déclencher une exception (plus précisément une ClassCastException).

Si le contenu d'une structure de données générique est accédé de façon intensive (par exemple lors d'un tri), toutes les opérations de transtypage nécessaires vont engendrer une dégradation substantielle de la performance. De plus, un code plein d'opérations de transtypage est beaucoup plus difficile a comprendre et, de facto, à maintenir.

D'un autre point de vue, les structures de données génériques sont très utiles puisqu'elles évitent d'écrire sans cesse le même code pour des types de données différents (ListeChainee pour les double, pour les int, pour les char, pour MesObjetsPreferesAMoi etc..). En fait de nombreuses structures de données génériques sont définies dans l'API de Java (listes, piles, tables de hashage etc..). C'est ce que l'on appelle le "Collection Framework". Dans les versions de Java antérieures à la 1.5, ces structures de données étaient programmées en utilisant des objets de type Object (comme vous l'avez fait dans cet exercice). Java 1.5, a introduit une nouvelle notion, les classes génériques (generics), permettant de contourner, en partie, les problèmes précités.

 

 

  • Contactez-nous
  • A propos de nous
  • On recrute
  • Rechercher dans le site
  • Politique de confidentialité
  • Droit d'auteur/Copyright
  • Conditions générales d'utilisation
  • Plan du site
  • Accueil
  • Blog
  • Finance et compta.
  • Formations Pro.
  • Logiciels & Apps
  • Organisation
  • Cours informatique
  • Aide à la rédaction
  • Etudes et Metiers
  • Science et Tech
  • Titans de la Tech
id 11354 02