t
t
t
t
t t 9) Stockage des objets
tttt
9) Stockage des objets
Texte original t Traducteur : Jérome QUELIN
t
t
///
Ce chapitre contient 14 pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14
\\\
t t t
t t t
t
t t t
In basicTest( ) and iterMotion( ) the calls are simply made to show the proper syntax, and while the return value is captured, it is not used. In some cases, the return value isn’t captured since it isn’t typically used. You should look up the full usage of each of these methods in the online documentation from java.sun.com before you use them. t basicTest() et iterMotion() sont des procédures qui n'ont d'autre but que celui de montrer la syntaxe d'appel  des méthodes dont la valeur de retour n'est pas utilisée bien que récupérée. Dans certains cas, la valeur de retour des méthodes n'est même pas récupérée car jamais utilisée même dans un programme réel. Se référer à la documentation online de java.sun.com pour un examen approfondi de l'utilisation de chacune de ces méthodes.
t t t

Making a stack from a LinkedList

t

Réaliser une pile à partir d'une LinkedList

t t t
A stack is sometimes referred to as a “last-in, first-out” (LIFO) container. That is, whatever you “push” on the stack last is the first item you can “pop” out. Like all of the other containers in Java, what you push and pop are Objects, so you must cast what you pop, unless you’re just using Object behavior. t Une pile est un conteneur « dernier arrivé, premier sorti » (LIFO - « Last In, First Out »). C'est à dire que l'objet qu'on « pousse » (« push »)sur la pile en dernier sera le premier accessible lors d'une extraction (« pop »). Comme tous les autres conteneurs de Java, on stocke et récupère des Objects, qu'il faudra donc retranstyper après leur extraction, à moins qu'on ne se contente des fonctionnalités de la classe Object.
t t t
The LinkedList has methods that directly implement stack functionality, so you can also just use a LinkedList rather than making a stack class. However, a stack class can sometimes tell the story better: t La classe LinkedList possède des méthodes qui implémentent directement les fonctionnalités d'une pile, on peut donc utiliser directement une LinkedList plutôt que de créer une classe implémentant une pile. Cependant une classe est souvent plus explicite :
t t t
//: c09:StackL.java
// Making a stack from a LinkedList.
import java.util.*;
import com.bruceeckel.util.*;

public class StackL {
  private LinkedList list = new LinkedList();
  public void push(Object v) {
    list.addFirst(v);
  }
  public Object top() { return list.getFirst(); }
  public Object pop() {
    return list.removeFirst();
  }
  public static void main(String[] args) {
    StackL stack = new StackL();
    for(int i = 0; i < 10; i++)
      stack.push(Collections2.countries.next());
    System.out.println(stack.top());
    System.out.println(stack.top());
    System.out.println(stack.pop());
    System.out.println(stack.pop());
    System.out.println(stack.pop());
  }
} ///:~
t
//: c09:StackL.java
// Réaliser une pile à partir d'une LinkedList.
import java.util.*;
import com.bruceeckel.util.*;

public class StackL {
  private LinkedList list = new LinkedList();
  public void push(Object v) {
    list.addFirst(v);
  }
  public Object top() { return list.getFirst(); }
  public Object pop() {
    return list.removeFirst();
  }
  public static void main(String[] args) {
    StackL stack = new StackL();
    for(int i = 0; i < 10; i++)
      stack.push(Collections2.countries.next());
    System.out.println(stack.top());
    System.out.println(stack.top());
    System.out.println(stack.pop());
    System.out.println(stack.pop());
    System.out.println(stack.pop());
  }
} ///:~
t t t
If you want only stack behavior, inheritance is inappropriate here because it would produce a class with all the rest of the LinkedList methods (you’ll see later that this very mistake was made by the Java 1.0 library designers with Stack). t L'héritage n'est pas approprié ici puisqu'il produirait une classe contenant toutes les méthodes d'une LinkedList (on verra que cette erreur a déjà été faite par les concepteurs de la bibliothèque Java 1.0 avec la classe Stack).
t t t

Making a queue from a LinkedList

t

Réaliser une file à partir d'une LinkedList

