\exercice Soit la classe Etudiant. En utilisant les collections, Écrire une classe promotion, disposant des méthodes suivantes : \begin{mycode} add(Etudiant e); remove(Etudiant e); Iterator iterator() double getMoyenne() \end{mycode} \begin{itemize} \item utilisez une ArrayList pour implémenter Promotion \item vous écrirez la méthode \texttt{moyenne} en utilisant un itérateur ; \end{itemize} \begin{correction} \textbf{Correction} \begin{mycode} // Version de promotion pour l'exercice 1 : import java.util.*; public class Promotion { private ArrayList etudiants; public Promotion() { etudiants= new ArrayList(); } public void add(Etudiant e) { etudiants.add(e); } public void remove(Etudiant e) { etudiants.remove(e); } public Iterator iterator() { return etudiants.iterator(); } double getMoyenne() { double somme= 0.0; for (Iterator i= iterator(); i.hasNext(); ) { Etudiant e= (Etudiant)i.next(); somme+= e.getMoyenne(); } return somme / etudiants.size(); } public String toString() { String s= ""; for (Iterator i= iterator(); i.hasNext(); ) { s+= i.next() + "\backslash«»n"; } return s; } public static void main(String args[]) { Promotion promo= new Promotion(); Etudiant e, e1; e= new Etudiant(20, "Turing"); e.setMoyenne(16); promo.add(e); e= new Etudiant(10, "Babbage"); e.setMoyenne(12); promo.add(e); e1= e; e= new Etudiant(34, "Lovelace"); e.setMoyenne(18); promo.add(e); e= new Etudiant(2, "Wirth"); e.setMoyenne(13); promo.add(e); System.out.println(promo); promo.remove(e1); System.out.println(promo); System.out.println("moyenne "+ promo.getMoyenne()); } } \end{mycode} On pourrait écrire \texttt{Promotion extends ArrayList.} Cependant, la solution choisie est plus correcte. En effet, on peut ajouter n'importe quoi dans une \texttt{ArrayList}. Par contre, dans notre classe \texttt{Promotion,} il est impossible d'ajouter autre chose qu'un étudiant. L'iterateur, seul pose un léger problème car il oblige à un cast. Une solution possible, mais un peu lourde, consiste à définir une classe \texttt{PromotionIterator,} dont la méthode \texttt{next} retourne un \texttt{Etudiant} et non un \texttt{Object}. La méthode iterator est modifiée : \begin{mycode} public PromotionIterator iterator() { return new PromotionIterator(this); } \end{mycode} avec \begin{mycode} public class PromotionIterator { Iterator representation; PromotionIterator(Promotion p) { representation= p.iterator(); } public boolean hasNext() { return representation.hasNext(); } public Etudiant next() { return (Etudiant)representation.next(); } } \end{mycode} \end{correction} \exercice{} Même chose, mais on veut remplacer la \emph{liste} des éléments par un \emph{ensemble} ordonné, les étudiants étant classés par ordre alphabétique (et affichés de même). \begin{correction} \mbox{} \paragraph{Correction.} Il suffit de remplacer \texttt{ArrayList} par \texttt{TreeSet} dans l'exercice précédent. Pour que cela fonctionne, il faut modifier la classe \texttt{Etudiant} qui doit implémenter l'interface \texttt{Comparable.} La méthode \texttt{compareTo} à écrire est : \begin{mycode} //... Dans la classe Etudiant ... public int compareTo(Object o) { Etudiant e= (Etudiant)o; // On compare les noms. int res= nom.compareTo(e.nom); // Deux étudiants de même nom, mais de numéros // différents, sont différents. D'où le test qui // suit : if (res!=0) { return res; } else { return numero - e.numero; } } \end{mycode} \end{correction} \exercice{} La classe DicoFrame est l'interface d'un dictionnaire. L'utilisateur peut y insérer un mot et visualiser les définitions existantes. On veut compléter \texttt{DicoFrame} en écrivant une classe \texttt{Dictionnaire}. Vous pourrez utiliser une \texttt{Map}. \begin{itemize} \item faites fonctionner le bouton \texttt{insérer} \item faites fonctionner le bouton \texttt{chercher} \item faites fonctionner le bouton \texttt{lister} : la liste des mots définis apparaîtra dans la fenêtre centrale. \item Regardez la documentation de \texttt{SortedMap}. modifiez la fonction de recherche pour qu'elle renvoie le premier mot qui \emph{commence} par ce qui est tapé dans la fenêtre du haut. \end{itemize} \begin{correction} \mbox{} \paragraph{Correction :} on notera en particulier le parcours du tableau associatif. \begin{mycode} import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; // Il serait plus propre d'avoir une classe dictionnaire séparée. public class DicoFrame1 extends JFrame implements ActionListener { private JButton chercher; private JButton inserer; private JButton lister; // Le mot à definir ou à chercher : private JTextField mot; private JTextArea definition; private TreeMap dictionnaire; public DicoFrame1() { // On donne à la fenêtre le nom "Dictionnaire". super("Dictionnaire"); Container p= getContentPane(); // On fixe le layout. p.setLayout(new BorderLayout()); // On crée les champs textes et on les ajoute : mot= new JTextField(); definition= new JTextArea(10,30); p.add(mot, BorderLayout.NORTH); p.add(definition, BorderLayout.CENTER); // On crée un panneau pour les boutons : JPanel sub= new JPanel(); // On crée les boutons et on les ajoute. chercher= new JButton("chercher"); inserer= new JButton("inserer"); lister= new JButton("lister"); chercher.addActionListener(this); inserer.addActionListener(this); lister.addActionListener(this); sub.setLayout(new FlowLayout()); sub.add(chercher); sub.add(inserer); sub.add(lister); // On ajoute le panneau des boutons à l'application. p.add(sub, BorderLayout.SOUTH); // On crée le dictionnaire dictionnaire= new TreeMap(); } /** * * @param param1 event */ public void actionPerformed(ActionEvent param1) { if (param1.getSource() == chercher) { definition.setText((String)dictionnaire.get(mot.getText())); } else if ( param1.getSource() == inserer) { dictionnaire.put(mot.getText(), definition.getText()); mot.setText(""); definition.setText(""); } else if ( param1.getSource() == lister) { Set entrees= dictionnaire.entrySet(); definition.setText(""); for (Iterator i= entrees.iterator(); i.hasNext();) { // Récupérer la clef Map.Entry entree= (Map.Entry)i.next(); String clef = (String) entree.getKey(); // L'ajouter dans la fenêtre de texte : definition.append(clef+ "\backslash«»n"); } } } public static void main(String arg[]) { DicoFrame1 f= new DicoFrame1(); f.pack(); f.setVisible(true); } } \end{mycode} Pour la dernière question, on utilise la méthode \texttt{tailMap} (voir \texttt{SortedMap} dans la javadoc). Comme une \texttt{TreeMap} est une \texttt{SortedMap,} il suffit d'écrire : \begin{mycode} if (param1.getSource() == chercher) { // On considère le dictionnaire des mots // supérieurs ou égaux à mot.getText(); Map sousDico= dictionnaire.tailMap(mot.getText()); // On veut en récupérer le premier élément -- s'il // existe ! Il y a de nombreuses solutions. // La suivante n'est pas la plus efficace, mais elle // est simple : // S'il y a au moins un mot >= prefixe cherché : if (sousDico.size() > 0) { String premier= sousDico.firstKey(); // et que le plus petit de ces mots commence // effectivement par le mot cherché ... if (premier.startsWith(mot.getText()) { mot.setText(premier); definition.setText((String)dictionnaire.get(premier)); } } } \end{mycode} \end{correction}