Строка # содержит использование Pattern - PullRequest
1 голос
/ 24 февраля 2020

Если бы я хотел создать 100% клон String#contains(CharSequence s): boolean в Java регулярное выражение, используя Pattern. Будут ли следующие вызовы идентичны?

input.contains(s);

и

Pattern.compile(".*" + Pattern.quote(s) + ".*").matcher(input).matches();

Аналогично, следующий код будет иметь такую ​​же функциональность?

Pattern.compile(Pattern.quote(s)).matcher(input).find();

Я предполагаю, что поиск по регулярному выражению менее производительный, но только с постоянным коэффициентом. Это правильно? Есть ли способ оптимизировать регулярные выражения для mimi c contains?


Причина, по которой я спрашиваю, состоит в том, что у меня есть фрагмент кода, который написан вокруг Pattern и кажется бесполезным создавать отдельный фрагмент кода, который использует contains. С другой стороны, я не хочу разных результатов теста - даже незначительных - для каждого кода. Есть ли какие-либо различия, связанные с Unicode, например?

Ответы [ 3 ]

2 голосов
/ 24 февраля 2020

Если вам нужно написать .contains подобный метод, основанный на Pattern, вы должны выбрать Matcher#find() версию:

Pattern.compile(Pattern.quote(s)).matcher(input).find()

Если вы хотите использовать .matches(), имейте в виду, что:

  • .* не будет соответствовать разрывам строк по умолчанию, и вам потребуется (?s) встроенный модификатор в начале шаблона или используйте Pattern.DOTALL параметр
  • .* в начале шаблона вызовет слишком большую отдачу, и вы можете получить исключение переполнения стека, или выполнение кода может просто зависнуть.
1 голос
/ 24 февраля 2020

Это просто, чтобы поделиться тем, как я решил решить эту маленькую головоломку. Я перепроектировал библиотеку, чтобы не брать Pattern, а принимать предикат, например:

public static Set<String> findAll() {
    return find(input -> true);
}

public static Set<String> findSubstring(String s) {
    return find(input -> input.contains(s));
}

public static Set<String> findPattern(Pattern p) {
    return find(p.asPredicate());
}

public static Set<String> findCaseInsensitiveSubstring(String s) {
    return find(Pattern.compile(Pattern.quote(s), Pattern.CASE_INSENSITIVE).asPredicate());
}

private static Set<String> find(Predicate<String> matcher) {
    var testInput = Set.of("some", "text", "to", "test");
    return testInput.stream().filter(matcher).collect(Collectors.toSet());
}

public static void main(String[] args) {
    System.out.println(findAll());
    System.out.println(findSubstring("t"));
    System.out.println(findPattern(Pattern.compile("^[^s]")));
    System.out.println(findCaseInsensitiveSubstring("T"));
}

, где я использовал все комментарии и ответы, приведенные до сих пор.

Обратите внимание, что есть также Pattern#asMatchPredicate() в случае, если вместо этого требуется сопоставление, например, для функции matchPattern.

Конечно, выше это просто демонстрация, а не фактические функции в моем решении.

1 голос
/ 24 февраля 2020

Есть 2 способа проверить, соответствует ли строка шаблону:

return Pattern.compile(Pattern.quote(s)).asPredicate().test(input);

или

return Pattern.compile(Pattern.quote(s)).matcher.find(input);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...