Nous arrivons maintenant au morceau de choix de ce chapitre. Comme nous l'avons déjà entrevu, les expressions régulières sont exprimées dans une syntaxe très précise, très hermétique, et très chatouilleuse. Des livres entiers y ont été consacrées, il ne s'agit donc pas ici d'en faire un cours complet, mais plutôt un aperçu qui permette de résoudre les cas simples, et d'éviter de tomber dans les pièges les plus fréquents. La syntaxe des expressions régulières Java est précisée dans la Javadoc à la page Pattern .

Une expression régulière est une chaîne de caractères. Le premier principe est qu'un caractère se représente lui-même. Ainsi le pattern "bonjour" représente simplement le mot "bonjour".

Il est ensuite possible d'ajouter des caractères spéciaux à un pattern, de façon à enrichir ce qu'il représente. Par exemple, le pattern "a*" représente toutes les chaînes de caractères constituées d'un nombre quelconque de "a" (y compris la chaîne vide). Ajouter le caractère "*" à un pattern signifie que ce pattern peut se répéter. Nous avons également vu que le caractère "." pouvait représenter n'importe quel caractère. Nous en déduisons que le pattern ".*", que nous avons déjà utilisé, représente toutes les chaînes de caractères, y compris la chaîne vide.

Il est possible ensuite de définir et d'utiliser des classes de caractères . Une classe de caractère est définie par une chaîne de caractères écrite entre crochets. Par exemple, la classe "[abc]" représente un unique caractère, qui peut être a ou b ou c. Voyons toutes les possibilités de définir une classe.


Certains classes sont prédéfinies, et portent un nom particulier. Nous en avons en fait déjà vue une : ".". Cette classe particulière représente n'importe quel caractère. Voyons ici ces classes prédéfinies.


Ces quatre dernières classes font appel aux méthodes correspondantes de la classe Character. Tous les caractères c pour lesquels Character.isLowerCase(c) retourne true appartiennent à la classe \p{javaLowerCase}.

On peut utiliser toutes les méthodes statiques de la classe Character du type isProperty(char) de cette façon, en utilisant la classe \p{javaProperty}.

Il existe encore quelques caractères spéciaux, qui permettent de détecter des éléments particuliers d'un texte.


Enfin voici les quantifieurs, avec leurs deux versions greedy et reluctant . Dans ces tableaux, X représente une classe quelconque.


Enfin signalons l'opérateur | : X | Y signifie que le caractère considéré doit appartenir soit à la classe X , soit à la classe Y .

Voyons maintenant quelques exemples d'application, indispensables pour comprendre comment tout cela fonctionne.

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