Sprawdź, czy ciąg zawiera wiele słów kluczowych w języku Java

1. Wprowadzenie

Z tego krótkiego samouczka dowiemy się, jak wykryć wiele słów w ciągu .

2. Nasz przykład

Załóżmy, że mamy ciąg:

String inputString = "hello there, Baeldung";

Naszym zadaniem jest sprawdzenie, czy inputString zawiera słowa „hello” i „Baeldung” .

Więc umieśćmy nasze słowa kluczowe w tablicy:

String[] words = {"hello", "Baeldung"};

Co więcej, kolejność słów nie jest ważna, a dopasowania powinny uwzględniać wielkość liter.

3. Używanie String.contains ()

Na początek pokażemy, jak użyć metody String.contains () , aby osiągnąć nasz cel .

Zapętlmy tablicę słów kluczowych i sprawdźmy występowanie każdego elementu wewnątrz 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; }

Metoda zawiera () zwróci wartość true, jeśli inputString zawiera daną pozycję . Kiedy nie mamy żadnego ze słów kluczowych w naszym ciągu, możemy przestać iść do przodu i zwrócić natychmiastowe fałsz .

Pomimo tego, że musimy napisać więcej kodu, to rozwiązanie jest szybkie w prostych przypadkach użycia.

4. Używanie String.indexOf ()

Podobne do rozwiązania, które wykorzystuje String.contains () metodę, możemy sprawdzić indeksy słów kluczowych za pomocą String.indexOf () metody . W tym celu potrzebujemy metody akceptującej inputString i listę słów kluczowych:

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; }

Metoda indexOf () zwraca indeks słowa wewnątrz ciągu inputString . Gdy nie mamy słowa w tekście, indeks będzie wynosił -1.

5. Używanie wyrażeń regularnych

Teraz użyjmy wyrażenia regularnego, aby dopasować nasze słowa. W tym celu użyjemy klasy Pattern .

Najpierw zdefiniujmy wyrażenie tekstowe. Ponieważ musimy dopasować dwa słowa kluczowe, utworzymy naszą regułę wyrażenia regularnego z dwoma wyprzedzeniami:

Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)");

A dla przypadku ogólnego:

StringBuilder regexp = new StringBuilder(); for (String word : words) { regexp.append("(?=.*").append(word).append(")"); }

Następnie użyjemy metody matcher () , aby znaleźć () wystąpienia:

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(); }

Jednak wyrażenia regularne mają koszt wydajności. Jeśli mamy wiele słów do wyszukania, wydajność tego rozwiązania może nie być optymalna.

6. Korzystanie z języka Java 8 i listy

I wreszcie możemy użyć Stream API Java 8. Ale najpierw wykonajmy drobne transformacje z naszymi początkowymi danymi:

List inputString = Arrays.asList(inputString.split(" ")); List words = Arrays.asList(words);

Teraz nadszedł czas, aby użyć Stream API:

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); }

Powyższy potok operacji zwróci wartość true, jeśli ciąg wejściowy zawiera wszystkie nasze słowa kluczowe.

Alternatywnie, możemy po prostu użyć metody includeAll () struktury Collections, aby osiągnąć pożądany wynik:

public static boolean containsWordsArray(String inputString, String[] words) { List inputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return inputStringList.containsAll(wordsList); }

Jednak ta metoda działa tylko dla całych słów. Tak więc znalazłby nasze słowa kluczowe tylko wtedy, gdyby były oddzielone spacjami w tekście.

7. Korzystanie z algorytmu Aho-Corasicka

Mówiąc najprościej, algorytm Aho-Corasick służy do wyszukiwania tekstu za pomocą wielu słów kluczowych . Ma złożoność czasową O (n) bez względu na to, ile słów kluczowych szukamy lub jak długa jest długość tekstu.

Uwzględnijmy zależność algorytmu Aho-Corasick w naszym pom.xml :

 org.ahocorasick ahocorasick 0.4.0 

Najpierw zbudować rurociąg TRIE ze słowa tablicy słów kluczowych. W tym celu użyjemy struktury danych Trie:

Trie trie = Trie.builder().onlyWholeWords().addKeywords(words).build();

Po tym, nazwijmy metoda parser z inputString tekstu, w którym chcielibyśmy, aby znaleźć słowa kluczowe i zapisać wyniki w emituje kolekcji:

Collection emits = trie.parseText(inputString);

I wreszcie, jeśli wydrukujemy nasze wyniki:

emits.forEach(System.out::println);

Dla każdego słowa kluczowego zobaczymy pozycję początkową słowa kluczowego w tekście, pozycję końcową i samo słowo kluczowe:

0:4=hello 13:20=Baeldung

Na koniec zobaczmy pełną implementację:

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; }

W tym przykładzie szukamy tylko całych słów. Tak więc, jeśli chcemy dopasować nie tylko inputString, ale także „helloBaeldung” , powinniśmy po prostu usunąć atrybut onlyWholeWords () z potoku budującego Trie .

Ponadto pamiętaj, że usuwamy również zduplikowane elementy z kolekcji emits , ponieważ może istnieć wiele dopasowań dla tego samego słowa kluczowego.

8. Wniosek

W tym artykule dowiedzieliśmy się, jak znaleźć wiele słów kluczowych w ciągu znaków. Ponadto pokazaliśmy przykłady przy użyciu podstawowego JDK, a także biblioteki Aho-Corasick .

Jak zwykle, pełny kod tego artykułu jest dostępny w serwisie GitHub.