t t t
A queue is a “first-in, first-out” (FIFO) container. That is, you put things in at one end, and pull them out at the other. So the order in which you put them in will be the same order that they come out. LinkedList has methods to support queue behavior, so these can be used in a Queue class: t Une file (ou queue) est un conteneur « premier arrivé, premier sorti » (FIFO - « First In, First Out »). C'est à dire qu'on « pousse » des objets à une extrémité et qu'on les en retire à l'autre extrémité. L'ordre dans lequel on pousse les objets sera donc le même que l'ordre dans lequel on les récupérera. La classe LinkedList possède des méthodes qui implémentent directement les fonctionnalités d'une file, on peut donc les utiliser directement dans une classe Queue :
t t t
//: c09:Queue.java
// Making a queue from a LinkedList.
import java.util.*;

public class Queue {
  private LinkedList list = new LinkedList();
  public void put(Object v) { list.addFirst(v); }
  public Object get() {
    return list.removeLast();
  }
  public boolean isEmpty() {
    return list.isEmpty();
  }
  public static void main(String[] args) {
    Queue queue = new Queue();
    for(int i = 0; i < 10; i++)
      queue.put(Integer.toString(i));
    while(!queue.isEmpty())
      System.out.println(queue.get());
  }
} ///:~
t
//: c09:Queue.java
// Réaliser une file à partir d'une LinkedList.
import java.util.*;

public class Queue {
  private LinkedList list = new LinkedList();
  public void put(Object v) { list.addFirst(v); }
  public Object get() {
    return list.removeLast();
  }
  public boolean isEmpty() {
    return list.isEmpty();
  }
  public static void main(String[] args) {
    Queue queue = new Queue();
    for(int i = 0; i < 10; i++)
      queue.put(Integer.toString(i));
    while(!queue.isEmpty())
      System.out.println(queue.get());
  }
} ///:~
t t t
You can also easily create a deque (double-ended queue) from a LinkedList. This is like a queue, but you can add and remove elements from either end. t Il est aussi facile de créer une file double (queue à double entrée) à partir d'une LinkedList. Une file double est une file à laquelle on peut ajouter et supprimer des éléments à chacune de ses extrémités.
t t t

Set functionality

t

Fonctionnalités des Sets

t t t
Set has exactly the same interface as Collection, so there isn’t any extra functionality like there is with the two different Lists. Instead, the Set is exactly a Collection, it just has different behavior. (This is the ideal use of inheritance and polymorphism: to express different behavior.) A Set refuses to hold more than one instance of each object value (what constitutes the “value” of an object is more complex, as you shall see). t Les Sets ont exactement la même interface que les Collections, et à l'inverse des deux différentes Lists, ils ne proposent aucune fonctionnalité supplémentaire. Les Sets sont donc juste une Collection ayant un comportement particulier (implémenter un comportement différent constitue l'exemple type où il faut utiliser l'héritage et le polymorphisme). Un Set refuse de contenir plus d'une instance de chaque valeur d'un objet (savoir ce qu'est la « valeur » d'un objet est plus compliqué, comme nous allons le voir).
t t t
Set (interface) Each element that you add to the Set must be unique; otherwise the Set doesn’t add the duplicate element. Objects added to a Set must define equals( ) to establish object uniqueness. Set has exactly the same interface as Collection. The Set interface does not guarantee it will maintain its elements in any particular order.
HashSet* For Sets where fast lookup time is important. Objects must also define hashCode( ).
TreeSet An ordered Set backed by a tree. This way, you can extract an ordered sequence from a Set.
t
Set (interface) Chaque élément ajouté au Set doit être unique ; sinon le Set n'ajoutera pas le doublon. Les Objects ajoutés à un Set doivent définir la méthode equals() pour pouvoir établir l'unicité de l'objet. Un Set possède la même interface qu'une Collection. L'interface Set ne garantit pas qu'il maintiendra les éléments dans un ordre particulier.
HashSet* Pour les Sets où le temps d'accès aux éléments est primordial. Les Objects doivent définir la méthode hashCode().
TreeSet Un Set trié stocké dans un arbre. De cette manière, on peut extraire une séquence triée à partir du Set.
t t t
The following example does not show everything you can do with a Set, since the interface is the same as Collection, and so was exercised in the previous example. Instead, this demonstrates the behavior that makes a Set unique: t L'exemple suivant ne montre pas tout ce qu'il est possible de faire avec un Set, puisque l'interface est la même que pour les Collections, et comme telle a déjà été testée dans l'exemple précédent. Par contre, il illustre les comportements qui rendent un Set particulier :
t t t
//: c09:Set1.java
// Things you can do with Sets.
import java.util.*;
import com.bruceeckel.util.*;

