1. Introduction
Dans ce tutoriel rapide, nous découvrirons comment détecter plusieurs mots à l'intérieur d'une chaîne .
2. Notre exemple
Supposons que nous ayons la chaîne:
String inputString = "hello there, Baeldung";
Notre tâche est de savoir si la chaîne inputString contient les mots «bonjour» et «Baeldung» .
Alors, mettons nos mots-clés dans un tableau:
String[] words = {"hello", "Baeldung"};
De plus, l'ordre des mots n'est pas important et les correspondances doivent être sensibles à la casse.
3. Utilisation de String.contains ()
Pour commencer, nous montrerons comment utiliser la méthode String.contains () pour atteindre notre objectif .
Passons en boucle sur le tableau des mots-clés et vérifions l'occurrence de chaque élément à l'intérieur de la chaîne inputString:
public static boolean containsWords(String inputString, String[] items) { boolean found = true; for (String item : items) { if (!inputString.contains(item)) { found = false; break; } } return found; }
La méthode contains () retournera true si la chaîne inputString contient l' élément donné . Lorsque nous n'avons aucun des mots-clés dans notre chaîne, nous pouvons arrêter d'avancer et renvoyer immédiatement un faux .
Malgré le fait que nous ayons besoin d'écrire plus de code, cette solution est rapide pour des cas d'utilisation simples.
4. Utilisation de String.indexOf ()
Semblable à la solution qui utilise la méthode String.contains () , nous pouvons vérifier les indices des mots-clés à l'aide de la méthode String.indexOf () . Pour cela, nous avons besoin d'une méthode acceptant la inputString et la liste des mots-clés:
public static boolean containsWordsIndexOf(String inputString, String[] words) { boolean found = true; for (String word : words) { if (inputString.indexOf(word) == -1) { found = false; break; } } return found; }
La méthode indexOf () renvoie l'index du mot à l'intérieur de inputString . Lorsque nous n'avons pas le mot dans le texte, l'index sera -1.
5. Utilisation d'expressions régulières
Maintenant, utilisons une expression régulière pour faire correspondre nos mots. Pour cela, nous utiliserons la classe Pattern .
Tout d'abord, définissons l'expression de chaîne. Comme nous devons faire correspondre deux mots-clés, nous allons créer notre règle regex avec deux lookaheads:
Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)");
Et pour le cas général:
StringBuilder regexp = new StringBuilder(); for (String word : words) { regexp.append("(?=.*").append(word).append(")"); }
Après cela, nous utiliserons la méthode matcher () pour rechercher () les occurrences:
public static boolean containsWordsPatternMatch(String inputString, String[] words) { StringBuilder regexp = new StringBuilder(); for (String word : words) { regexp.append("(?=.*").append(word).append(")"); } Pattern pattern = Pattern.compile(regexp.toString()); return pattern.matcher(inputString).find(); }
Mais les expressions régulières ont un coût en termes de performances. Si nous avons plusieurs mots à rechercher, les performances de cette solution peuvent ne pas être optimales.
6. Utilisation de Java 8 et de List
Et enfin, nous pouvons utiliser l'API Stream de Java 8. Mais d'abord, faisons quelques transformations mineures avec nos données initiales:
List inputString = Arrays.asList(inputString.split(" ")); List words = Arrays.asList(words);
Il est maintenant temps d'utiliser l'API Stream:
public static boolean containsWordsJava8(String inputString, String[] words) { List inputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return wordsList.stream().allMatch(inputStringList::contains); }
Le pipeline d'opérations ci-dessus retournera true si la chaîne d'entrée contient tous nos mots clés.
Alternativement, nous pouvons simplement utiliser la méthode containsAll () du framework Collections pour obtenir le résultat souhaité:
public static boolean containsWordsArray(String inputString, String[] words) { List inputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return inputStringList.containsAll(wordsList); }
Cependant, cette méthode ne fonctionne que pour des mots entiers. Ainsi, il trouverait nos mots-clés uniquement s'ils sont séparés par des espaces dans le texte.
7. Utilisation de l' Aho-Corasick algorithme
En termes simples, l' algorithme Aho-Corasick est destiné à la recherche de texte avec plusieurs mots-clés . Il a une complexité temporelle O (n) quel que soit le nombre de mots-clés que nous recherchons ou la longueur du texte.
Incluons la dépendance de l'algorithme Aho-Corasick dans notre pom.xml :
org.ahocorasick ahocorasick 0.4.0
Tout d' abord, nous allons construire le pipeline de Trie avec les mots éventail de mots - clés. Pour cela, nous utiliserons la structure de données Trie:
Trie trie = Trie.builder().onlyWholeWords().addKeywords(words).build();
Après cela, appelons la méthode parser avec le texte inputString dans lequel nous aimerions trouver les mots-clés et enregistrer les résultats dans la collection emits :
Collection emits = trie.parseText(inputString);
Et enfin, si nous imprimons nos résultats:
emits.forEach(System.out::println);
Pour chaque mot-clé, nous verrons la position de départ du mot-clé dans le texte, la position de fin et le mot-clé lui-même:
0:4=hello 13:20=Baeldung
Enfin, voyons l'implémentation complète:
public static boolean containsWordsAhoCorasick(String inputString, String[] words) { Trie trie = Trie.builder().onlyWholeWords().addKeywords(words).build(); Collection emits = trie.parseText(inputString); emits.forEach(System.out::println); boolean found = true; for(String word : words) { boolean contains = Arrays.toString(emits.toArray()).contains(word); if (!contains) { found = false; break; } } return found; }
Dans cet exemple, nous recherchons uniquement des mots entiers. Donc, si nous voulons faire correspondre non seulement la chaîne inputString mais également «helloBaeldung» , nous devrions simplement supprimer l' attribut onlyWholeWords () du pipeline du générateur Trie .
De plus, gardez à l'esprit que nous supprimons également les éléments en double de la collection emits , car il peut y avoir plusieurs correspondances pour le même mot-clé.
8. Conclusion
Dans cet article, nous avons appris à trouver plusieurs mots-clés dans une chaîne. De plus, nous avons montré des exemples en utilisant le noyau JDK, ainsi qu'avec la bibliothèque Aho-Corasick .
Comme d'habitude, le code complet de cet article est disponible à l'adresse over sur GitHub.