Vérifier si une chaîne contient plusieurs mots-clés en Java

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.