5. Interface SortedSet

5.1. Notion de SortedSet

L'interface SortedSet est une extension de l'interface Set. Cette interface impose de plus que tous les objets enregistrés dans cet ensemble sont automatiquement triés dans un ordre que nous allons préciser. L'itération sur les éléments d'un SortedSet se fait dans l'ordre croissant associés aux objets de cet ensemble. La comparaison de deux objets n'est pas définie au niveau de la classe Object. Il y a deux façons de faire pour comparer deux objets.
  • Implémenter l'interface Comparable. Cette interface expose une unique méthode : compareTo(T t), qui retourne un entier. Le fait que cet entier soit négatif ou positif nous dit si l'objet comparé est plus grand ou plus petit que notre objet.
  • Fournir au SortedSet, lors de sa construction, une instance de Comparator. L'interface Comparator n'expose qu'une unique méthode : compare(T t1, T t2), qui a la même sémantique que la méthode compareTo(T t) de Comparable.

5.2. Détails des méthodes disponibles

L'interface SortedSet propose les méthodes supplémentaires suivantes.
  • comparator() : retourne l'objet instance de Comparator qui permet la comparaison, s'il existe.
  • first() et last() : retournent le plus petit objet de l'ensemble, et le plus grand, respectivement.
  • headSet(T t) : retourne une instance de SortedSet contenant tous les éléments strictement plus petit que l'élément passé en paramètre. Ce sous-ensemble est une vue sur l'ensemble sur lequel il est construit. Il reflète donc les changements de cet ensemble, et réciproquement.
  • tailSet(T t) : retourne une instance de SortedSet contenant tous les éléments plus grands ou égaux que l'élément passé en paramètre. Ce sous-ensemble est une vue sur l'ensemble sur lequel il est construit. Il reflète donc les changements de cet ensemble, et réciproquement.
  • subSet(T inf, T sup) : retourne une instance de SortedSet contenant tous les éléments plus grands ou égaux que inf, et strictement plus petits que sup. Là encore, ce sous-ensemble est une vue sur l'ensemble sur lequel il est construit, qui reflète donc les changements de cet ensemble, et réciproquement.

5.3. Exemples d'utilisation

5.3.1. Utilisation avec une classe Comparable

Toutes les classes enveloppes des types de base, ainsi que la classe String, implémente Comparable, elles peuvent donc être utilisées normalement dans les ensembles triés. Créons une classe Marin qui va nous servir dans notre exemple. Cette classe va être utilisée dans des Set, donc elle doit surcharger equals() et hashCode().

Exemple 9. Classe ComparableMarin

public  class ComparableMarin  implements Comparable<Marin> {
   
    // deux champs classiques
    private String nom, prenom ;
   
    // suivent les getters et les setters
   
    // suit la surcharge de equals() et de hashCode()
   
    // surcharge de toString() 
    public String toString() {
   
       // un bonne méthode toString() est une méthode
       // qui ne fait pas de concaténation de chaîne !
      StringBuffer sb =  new StringBuffer() ;
      sb.append(nom).append(" ").append(prenom) ;
       return sb.toString() ;
   }
   
    // méthode imposée par Comparable<Marin>
    public  int compareTo(Marin m) {
      
       // une version complète de cette méthode
       // doit gérer le cas où nom et prenom sont nuls
       if (getNom().equals(m.getNom())) {
          return getPrenom().compareTo(m.getPrenom()) ;
      }  else {
          return getNom().compareTo(m.getNom()) ;
      }
   }
}

On peut utiliser cette classe de la façon suivante.

Exemple 10. Utilisation de SortedSet avec des éléments Comparable

// dans une méthode main
SortedSet<ComparableMarin> set =  new TreeSet<ComparableMarin>() ;
		