public class Set1 {
  static Collections2.StringGenerator gen =
    Collections2.countries;
  public static void testVisual(Set a) {
    Collections2.fill(a, gen.reset(), 10);    
    Collections2.fill(a, gen.reset(), 10);    
    Collections2.fill(a, gen.reset(), 10);    
    System.out.println(a); // No duplicates!
    // Add another set to this one:
    a.addAll(a);
    a.add("one");
    a.add("one");
    a.add("one");
    System.out.println(a);
    // Look something up:
    System.out.println("a.contains(\"one\"): " +
      a.contains("one"));
  }
  public static void main(String[] args) {
    System.out.println("HashSet");
    testVisual(new HashSet());
    System.out.println("TreeSet");
    testVisual(new TreeSet());
  }
} ///:~
t
//: c09:Set1.java
// Opérations disponibles pour les Sets.
import java.util.*;
import com.bruceeckel.util.*;

public class Set1 {
  static Collections2.StringGenerator gen =
    Collections2.countries;
  public static void testVisual(Set a) {
    Collections2.fill(a, gen.reset(), 10);    
    Collections2.fill(a, gen.reset(), 10);    
    Collections2.fill(a, gen.reset(), 10);    
    System.out.println(a); // Pas de doublons !
    // Ajoute un autre ensemble à celui-ci :
    a.addAll(a);
    a.add("one");
    a.add("one");
    a.add("one");
    System.out.println(a);
    // Extraction d'item :
    System.out.println("a.contains(\"one\"): " +
      a.contains("one"));
  }
  public static void main(String[] args) {
    System.out.println("HashSet");
    testVisual(new HashSet());
    System.out.println("TreeSet");
    testVisual(new TreeSet());
  }
} ///:~
t t t
Duplicate values are added to the Set, but when it is printed you’ll see the Set has accepted only one instance of each value. t Cet exemple tente d'ajouter des valeurs dupliquées au Set, mais lorsqu'on l'imprime on voit que le Set n'accepte qu'une instance de chaque valeur.
t t t
When you run this program you’ll notice that the order maintained by the HashSet is different from TreeSet, since each has a different way of storing elements so they can be located later. (TreeSet keeps them sorted, while HashSet uses a hashing function, which is designed specifically for rapid lookups.) When creating your own types, be aware that a Set needs a way to maintain a storage order, which means you must implement the Comparable interface and define the compareTo( ) method. Here’s an example: t Lorsqu'on lance ce programme, on voit que l'ordre interne maintenu par le HashSet est différent de celui de TreeSet, puisque chacune de ces implémentations stocke les éléments d'une manière différente (TreeSet garde les éléments triés, tandis que HashSet utilise une fonction de hachage, conçue spécialement pour des accès optimisés). Quand on crée un nouveau type, il faut bien se rappeler qu'un Set a besoin de maintenir un ordre de stockage, ce qui veut dire qu'il faut implémenter l'interface Comparable et définir la méthode compareTo(). Voici un exemple :
t t t
//: c09:Set2.java
// Putting your own type in a Set.
import java.util.*;

class MyType implements Comparable {
  private int i;
  public MyType(int n) { i = n; }
  public boolean equals(Object o) {
    return
      (o instanceof MyType)
      && (i == ((MyType)o).i);
  }
  public int hashCode() { return i; }
  public String toString() { return i + " "; }
  public int compareTo(Object o) {
    int i2 = ((MyType)o).i;
    return (i2 < i ? -1 : (i2 == i ? 0 : 1));
  }
}

public class Set2 {
  public static Set fill(Set a, int size) {
    for(int i = 0; i < size; i++)
      a.add(new MyType(i));
    return a;
  }
  public static void test(Set a) {
    fill(a, 10);
    fill(a, 10); // Try to add duplicates
    fill(a, 10);
    a.addAll(fill(new TreeSet(), 10));
    System.out.println(a);
  }
  public static void main(String[] args) {
    test(new HashSet());
    test(new TreeSet());
  }
} ///:~
t
//: c09:Set2.java
// Ajout d'un type particulier dans un Set.
import java.util.*;

