Рубрики
Без рубрики

Проверьте, содержит ли строка несколько ключевых слов в Java

Узнайте о различных методах определения того, содержит ли строка Java несколько ключевых слов

Автор оригинала: baeldung.

1. введение

В этом кратком руководстве мы узнаем, как обнаружить несколько слов внутри строки .

2. Наш Пример

Предположим, у нас есть строка:

String inputString = "hello there, Baeldung";

Наша задача состоит в том, чтобы найти, содержит ли входная строка | слова/| “hello” и “Baeldung” .

Итак, давайте поместим наши ключевые слова в массив:

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

Кроме того, порядок слов не важен, и совпадения должны быть чувствительны к регистру.

3. Использование String.contains()

Для начала мы покажем, как использовать метод String.contains() для достижения нашей цели .

Давайте пройдемся по массиву ключевых слов и проверим вхождение каждого элемента в 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;
}

Метод contains() вернет true , если входная строка содержит данный элемент . Когда у нас нет ни одного из ключевых слов внутри нашей строки, мы можем прекратить движение вперед и немедленно вернуть false .

Несмотря на то, что нам нужно написать больше кода, это решение является быстрым для простых случаев использования.

4. Использование String.indexOf()

Аналогично решению, использующему метод String.contains () , мы можем проверить индексы ключевых слов с помощью метода String.indexOf () /. Для этого нам нужен метод, принимающий входную строку и список ключевых слов:

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

Метод indexOf() возвращает индекс слова внутри входной строки /. Когда у нас нет слова в тексте, индекс будет равен -1.

5. Использование Регулярных Выражений

Теперь давайте использовать регулярное выражение , чтобы соответствовать нашим словам. Для этого мы будем использовать класс Pattern .

Во-первых, давайте определим строковое выражение. Поскольку нам нужно сопоставить два ключевых слова, мы построим наше правило регулярных выражений с двумя точками обзора:

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

И для общего случая:

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

После этого мы будем использовать метод matcher() для поиска() вхождений:

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

Но, регулярные выражения имеют стоимость производительности. Если у нас есть несколько слов для поиска, производительность этого решения может быть не оптимальной.

6. Использование Java 8 и списка

И, наконец, мы можем использовать потоковый API Java 8 . Но сначала давайте сделаем некоторые незначительные преобразования с нашими исходными данными:

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

Теперь пришло время использовать 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);
}

Приведенный выше конвейер операций вернет true , если входная строка содержит все наши ключевые слова.

В качестве альтернативы мы можем просто использовать метод containsAll() фреймворка Collections для достижения желаемого результата:

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

    return inputStringList.containsAll(wordsList);
}

Однако этот метод работает только для целых слов. Таким образом, он будет определять ключевые слова только в том случае, если они разделены пробелами в тексте.

7. Использование алгоритма Ахо-Корасика

Проще говоря, алгоритм Aho-Corasick предназначен для поиска текста по нескольким ключевым словам . Он имеет O(n) временную сложность независимо от того, сколько ключевых слов мы ищем или какова длина текста.

Давайте включим зависимость алгоритма Ахо-Корасика в ваш pom.xml :


    org.ahocorasick
    ahocorasick
    0.4.0

Во-первых, давайте построим конвейер trie с массивом ключевых слов words . Для этого мы будем использовать структуру данных Trie :

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

После этого вызовем метод парсера с входной строкой текстом, в котором мы хотели бы найти ключевые слова, и сохраним результаты в коллекции emits :

Collection emits = trie.parseText(inputString);

И, наконец, если мы напечатаем наши результаты:

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

Для каждого ключевого слова мы увидим начальную позицию ключевого слова в тексте, конечную позицию и само ключевое слово:

0:4=hello
13:20=Baeldung

Наконец, давайте посмотрим на полную реализацию:

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

В этом примере мы ищем только целые слова. Итак, если мы хотим сопоставить не только inputString , но и “helloBaeldung” , мы должны просто удалить атрибут onlyWholeWords() из конвейера Trie builder.

Кроме того, имейте в виду, что мы также удаляем повторяющиеся элементы из коллекции emits , так как для одного и того же ключевого слова может быть несколько совпадений.

8. Заключение

В этой статье мы узнали, как найти несколько ключевых слов внутри строки. Кроме того, мы показали примеры с использованием основного JDK, а также с библиотекой Aho-Corasick .

Как обычно, полный код этой статьи доступен на GitHub .