ComparableMarin m1 =  new ComparableMarin("Surcouf",  "Alain") ;
ComparableMarin m2 =  new ComparableMarin("Tabarly",  "Eric") ;
ComparableMarin m3 =  new ComparableMarin("Auguin",  "Christophe") ;
ComparableMarin m4 =  new ComparableMarin("Surcouf",  "Robert") ;

set.add(m1) ;
set.add(m2) ;
set.add(m3) ;
set.add(m3) ;
set.add(m4) ;

 for (ComparableMarin m : set) {
   System.out.println(m) ;
}

Le code précédent affiche le texte suivant.
Auguin Christophe
Surcouf Alain
Surcouf Robert
Tabarly Eric

5.3.2. Utilisation avec un Comparator

Supposons que nous n'ayons pas la possibilité de créer une classe Comparable. Cela peut arriver dans de nombreux cas, notamment si notre classe Marin nous est donnée toute faite, sans possibilité de la modifier. On utilise donc dans cet exemple une classe Marin qui n'implémente pas Comparable. Voyons comment utiliser un SortedSet avec un Comparator.

Exemple 11. Utilisation de SortedSet avec un Comparator

// dans une méthode main
 // définition d'une classe anonyme, implémentation de Comparator<Marin>
SortedSet<Marin> set =  new TreeSet<Marin>(new Comparator<Marin>() {

    public  int compare(Marin m1, Marin m2) {
		
       if (m1.getNom().equals(m2.getNom())) {
          return m1.getPrenom().compareTo(m2.getPrenom()) ;
      }  else {
          return m1.getNom().compareTo(m2.getNom()) ;
      }
   }
}) ;

Marin m1 =  new Marin("Surcouf",  "Alain") ;
Marin m2 =  new Marin("Tabarly",  "Eric") ;
Marin m3 =  new Marin("Auguin",  "Christophe") ;
Marin m4 =  new Marin("Surcouf",  "Robert") ;

set.add(m1) ;
set.add(m2) ;
set.add(m3) ;
set.add(m3) ;
set.add(m4) ;

 for (Marin m : set) {
   System.out.println(m) ;
}

