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 : AB

L'intersection de deux ensembles : AB.

La différence : A - B.

La différence symétrique
A Δ B = (AB ) - (AB).


/* Une idée...