pdf - e-book - archive - github.com

1.15  Collections

1.15.1  Types paramétrés

Déclaration

On crée une classe paramétrée en plaçant le type inconnu (dans l’exemple ci-dessous : T) entre chevrons à côté du nom de la classe.

package collections.exemples;

public class ClasseParametree<T>
{
 private T data;

 public ClasseParametree(T data)
 {
  this.data = data;
 }

 public T get()
 {
  return data;
 }

 public void set(T data)
 {
  this.data = data;
 }

 public static void main(String[] args)
 {
  ClasseParametree<String> conteneurString = new ClasseParametree<>(
    "toto");
  String chaine = conteneurString.get();
  System.out.println(chaine);

  ClasseParametree<Integer> conteneurInt = new ClasseParametree<>(5);
  int entier = conteneurInt.get();
  System.out.println(entier);
 }
}

Télécharger le fichier

On peut voir une classe paramétrée comme un moule à classes.

Héritage entre classes paramétrées

On est amené naturellement à se demander si ClasseParametree<String> hérite de ClasseParametree<Object>. Un exercice traite cette question...

Java Vs C++

Le mécanisme des classes paramétrées en Java en bien plus fin que les templates utilisées en C++. Les templates ne sont que de vulgaires rechercher/remplacer, alors qu’en Java, le code compilé est le même que si les types ne sont pas paramétrés. Les types paramétrés de java ne sont donc qu’un moyen pour le compilateur de s’assurer que vous faites les choses proprement en vous obligeant à déclarer les types que vous placez dans les collections.

1.15.2  Paramètres et héritage

Paramètre sur la classe mère

Il est possible depuis une classe non paramétrée d’hériter d’une classe paramétrée en précisant son type :

package collections.exemples;

public class StringWrapper implements Comparable<StringWrapper>
{
 private String data;

 public StringWrapper(String data)
 {
  this.data = data;
 }

 public String getData()
 {
  return data;
 }

 public void setData(String data)
 {
  this.data = data;
 }

 @Override
 public int compareTo(StringWrapper autre)
 {
  return data.compareTo(autre.getData());
 }

 public static void main(String[] args)
 {
  StringWrapper e1 = new StringWrapper("toto"), 
    e2 = new StringWrapper("tutu");
  System.out.println(e1.compareTo(e2));
 }
}

Télécharger le fichier

Contraintes sur le paramètre

Il est souvent nécessaire que le type servant de paramètre vérifie certaines propriétés. Si vous souhaitez par exemple que l’objet hérite de Comparable, vous avez la possibilité de poser cette contrainte avec le paramètre <T extends Comparable<T>>.

package collections.exemples;

public class ComparableWrapper<T extends Comparable<T>> 
 implements Comparable<ComparableWrapper<T>>
{
 private T data;

 public ComparableWrapper(T data)
 {
  this.data = data;
 }

 public T getData()
 {
  return data;
 }

 public void setData(T data)
 {
  this.data = data;
 }

 @Override
 public int compareTo(ComparableWrapper<T> autre)
 {
  return data.compareTo(autre.getData());
 }

 public static void main(String[] args)
 {
  ComparableWrapper<String> e1 = new ComparableWrapper<>("toto"), 
    e2 = new ComparableWrapper<>("tutu");
  System.out.println(e1.compareTo(e2));
  ComparableWrapper<Integer> i1 = new ComparableWrapper<>(4), 
    i2 = new ComparableWrapper<>(3);
  System.out.println(i1.compareTo(i2));
 }
}

Télécharger le fichier

1.15.3  Collections standard

La distribution officielle de Java est fournie avec plusieurs milliers de classes. Les Collections sont des structures de données permettant d’optimiser des opérations comme le tri, la recherche de plus petit élément, etc. Les collections sont donc des regroupements d’objets.

Set<T>

Un ensemble ( Set<T>) est un regroupement d’éléments de type T, non ordonnés et sans doublons.

package collections.exemples;

import java.util.HashSet;
import java.util.Set;

public class SetInscriptions
{
 public static void main(String[] args)
 {
  Set<String> inscrits = new HashSet<>();
  inscrits.add("Lucien");
  inscrits.add("Raymond");
  inscrits.add("Huguette");
  System.out.println(inscrits.contains("Gégé"));
  System.out.println(inscrits.contains("Raymond"));
  for (String nom : inscrits)
   System.out.println(nom);
 }
}

Télécharger le fichier

SortedSet<T>

package collections.exemples;

import java.util.SortedSet;
import java.util.TreeSet;

class Coordonnees implements Comparable<Coordonnees>
{
 private int x, y;

 public Coordonnees(int x, int y)
 {
  this.x = x;
  this.y = y;
 }