Ce code affiche le même texte que le code précédent.
Auguin Christophe
Surcouf Alain
Surcouf Robert
Tabarly Eric
Java API avancées
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
API Collection
1. Introduction
2. Interface Collection
2.1. Notion de Collection
2.2. Détail des méthodes disponibles
2.3. Interface Iterator
2.4. Implémentation, exemples d'utilisation
3. Interface List
3.1. Notion de List
3.2. Détail des méthodes disponibles
3.3. Interface ListIterator
3.4. Implémentations, exemples d'utilisation
4. Interface Set
4.1. Notion de Set
4.2. Implémentations HashSet et LinkedHashSet
4.3. Exemples d'utilisation
5. Interface SortedSet
5.1. Notion de SortedSet
5.2. Détails des méthodes disponibles
5.3. Exemples d'utilisation
6. Interface NavigableSet
6.1. Notion de NavigableSet
6.2. Détails des méthodes disponibles
6.3. Exemple d'utilisation
7. Interfaces Queue et Deque
7.1. Notion de file d'attente
7.2. Détail des méthodes disponibles
7.3. Utilisation des interfaces Queue et Deque
8. Tables de hachage
8.1. Notion de table de hachage
8.2. Interface Map
8.3. Interface Map.Entry
8.4. Interface SortedMap
8.5. Interface NavigableMap
8.6. Implémentations
8.7. Exemples d'utilisation
9. Classes utilitaires Collections et Arrays
9.1. Introduction
9.2. Classe Arrays
9.3. Classe Collections
Génériques
1. Introduction
2. Un premier exemple
2.1. Une première classe générique
2.2. Une première méthode générique
3. Contraindre un type générique
3.1. Problème posé
3.2. Contraindre un type générique
4. Implémentation des génériques
4.1. Type erasure
4.2. Types génériques et casts
4.3. Type générique et exception
4.4. Construction d'une instance générique
4.5. Génériques et membres statiques
4.6. Collisions de méthodes génériques
4.7. Implémentation de plusieurs types identiques
5. Type <?>
5.1. Introduction
5.2. Type ? extension d'un type
5.3. Type ? super-type d'un type
Expressions régulières
1. Introduction
2. Mise en œuvre des expressions régulières
2.1. Fonctionnement d'une regexp
2.2. Fonctionnement de l'API en Java
2.3. Un premier exemple
2.4. Classe Pattern
2.5. Classe Matcher
2.6. Utilisation des méthode find() et group()
2.7. Méthodes de remplacement
2.8. Sélection de régions
3. Syntaxe des expressions régulières
3.1. Notion de classe
3.2. Étude d'un cas réel
3.3. Recherche d'un mot précis
3.4. Recherche de deux mots précis
3.5. Recherche d'un mot commençant par une lettre donnée
3.6. Cas de mots comportant des caractères accentués
3.7. Recherche sur les lignes
Introspection
1. Introduction
2. La classe Class
2.1. Utilisation de Class
2.2. Méthodes disponibles
2.3. Remarque sur la propriété Accessible
2.4. Type d'une classe
2.5. Création d'une instance à partir d'un objet Class
2.6. Cas des énumérations
3. Les classes Method et Constructor
3.1. Utilisation de Method
3.2. Utilisation de Constructor
3.3. Méthodes disponibles
3.4. Invocation d'une méthode par introspection
4. La classe Field
4.1. Utilisation de Field
4.2. Méthodes disponibles
4.3. Accès à un champ par introspection
5. La classe Modifier
Programmation concurrente
1. Introduction
2. Lançons nos premiers threads
2.1. Introduction
2.2. Un premier thread, extension de Thread
2.3. Un deuxième thread, implémentation de Runnable
2.4. Remarque sur la méthode Thread.sleep(long)
2.5. Arrêter un thread
3. Concurrence d'accès
3.1. Notion d'état
3.2. Exemple de concurrence d'accès sur un état
3.3. Analyse de la concurrence d'accès
3.4. Solution au problème
3.5. Champs volatile
4. Synchronisation
4.1. Définition d'un bloc synchronisé
4.2. Fonctionnement d'un bloc synchronisé
4.3. Notion de deadlock
4.4. Bonnes pratiques pour la synchronisation de threads
5. Opérations atomiques
5.1. Atomicité d'une opération
5.2. Solutions disponibles
5.3. Variables atomiques
6. Collections synchronisées et concurrentes
6.1. Introduction
6.2. Position du problème
6.3. Solutions proposées
7. Files d'attente
7.1. Introduction, pattern producteur / consommateur
7.2. Interface BlockingQueue<E>
7.3. Implémentations de BlockingQueue
7.4. Exemple de producteur / consommateur
7.5. Arrêter un producteur / consommateur : pilule empoisonnée
8. Classes utilitaires de l'API Concurrent
8.1. Introduction
8.2. Énumération TimeUnit
8.3. Interface Callable<V>
8.4. Interfaces Future<V> et RunnableFuture<V>
8.5. Interface ScheduledFuture<V> et RunnableScheduledFuture<V>
9. Pattern executor
9.1. Notion de réserve de threads
9.2. Interface Executor
9.3. Interface ExecutorService
9.4. Interface ScheduledExecutorService
9.5. Classe Executors
9.6. Pattern de lancement de tâches
10. Classes de contrôle d'accès
10.1. Introduction
10.2. Interfaces Lock et ReadWriteLock
10.3. Notion de verrou réentrant
10.4. Classe RentrantLock
10.5. Classe ReadWriteRentrantLock
11. Sémaphores, barrières et latches
11.1. Introduction
11.2. Notion de sémaphore, classe Semaphore
11.3. Notion de latch, classe CountDownLatch
11.4. Notion de barrière, classe CyclicBarrier