Скажем, у меня есть две строки,
String s1 = "AbBaCca";
String s2 = "bac";
Я хочу выполнить возврат чека, который s2
содержится внутри s1
. Я могу сделать это с:
return s1.contains(s2);
Я уверен, что contains()
это чувствительно к регистру, но я не могу определить это наверняка, прочитав документацию. Если это так, то я полагаю, что мой лучший метод будет что-то вроде:
return s1.toLowerCase().contains(s2.toLowerCase());
Помимо всего этого, есть ли другой (возможно, лучший) способ сделать это, не заботясь о чувствительности к регистру?
Ответы:
Да, содержит с учетом регистра. Вы можете использовать java.util.regex.Pattern с флагом CASE_INSENSITIVE для сопоставления без учета регистра:
РЕДАКТИРОВАТЬ: Если s2 содержит специальные символы регулярных выражений (из которых их много), важно сначала процитировать его. Я исправил свой ответ, так как это первый, который увидят люди, но проголосуйте за Мэтта Квила, так как он указал на это.
источник
Pattern.CASE_INSENSITIVE
, это работает только для символов ASCII (т. Е. «Ä» не будет соответствовать «ä»).UNICODE_CASE
Для достижения этого необходимо дополнительно указать флаг.Pattern
более производительный, чемs1.toLowerCase().contains(s2.toLowerCase())
?Pattern.compile(Pattern.quote(needle), Pattern.CASE_INSENSITIVE).matcher(haystack).find()
Одна проблема с ответом Дейва Л. - это когда s2 содержит разметку регулярных выражений, например
\d
, и т. Д.Вы хотите вызвать Pattern.quote () на s2:
источник
toLowerCase().contains()
быстрее. Я выполнил некоторый анализ скорости, см. Мой ответ для результатов: stackoverflow.com/a/25379180/1705598Pattern.UNICODE_CASE
флаг тоже. Не могли бы вы подтвердить это?Ты можешь использовать
Библиотека Apache Commons очень полезна для такого рода вещей. И этот конкретный может быть лучше, чем регулярные выражения, так как регулярное выражение всегда дорого с точки зрения производительности.
источник
String.regionMatches
, который использует посимвольные преобразования, так что нет. Более того,containsIgnoreCase("ß", "ss")
возвращает -1, что неправильно во всех локалях (немецкий язык «sharp s»Быстрая реализация: использование
String.regionMatches()
Использование регулярных выражений может быть относительно медленным. Это (медленно) не имеет значения, если вы просто хотите проверить в одном случае. Но если у вас есть массив или набор из тысяч или сотен тысяч строк, все может стать довольно медленным.
Представленное ниже решение не использует ни регулярные выражения, ни
toLowerCase()
(что также является медленным, потому что оно создает другие строки и просто выбрасывает их после проверки).Решение основано на методе String.regionMatches (), который кажется неизвестным. Он проверяет,
String
совпадают ли 2 области, но важно то, что он также имеет перегрузку с удобнымignoreCase
параметром.Анализ скорости
Этот анализ скорости не означает ракетостроение, это лишь приблизительная картина того, насколько быстры разные методы.
Я сравниваю 5 методов.
String.contains()
.String.contains()
с предварительно кэшированной подстрокой . Это решение уже не так гибко, потому что оно тестирует предстроку подстроки.Pattern.compile().matcher().find()
...)Pattern
. Это решение уже не так гибко, потому что оно тестирует предопределенную подстроку.Результаты (вызвав метод 10 миллионов раз):
Pattern
: 1845 мсРезультаты в таблице:
Наш метод в 4 раза быстрее по сравнению со строчными буквами и использованием
contains()
, в 10 раз быстрее по сравнению с использованием регулярных выражений, а также в 3 раза быстрее, даже еслиPattern
он предварительно кэширован (и теряет гибкость проверки произвольной подстроки).Анализ тестового кода
Если вам интересно, как был проведен анализ, вот вам готовое приложение:
источник
ß
(немецкая резкая S; с заглавной буквыSS
), а также для некоторых других символов (см. ИсточникString.regionMatches
, который пытается оба преобразования).StringUtils.containsIgnoreCase()
- это то, что и мое решение, и Apache используютregionMatches()
метод (в цикле), но даже это не то же самое, что я вызываюString.regionMatches()
и ApacheCharSequenceUtils.regionMatches()
.CharSequenceUtils.regionMatches
просто звонит наString.regionMatches
самом деле. В любом случае, я хотел дать информацию, что если кто-то уже использует библиотеку StringUtils, он может просто вызвать ее, потому что это эффективный способ, как вы докажете это с помощью своего теста. Если бы я не использовал Apache lib, я бы окончательно использовал ваш метод;)Более простым способом сделать это (не беспокоясь о сопоставлении с образцом) было бы преобразование обоих
String
s в нижний регистр:источник
Да, это достижимо
Этот код вернет строку "ИСТИНА!" как выяснилось, что ваши персонажи содержались.
источник
s2
. Не говоря о таких деталях, как эта, эта не компилируется, и если она это делает, она возвращает строку.Вы можете использовать регулярные выражения , и это работает:
источник
Вот некоторые Unicode-дружественные, которые вы можете сделать, если вы используете ICU4j. Я предполагаю, что «игнорировать регистр» сомнителен для имен методов, потому что, хотя первичные сравнения силы действительно игнорируют регистр, он описывается как специфика, зависящая от локали. Но мы надеемся, что это зависит от локали, как и ожидал пользователь.
источник
Я сделал тест, чтобы найти регистр без учета совпадения строки. У меня есть Вектор из 150000 объектов со Строкой в одном поле, и я хотел найти подмножество, соответствующее строке. Я попробовал три метода:
Конвертировать все в нижний регистр
Используйте метод String match ()
Используйте регулярные выражения
Сроки результаты:
Нет попыток совпадения: 20 мсек
Чтобы понизить соответствие: 182 мсек
Струнные совпадения: 278 мсек
Регулярное выражение: 65 мсек
Регулярное выражение выглядит самым быстрым для этого варианта использования.
источник
Существует простой и краткий способ использования флага регулярных выражений (без учета регистра {i}):
источник
Я не уверен, что ваш главный вопрос здесь, но да, .contains учитывает регистр.
источник
По сути, это метод, который принимает две строки. Предполагается, что это версия с учетом регистра (не чувствительная к регистру). При использовании метода contains вы хотите увидеть, содержится ли одна строка в другой.
Этот метод берет строку, которая является «sub», и проверяет, равна ли она подстрокам строки контейнера, длина которых равна «sub». Если вы посмотрите на
for
цикл, вы увидите, что он перебирает подстроки (длина «sub») над строкой контейнера.Каждая итерация проверяет, находится ли подстрока строки контейнера
equalsIgnoreCase
в подпрограмме.источник
Если вам придется искать строку ASCII в другой строке ASCII, например в URL , вы найдете мое решение лучше. Я проверил метод icza и мой на скорость, и вот результаты:
Код:
источник
источник
источник
Мы можем использовать поток с anyMatch и содержит Java 8
источник
или вы можете использовать простой подход и просто преобразовать регистр строки в регистр подстроки, а затем использовать метод contains.
источник
источник
Вы можете просто сделать что-то вроде этого:
источник