 @Override
 public String toString()
 {
  return x + " " + y;
 }

 @Override
 public int compareTo(Coordonnees autre)
 {
  if (x == autre.x)
   return y - autre.y;
  return x - autre.x;
 }
}

public class SortedSetCoordonnees
{
 public static void main(String[] args)
 {
  SortedSet<Coordonnees> cases = new TreeSet<>();
  cases.add(new Coordonnees(1, 6));
  cases.add(new Coordonnees(7, 3));
  cases.add(new Coordonnees(-2, 5));
  cases.add(new Coordonnees(1, 5));
  for (Coordonnees c : cases)
   System.out.println(c);
 }
}

Télécharger le fichier

package collections.exemples;

import java.util.SortedSet;
import java.util.TreeSet;

public class SortedSetComparator
{
 public static void main(String[] args)
 {
  SortedSet<String> dico = new TreeSet<>
  (
     (str1, str2) -> str1.length() - str2.length()
  );
  // ou bien
  /*
  SortedSet<String> dico = new TreeSet<>(new Comparator<String>()  
  {
   @Override
   public int compare(String str1, String str2)
   {
    return str1.length() - str2.length();
   }   
  });
  */ 
  dico.add("xyz");
  dico.add("abcde");
  dico.add("mp");
  dico.add("gfeadcba");
  for (String s : dico)
   System.out.println(s);

 }
}

Télécharger le fichier

Lists<T>

Une liste ( List<T>) est un ensemble d’éléments de type T, disposés dans l’ordre dans lequel ils ont été insérés, et contenant éventuellement des doublons.

package collections.exemples;

import java.util.LinkedList;
import java.util.List;

public class ListPalmares
{
 public static void main(String[] args)
 {
  List<String> palmares = new LinkedList<>();
  palmares.add("Ginette");
  palmares.add("Gertrude");
  palmares.add("Maurice");
  for (String nom : palmares)
   System.out.println(nom);
 }
}

Télécharger le fichier

Maps<T>

Une application, ( Map<K, T>) permet d’associer à des clés de type K des objets de type T.

package collections.exemples;

import java.util.HashMap;
import java.util.Map;

public class HashMapSalaires
{
 public static void main(String[] args)
 {
  Map<String, Integer> salaires = new HashMap<>();
  salaires.put("Raymond", 1000);
  salaires.put("Marcel", 2000);
  salaires.put("Ursule", 3000);
  for(String nom : salaires.keySet())
   System.out.println("Le salaire de " + nom + " est " 
    + salaires.get(nom) + " euros.");
 }
}

Télécharger le fichier

package collections.exemples;

import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

public class SortedMapSalaires
{
 public static void main(String[] args)
 {
  SortedMap<String, Integer> salaires = new TreeMap<>();
  salaires.put("Dédé", 5000);
  salaires.put("Marcel", 2000);
  salaires.put("Ginette", 3000);
  salaires.put("Lucienne", 1000);
  for (String e : salaires.keySet())
   System.out.println(e);
  for (int e : salaires.values())
   System.out.println(e);
  for (Entry<String, Integer> e : salaires.entrySet())
   System.out.println("Le salaire de " + e.getKey() + " est " + e.getValue());
 }
}

Télécharger le fichier

Iterable<T>

Il n’est possible d’utiliser la boucle for simplifiée que si collection parcourue implémente Iterable<T>.

Voici un exemple de collection itérable :

package collections.exemples;

import java.util.Iterator;

public class IterableArray implements Iterable<Integer>
{
 private final int TAILLE;
 private int[] tableau;

 public IterableArray(int taille)
 {
  this.TAILLE = taille;
  tableau = new int[taille];
 }

 public void set(int i, int data)
 {
  tableau[i] = data;
 }

 public int get(int i)
 {
  return tableau[i];
 }

 @Override
 public Iterator<Integer> iterator()
 {
  return new Iterator<Integer>()
  {
   private int index = -1;

   @Override
   public boolean hasNext()
   {
    index++;
    return index < TAILLE;
   }

   @Override
   public Integer next()
   {
    return get(index);
   }

   @Override
   public void remove()
   {
    for (int i = index; i < TAILLE - 1; i++)
     set(i, get(i + 1));
    set(TAILLE - 1, 0);
    index --;
   }
  };
 }

 public static void main(String[] args)
 {
  IterableArray tab = new IterableArray(10);
  for (int i = 0; i < 10; i++)
   tab.set(i, i + 1);
  
  Iterator<Integer> iterator = tab.iterator();
  while (iterator.hasNext()) 
  {
   int value = iterator.next();
   if (value % 2 != 0)
    iterator.remove();
  }  
  for (int value : tab)
   System.out.println(value);
 }
}

Télécharger le fichier