Exercices dirigés NFP121
Les collections, les Patrons Iterator et Template Method
Le projet BlueJ
L'interface CollectionI<E>
import java.util.Iterator; public interface CollectionI<E> extends Iterable<E>{ /** Ajout d'un élément à la collection. * @param e l'élément (!=null) * @return true si la collection a été modifiée */ boolean ajouter(E e); /** Ajout de tous les éléments d'une collection à la collection. * @param c la collection (!=null) * @return true si la collection a été modifiée */ boolean ajouter(CollectionI<E> c); /** Suppression d'un élément de la collection. * @param e l'élément (!=null) * @return true si la collection a été modifiée */ boolean supprimer(E e); /** Suppression de tous les éléments de c de la collection en cours. * @param c une collection (!=null) * @return true si la collection a été modifiée */ boolean supprimer(CollectionI<E> c); /** Obtention d'un itérateur sur la collection. * @return un itérateur */ Iterator<E> iterator(); /** Test de la présence d'un élément. * @param e l'élément (!=null) * @return true si cet élément est présent */ boolean contient(E e); /** Test de l'inclusion d'une collection. * @param c une collection (!=null) * @return true si c est incluse dans la collection */ boolean contient(CollectionI<E> c); /** Obtention du nombre d'éléments de l'inclusion d'une collection. * @return le nombre d'élément de la collection */ int taille(); /** Egalité de deux collections, même taille, mêmes éléments. * @return true si les deux collections sont égales */ boolean equals(Object o); /** Obtention d'une valeur de hashCode. * Soit ici la somme des valeur de hashCode de chaque élément. * @return une valeur */ int hashCode(); }
Seules les méthodes ajouter et iterator sont laissées à la responsabilité des sous-classes, en rappel le patron Template Method
QUESTION 1 : Complétez toutes les méthodes de la classe IncompleteCollection ci_dessous
import java.util.Iterator; public abstract class IncompleteCollection<E> implements CollectionI<E>{ public abstract boolean ajouter(E e); public abstract Iterator<E> iterator(); public boolean ajouter(CollectionI<E> c){ boolean res = false;
// à compléter
return res; } public boolean supprimer(E e){ if(e==null) throw new NullPointerException();
// à compléter
return false; } public boolean supprimer(CollectionI<E> c){ boolean res = false;
// à compléter
return res; } public boolean contient(E e){
// à compléter
return false; } public boolean contient(CollectionI<E> c){
// à compléter
return true; } public boolean equals(Object o){ if(o==null || !(o instanceof CollectionI)) return false; CollectionI<E> c = (CollectionI<E>)o;
// à compléter
return false; } public int hashCode(){ int res = 0; // à compléter return res; } public int taille(){ int res = 0;
// à compléter
return res; } public String toString(){ String str = "[";
// à compléter
return str + "]"; } }
QUESTION2: Proposez une classe concrète nommée Sac, un sac d'objets, l'implémentation est libre et la classe de tests unitaires SacTest ci-dessous doit s'exécuter sans échec, classe que vous pouvez enrichir.
public class Sac<E> extends IncompleteCollection<E>{
// à compléter
public class SacTest extends junit.framework.TestCase{ public void testAjouterEtTaille(){ CollectionI<Integer> sac = new Sac<Integer>(); assertTrue(sac.ajouter(3)); assertTrue(sac.contient(3)); assertTrue(sac.ajouter(2)); assertTrue(sac.contient(2)); assertTrue(sac.ajouter(1)); assertTrue(sac.contient(1)); assertEquals(3,sac.taille()); } public void testSupprimer(){ CollectionI<Integer> sac = new Sac<Integer>(); assertTrue(sac.ajouter(3)); assertEquals(1,sac.taille()); assertTrue(sac.contient(3)); assertTrue(sac.supprimer(3)); assertEquals(0,sac.taille()); assertTrue(sac.ajouter(3)); assertTrue(sac.ajouter(3)); assertTrue(sac.ajouter(2)); assertTrue(sac.contient(2)); assertEquals(3,sac.taille()); assertTrue(sac.supprimer(2)); assertEquals(2,sac.taille()); } public void testAjouterCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(1); int n = sacA.taille(); CollectionI<Integer> sacB = new Sac<Integer>(); sacB.ajouter(4);sacB.ajouter(sacA); assertEquals(n+1, sacB.taille()); assertTrue(sacB.contient(3)); assertTrue(sacB.contient(2)); assertTrue(sacB.contient(1)); assertTrue(sacB.contient(4)); } public void testSupprimerCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(1); CollectionI<Integer> sacB = new Sac<Integer>(); sacB.ajouter(2);sacB.ajouter(4);sacB.ajouter(3); assertTrue(sacB.supprimer(sacA)); assertEquals(1, sacB.taille()); assertTrue(sacB.contient(4)); } public void testEgaliteCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(1); CollectionI<Integer> sacB = new Sac<Integer>(); sacB.ajouter(2);sacB.ajouter(4);sacB.ajouter(3); assertFalse(sacA.equals(sacB)); sacB.supprimer(4); sacA.supprimer(1); assertTrue(sacA.equals(sacB)); } // à compléter }
QUESTION3: Proposez une sous-classe de Sac concrète nommée SacAObjetsUniques, ce sac est sans doublon, l'implémentation est libre et la classe de tests unitaires SacAObjetsUniquesTest ci-dessous doit s'exécuter sans échec.
public class SacAObjetsUniques<E> extends Sac<E>{
// à compléter
// Une seule méthode est à redéfinir, pourquoi ?
public class SacAObjetsUniquesTest extends junit.framework.TestCase{ public void testAjouter(){ CollectionI<Integer> sac = new SacAObjetsUniques<Integer>(); assertTrue(sac.ajouter(3)); assertEquals(1,sac.taille()); assertTrue(sac.contient(3)); assertTrue(sac.ajouter(2)); assertEquals(2,sac.taille()); assertFalse(sac.ajouter(3)); assertEquals(2,sac.taille()); assertFalse(sac.ajouter(2)); assertEquals(2,sac.taille()); } public void testAjouterCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(2);sacA.ajouter(2);sacA.ajouter(1);sacA.ajouter(1); assertEquals(6, sacA.taille()); CollectionI<Integer> sacB = new SacAObjetsUniques<Integer>(); sacB.ajouter(4);sacB.ajouter(sacA); assertEquals(4, sacB.taille()); assertTrue(sacB.contient(3)); assertTrue(sacB.contient(2)); assertTrue(sacB.contient(1)); assertTrue(sacB.contient(4)); } public void testSupprimerCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(1); CollectionI<Integer> sacB = new SacAObjetsUniques<Integer>(); sacB.ajouter(2);sacB.ajouter(4);sacB.ajouter(4);sacB.ajouter(3); assertTrue(sacB.supprimer(sacA)); assertEquals(1, sacB.taille()); assertTrue(sacB.contient(4)); }
// à compléter, }
QUESTION4: Proposez une sous-classe de SacAObjetsUniques concrète nommée SacOrdonneAObjetsUniques, le sac est ordonné, et sans doublon, l'implémentation est libre et la classe de tests unitaires SacOrdonneAObjetsUniquesTest ci-dessous doit s'exécuter sans échec.
public class SacOrdonneAObjetsUniques<E> extends SacAObjetsUniques<E>{
Une exception de type RuntimeException est levée si lors de l'ajout l'élément n'est pas comparable, i.e. la classe n'implémente pas l'interface Comparable<E>.
import java.util.*; public class SacOrdonneAObjetsUniquesTest extends junit.framework.TestCase{ public void testAjouter(){ CollectionI<Integer> sac = new SacOrdonneAObjetsUniques<Integer>(); assertTrue(sac.ajouter(3)); assertEquals(1,sac.taille()); assertTrue(sac.contient(3)); assertTrue(sac.ajouter(2)); assertEquals(2,sac.taille()); assertFalse(sac.ajouter(3)); assertEquals(2,sac.taille()); assertFalse(sac.ajouter(2)); assertEquals(2,sac.taille()); assertTrue("sac non ordonné ???", isSorted(sac)); } public void testAjouterCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(2);sacA.ajouter(2);sacA.ajouter(1);sacA.ajouter(1); assertEquals(6, sacA.taille()); CollectionI<Integer> sacB = new SacOrdonneAObjetsUniques<Integer>(); sacB.ajouter(4);sacB.ajouter(sacA); assertEquals(4, sacB.taille()); assertTrue(sacB.contient(3)); assertTrue(sacB.contient(2)); assertTrue(sacB.contient(1)); assertTrue(sacB.contient(4)); assertTrue("sac non ordonné ???", isSorted(sacB)); } public void testSupprimerCollection(){ CollectionI<Integer> sacA = new Sac<Integer>(); sacA.ajouter(3);sacA.ajouter(2);sacA.ajouter(1); CollectionI<Integer> sacB = new SacOrdonneAObjetsUniques<Integer>(); sacB.ajouter(2);sacB.ajouter(4);sacB.ajouter(4);sacB.ajouter(3); assertTrue(sacB.supprimer(sacA)); assertEquals(1, sacB.taille()); assertTrue(sacB.contient(4)); assertTrue("sac non ordonné ???", isSorted(sacB)); CollectionI<Integer> sacC = new SacOrdonneAObjetsUniques<Integer>(); sacC.ajouter(sacA); assertTrue("sac non ordonné ???", isSorted(sacC)); } private static class A{} private static class B implements Comparable<B>{ public int compareTo(B b){ return 0;} } public void testException(){ CollectionI<A> sacA = new SacOrdonneAObjetsUniques<A>(); try{ sacA.ajouter(new A()); }catch(Exception e){ assertTrue(e instanceof RuntimeException); } CollectionI<B> sacB = new SacOrdonneAObjetsUniques<B>(); try{ sacB.ajouter(new B()); }catch(Exception e){ fail(" pas d'exception attendue ici ..."); } } // http://stackoverflow.com/questions/3047051/how-to-determine-if-a-list-is-sorted-in-java public static <T extends Comparable<? super T>> boolean isSorted(Iterable<T> iterable) { Iterator<T> iter = iterable.iterator(); if (!iter.hasNext()) { return true; } T t = iter.next(); while (iter.hasNext()) { T t2 = iter.next(); if (t.compareTo(t2) > 0) { return false; } t = t2; } return true; } }
QUESTION5: Substituer la déclaration de la classe SacsOrdonneAObjetsUniques à la question 4 par la déclaration ci-dessous, modifier votre classe SacsOrdonneAObjetsUniques et la classe de tests, en conséquence.
public class SacOrdonneAObjetsUniques<E extends Comparable<E>> extends SacAObjetsUniques<E>{
QUESTION6: Proposez selon le patron Factory Method, une sous classe dans laquelle la création d'un sac est laissé à la responsabilité d'une de ses sous-classes, modifier le test ci dessous en faisant appel à votre fabrique
public interface Fabrique<T>{ public CollectionI<T> fabriquerUneCollection(); }
public class FabriqueDeSacTest extends junit.framework.TestCase{ public void testUneFabriqueAjouter(){ Fabrique<Integer> f = new FabriqueDeSacs<Integer>(); CollectionI<Integer> sac = f.fabriquerUneCollection(); assertTrue(sac.ajouter(3)); assertEquals(1,sac.taille()); assertTrue(sac.contient(3)); assertTrue(sac.ajouter(2)); assertEquals(2,sac.taille()); assertTrue(sac.ajouter(3)); assertEquals(3,sac.taille()); assertTrue(sac.ajouter(2)); assertEquals(4,sac.taille()); } }
Post-liminaire :
Préparation du tp5, exécution et tests de l'applette de l'énoncéconsole> appletviewer http://jfod.cnam.fr/progAvancee/tp5/tp5.html
avec si nécessaire sous windows set PATH=D:\BlueJ-315\jdk\bin;%PATH%Depuis votre navigateur http://jfod.cnam.fr/progAvancee/tp5/tp5.html
Ci-dessous les opérations sur les ensembles dont les images viennent de wikipedia
La réunion de deux ensembles : A ∪ B |
L'intersection de deux ensembles : A ∩ B. |
La différence : A - B. |
La différence symétrique |
/* Une idée...