class MyType implements Comparable {
  private int i;
  public MyType(int n) { i = n; }
  public boolean equals(Object o) {
    return
      (o instanceof MyType)
      && (i == ((MyType)o).i);
  }
  public int hashCode() { return i; }
  public String toString() { return i + " "; }
  public int compareTo(Object o) {
    int i2 = ((MyType)o).i;
    return (i2 < i ? -1 : (i2 == i ? 0 : 1));
  }
}

public class Set2 {
  public static Set fill(Set a, int size) {
    for(int i = 0; i < size; i++)
      a.add(new MyType(i));
    return a;
  }
  public static void test(Set a) {
    fill(a, 10);
    fill(a, 10); // Tente de créer des doublons
    fill(a, 10);
    a.addAll(fill(new TreeSet(), 10));
    System.out.println(a);
  }
  public static void main(String[] args) {
    test(new HashSet());
    test(new TreeSet());
  }
} ///:~
t t t
The form for the definitions for equals( ) and hashCode( ) will be described later in this chapter. You must define an equals( ) in both cases, but the hashCode( ) is absolutely necessary only if the class will be placed in a HashSet (which is likely, since that should generally be your first choice as a Set implementation). However, as a programming style you should always override hashCode( ) when you override equals( ). This process will be fully detailed later in this chapter. t La forme que doivent avoir les définitions des méthodes equals() et hashCode() sera décrite plus tard dans ce chapitre. Il faut définir une méthode equals() pour les deux implémentations de Set, mais hashCode() n'est nécessaire que si la classe est placée dans un hashSet (ce qui est probable, puisqu'il s'agit de l'implémentation recommandée pour un Set). Cependant, c'est une bonne pratique de programmation de redéfinir hashCode() lorsqu'on redéfinit equals(). Ce processus sera examiné en détails plus loin dans ce chapitre.
t t t
In the compareTo( ), note that I did not use the “simple and obvious” form return i-i2. Although this is a common programming error, it would only work properly if i and i2 were “unsigned” ints (if Java had an “unsigned” keyword, which it does not). It breaks for Java’s signed int, which is not big enough to represent the difference of two signed ints. If i is a large positive integer and j is a large negative integer, i-j will overflow and return a negative value, which will not work. t Notez que je n'ai pas utilisé la forme « simple et évidente » return i-i2 dans la méthode compareTo(). Bien que ce soit une erreur de programmation classique, elle ne fonctionne que si i et i2 sont des ints « non signés » (si Java disposait d'un mot-clef « unsigned », ce qu'il n'a pas). Elle ne marche pas pour les ints signés de Java, qui ne sont pas assez grands pour représenter la différence de deux ints signés. Si i est un grand entier positif et j un grand entier négatif, i-j débordera et renverra une valeur négative, ce qui n'est pas le résultat attendu.
t t t

SortedSet

t

Sets triés : les SortedSets

t t t
If you have a SortedSet (of which TreeSet is the only one available), the elements are guaranteed to be in sorted order which allows additional functionality to be provided with these methods in the SortedSet interface: t Un SortedSet (dont TreeSet est l'unique représentant) garantit que ses éléments seront stockés triés, ce qui permet de proposer de nouvelles fonctionnalités grâce aux méthodes supplémentaires de l'interface SortedSet suivantes :
t t t
Comparator comparator(): Produces the Comparator used for this Set, or null for natural ordering. t Comparator comparator() : Renvoie le Comparator utilisé pour ce Set, ou null dans le cas d'un tri naturel.
t t t
Object first(): Produces the lowest element. t Object first() : Renvoie le plus petit élément.
t t t
Object last(): Produces the highest element. t Object last() : Renvoie le plus grand élément.
t t t
SortedSet subSet(fromElement, toElement): Produces a view of this Set with elements from fromElement, inclusive, to toElement, exclusive. t SortedSet subSet(fromElement, toElement) : Renvoie une vue du Set contenant les éléments allant de fromElement inclus à toElement exclu.
t t t
SortedSet headSet(toElement): Produces a view of this Set with elements less than toElement. t SortedSet headSet(toElement) : Renvoie une vue du Set contenant les éléments inférieurs à toElement.
t t t
SortedSet tailSet(fromElement): Produces a view of this Set with elements greater than or equal to fromElement. t SortedSet tailSet(fromElement): Renvoie une vue du Set contenant les éléments supérieurs ou égaux à fromElement.
t t t

Map functionality

t

Fonctionnalités des Maps

t t t
An ArrayList allows you to select from a sequence of objects using a number, so in a sense it associates numbers to objects. But what if you’d like to select from a sequence of objects using some other criterion? A stack is an example: its selection criterion is “the last thing pushed on the stack.” A powerful twist on this idea of “selecting from a sequence” is alternately termed a map, a dictionary, or an associative array. Conceptually, it seems like an ArrayList, but instead of looking up objects using a number, you look them up using another object! This is often a key process in a program. t Une ArrayList permet de sélectionner des éléments dans une séquence d'objets en utilisant un nombre, elle associe donc des nombres à des objets. Mais qu'en est-il si on souhaite sélectionner des éléments d'une séquence en utilisant un autre critère ? Dans l'exemple d'une pile, son critère de sélection est « le dernier objet poussé sur la pile ». Un tableau associatif, ou map, ou dictionnaire est une alternative particulièrement puissante de cette idée de « sélection dans une séquence ». Conceptuellement, cela ressemble à une ArrayList, mais au lieu de sélectionner un objet par un nombre, on le sélectionne en utilisant un autre objet ! Ce fonctionnement est d'une valeur inestimable dans un programme.
t t t
The concept shows up in Java as the Map interface. The put(Object key, Object value) method adds a value (the thing you want), and associates it with a key (the thing you look it up with). get(Object key) produces the value given the corresponding key. You can also test a Map to see if it contains a key or a value with containsKey( ) and containsValue( ). t Le concept est illustré dans Java via l'interface Map. La méthode put(Object key, Object value) ajoute une valeur (la chose qu'on veut stocker), et l'associe à une clef (la chose grâce à laquelle on va retrouver la valeur). La méthode get(Object key) renvoie la valeur associée à la clef correspondante. Il est aussi possible de tester une Map pour voir si elle contient une certaine clef ou une certaine valeur avec les méthodes containsKey() et containsValue().
t t t
The standard Java library contains two different types of Maps: HashMap and TreeMap. Both have the same interface (since they both implement Map), but they differ in one distinct way: efficiency. If you look at what must be done for a get( ), it seems pretty slow to search through (for example) an ArrayList for the key. This is where HashMap speeds things up. Instead of a slow search for the key, it uses a special value called a hash code. The hash code is a way to take some information in the object in question and turn it into a “relatively unique” int for that object. All Java objects can produce a hash code, and hashCode( ) is a method in the root class Object. A HashMap takes the hashCode( ) of the object and uses it to quickly hunt for the key. This results in a dramatic performance improvement[50]. t La bibliothèque Java standard propose deux types de Maps : HashMap et TreeMap. Les deux implémentations ont la même interface (puisqu'elles implémentent toutes les deux Map), mais diffèrent sur un point particulier : les performances. Dans le cas d'un appel à  get(), il est peu efficace de chercher dans une ArrayList (par exemple) pour trouver une clef. C'est là que le HashMap intervient. Au lieu d'effectuer une recherche lente sur la clef, il utilise une valeur spéciale appelée code de hachage (hash code). Le code de hachage est une façon d'extraire une partie de l'information de l'objet en question et de la convertir en un int « relativement unique ». Tous les objets Java peuvent produire un code de hachage, et hashCode() est une méthode de la classe racine Object. Un HashMap récupère le hashCode() de l'objet et l'utilise pour retrouver rapidement la clef. Le résultat en est une augmentation drastique des performances  [50].  
t t t
Map (interface) Maintains key-value associations (pairs), so you can look up a value using a key.
HashMap* Implementation based on a hash table. (Use this instead of Hashtable.) Provides constant-time performance for inserting and locating pairs. Performance can be adjusted via constructors that allow you to set the capacity and load factor of the hash table.
TreeMap Implementation based on a red-black tree. When you view the keys or the pairs, they will be in sorted order (determined by Comparable or Comparator, discussed later). The point of a TreeMap is that you get the results in sorted order. TreeMap is the only Map with the subMap( ) method, which allows you to return a portion of the tree.
t
Map (interface) Maintient des associations clef - valeur (des paires), afin de pouvoir accéder à une valeur en utilisant une clef.
HashMap* Implémentation basée sur une table de hachage (utilisez ceci à la place d'une Hashtable). Fournit des performances constantes pour l'insertion et l'extraction de paires. Les performances peuvent être ajustées via des constructeurs qui permettent de positionner la capacité et le facteur de charge de la table de hachage.
TreeMap Implémentation basée sur un arbre rouge-noir. L'extraction des clefs ou des paires fournit une séquence triée (selon l'ordre spécifié par Comparable ou Comparator, comme nous le verrons plus loin). Le point important dans un TreeMap est qu'on récupère les résultats dans l'ordre. TreeMap est la seule Map disposant de la méthode subMap(), qui permet de renvoyer une portion de  l'arbre.
t t t
Sometimes you’ll also need to know the details of how hashing works, so we’ll look at that a little later. The following example uses the Collections2.fill( ) method and the test data sets that were previously defined: t Nous nous pencherons sur les mécanismes de hachage un peu plus loin. L'exemple suivant utilise la méthode Collections2.fill() et les ensembles de données définis précédemment :
t t t
//: c09:Map1.java
// Things you can do with Maps.
import java.util.*;
import com.bruceeckel.util.*;

public class Map1 {
  static Collections2.StringPairGenerator geo =
    Collections2.geography;
  static Collections2.RandStringPairGenerator
    rsp = Collections2.rsp;
  // Producing a Set of the keys:
  public static void printKeys(Map m) {
    System.out.print("Size = " + m.size() +", ");
    System.out.print("Keys: ");
    System.out.println(m.keySet());
  }
  // Producing a Collection of the values:
  public static void printValues(Map m) {
    System.out.print("Values: ");
    System.out.println(m.values());
  }
  public static void test(Map m) {
    Collections2.fill(m, geo, 25);
    // Map has 'Set' behavior for keys:
    Collections2.fill(m, geo.reset(), 25);
    printKeys(m);
    printValues(m);
    System.out.println(m);
    String key = CountryCapitals.pairs[4][0];
    String value = CountryCapitals.pairs[4][1];
    System.out.println("m.containsKey(\"" + key +
      "\"): " + m.containsKey(key));
    System.out.println("m.get(\"" + key + "\"): "
      + m.get(key));
    System.out.println("m.containsValue(\""
      + value + "\"): " +
      m.containsValue(value));
    Map m2 = new TreeMap();
    Collections2.fill(m2, rsp, 25);
    m.putAll(m2);
    printKeys(m);
    key = m.keySet().iterator().next().toString();
    System.out.println("First key in map: "+key);
    m.remove(key);
    printKeys(m);
    m.clear();
    System.out.println("m.isEmpty(): "
      + m.isEmpty());
    Collections2.fill(m, geo.reset(), 25);
    // Operations on the Set change the Map:
    m.keySet().removeAll(m.keySet());
    System.out.println("m.isEmpty(): "
      + m.isEmpty());
  }
  public static void main(String[] args) {
    System.out.println("Testing HashMap");
    test(new HashMap());
    System.out.println("Testing TreeMap");
    test(new TreeMap());
  }
} ///:~
t
//: c09:Map1.java
// Opérations disponibles pour les Maps.
import java.util.*;
import com.bruceeckel.util.*;

public class Map1 {
  static Collections2.StringPairGenerator geo =
    Collections2.geography;
  static Collections2.RandStringPairGenerator
    rsp = Collections2.rsp;
  // Produire un Set de clefs :
  public static void printKeys(Map m) {
    System.out.print("Size = " + m.size() +", ");
    System.out.print("Keys: ");
    System.out.println(m.keySet());
  }
  // Produire une Collection de valeurs :
  public static void printValues(Map m) {
    System.out.print("Values: ");
    System.out.println(m.values());
  }
  public static void test(Map m) {
    Collections2.fill(m, geo, 25);
    // Une Map a un comportement de « Set » pour les clefs :
    Collections2.fill(m, geo.reset(), 25);
    printKeys(m);
    printValues(m);
    System.out.println(m);
    String key = CountryCapitals.pairs[4][0];
    String value = CountryCapitals.pairs[4][1];
    System.out.println("m.containsKey(\"" + key +
      "\"): " + m.containsKey(key));
    System.out.println("m.get(\"" + key + "\"): "
      + m.get(key));
    System.out.println("m.containsValue(\""
      + value + "\"): " +
      m.containsValue(value));
    Map m2 = new TreeMap();
    Collections2.fill(m2, rsp, 25);
    m.putAll(m2);
    printKeys(m);
    key = m.keySet().iterator().next().toString();
    System.out.println("First key in map: "+key);
    m.remove(key);
    printKeys(m);
    m.clear();
    System.out.println("m.isEmpty(): "
      + m.isEmpty());
    Collections2.fill(m, geo.reset(), 25);
    // Les opérations sur le Set changent la Map :
    m.keySet().removeAll(m.keySet());
    System.out.println("m.isEmpty(): "
      + m.isEmpty());
  }
  public static void main(String[] args) {
    System.out.println("Testing HashMap");
    test(new HashMap());
    System.out.println("Testing TreeMap");
    test(new TreeMap());
  }
} ///:~
t t t
The printKeys( ) and printValues( ) methods are not only useful utilities, they also demonstrate how to produce Collection views of a Map. The keySet( ) method produces a Set backed by the keys in the Map. Similar treatment is given to values( ), which produces a Collection containing all the values in the Map. (Note that keys must be unique, while values may contain duplicates.) Since these Collections are backed by the Map, any changes in a Collection will be reflected in the associated Map. t Les méthodes printKeys() et printValues() ne sont pas seulement des utilitaires pratiques, elles illustrent aussi comment produire une vue (sous la forme d'une Collection) d'une Map. La méthode keySet() renvoie un Set rempli par les clefs de la Map. La méthode values() renvoie quant à elle une Collection contenant toutes les valeurs de la Map (notez bien que les clefs doivent être uniques, alors que les valeurs peuvent contenir des doublons). Ces Collections sont liées à la Map, tout changement effectué dans une Collection sera donc répercuté dans la Map associée.
t t t
The rest of the program provides simple examples of each Map operation, and tests each type of Map. t Le reste du programme fournit des exemples simples pour chacune des opérations disponibles pour une Map, et teste les deux types de Maps.
t t t
As an example of the use of a HashMap, consider a program to check the randomness of Java’s Math.random( ) method. Ideally, it would produce a perfect distribution of random numbers, but to test this you need to generate a bunch of random numbers and count the ones that fall in the various ranges. A HashMap is perfect for this, since it associates objects with objects (in this case, the value object contains the number produced by Math.random( ) along with the number of times that number appears): t Comme exemple d'utilisation d'un HashMap, considérons un programme vérifiant la nature aléatoire de la méthode Math.random() de Java. Idéalement, elle devrait produire une distribution parfaite de nombres aléatoires, mais pour tester cela il faut générer un ensemble de nombres aléatoires et compter ceux qui tombent dans les différentes plages. Un HashMap est parfait pour ce genre d'opérations, puisqu'il associe des objets à d'autres objets (dans ce cas, les objets valeurs contiennent le nombre produit par Math.random() ainsi que le nombre de fois où ce nombre apparaît) :
t t t
//: c09:Statistics.java
// Simple demonstration of HashMap.
import java.util.*;

class Counter {
  int i = 1;
  public String toString() {
    return Integer.toString(i);
  }
}

class Statistics {
  public static void main(String[] args) {
    HashMap hm = new HashMap();
    for(int i = 0; i < 10000; i++) {
      // Produce a number between 0 and 20:
      Integer r =
        new Integer((int)(Math.random() * 20));
      if(hm.containsKey(r))
        ((Counter)hm.get(r)).i++;
      else
        hm.put(r, new Counter());
    }
    System.out.println(hm);
  }
} ///:~
t
//: c09:Statistics.java
// Simple démonstration de l'utilisation d'un HashMap.
import java.util.*;

class Counter {
  int i = 1;
  public String toString() {
    return Integer.toString(i);
  }
}

class Statistics {
  public static void main(String[] args) {
    HashMap hm = new HashMap();
    for(int i = 0; i < 10000; i++) {
      // Produit un nombre entre 0 et 20 :
      Integer r =
        new Integer((int)(Math.random() * 20));
      if(hm.containsKey(r))
        ((Counter)hm.get(r)).i++;
      else
        hm.put(r, new Counter());
    }
    System.out.println(hm);
  }
} ///:~
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel