Digamos que eu tenho duas cordas,
String s1 = "AbBaCca";
String s2 = "bac";
Quero executar uma verificação de retorno que s2
esteja contida nele s1
. Eu posso fazer isso com:
return s1.contains(s2);
Tenho certeza de que contains()
diferencia maiúsculas de minúsculas, mas não posso determinar isso com certeza lendo a documentação. Se for, acho que meu melhor método seria algo como:
return s1.toLowerCase().contains(s2.toLowerCase());
Tudo isso à parte, existe outra maneira (possivelmente melhor) de fazer isso sem se preocupar com a distinção entre maiúsculas e minúsculas?
Respostas:
Sim, contém diferencia maiúsculas de minúsculas. Você pode usar java.util.regex.Pattern com o sinalizador CASE_INSENSITIVE para correspondência sem distinção entre maiúsculas e minúsculas:
EDIT: Se s2 contiver caracteres especiais regex (dos quais existem muitos), é importante citá-lo primeiro. Corrigi minha resposta, já que é a primeira que as pessoas verão, mas vote na de Matt Quail desde que ele apontou isso.
fonte
Pattern.CASE_INSENSITIVE
, isso funciona apenas para caracteres ASCII (ou seja, "Ä" não corresponde a "ä"). É preciso especificar adicionalmente aUNICODE_CASE
bandeira para conseguir isso.Pattern
mais desempenho do ques1.toLowerCase().contains(s2.toLowerCase())
?Pattern.compile(Pattern.quote(needle), Pattern.CASE_INSENSITIVE).matcher(haystack).find()
Um problema com a resposta de Dave L. é quando s2 contém a marcação regex como
\d
, etc.Você deseja chamar Pattern.quote () no s2:
fonte
toLowerCase().contains()
é mais rápido. Eu realizada uma análise rápida, consulte minha resposta para resultados: stackoverflow.com/a/25379180/1705598Pattern.UNICODE_CASE
bandeira também. Poderia confirmar isso?Você pode usar
A biblioteca Apache Commons é muito útil para esse tipo de coisa. E essa em particular pode ser melhor do que expressões regulares, pois a expressão regular é sempre cara em termos de desempenho.
fonte
String.regionMatches
, que usa conversões entre caracteres, portanto não. Além disso,containsIgnoreCase("ß", "ss")
retorna-1, o que é errado em cada localidade (os alemães "s afiados" capitaliza com "ss".Uma implementação mais rápida: utilizando
String.regionMatches()
O uso do regexp pode ser relativamente lento. (Ser lento) não importa se você deseja apenas verificar em um caso. Mas se você tiver uma matriz ou uma coleção de milhares ou centenas de milhares de strings, as coisas podem ficar bem lentas.
A solução apresentada abaixo não usa expressões regulares nem
toLowerCase()
(o que também é lento porque cria outras strings e as joga fora após a verificação).A solução baseia-se no método String.regionMatches () que parece ser desconhecido. Ele verifica se duas
String
regiões correspondem, mas o importante é que ele também tenha uma sobrecarga com umignoreCase
parâmetro útil .Análise rápida
Essa análise de velocidade não significa ciência de foguetes, apenas uma imagem aproximada da rapidez com que os diferentes métodos são.
Eu comparo 5 métodos.
String.contains()
.String.contains()
com a substring pré-armazenada em cache e em minúsculas. Essa solução já não é tão flexível porque testa uma substring de pré-amigo.Pattern.compile().matcher().find()
...)Pattern
. Essa solução já não é tão flexível porque testa uma substring predefinida.Resultados (chamando o método 10 milhões de vezes):
Pattern
: 1845 msResultados em uma tabela:
Nosso método é 4x mais rápido em comparação com letras minúsculas e usando
contains()
, 10x mais rápido em comparação com expressões regulares e também 3x mais rápido, mesmo se oPattern
cache for pré-armazenado em cache (e perdendo a flexibilidade de verificar se há uma substring arbitrária).Código do Teste de Análise
Se você estiver interessado em saber como a análise foi realizada, aqui está o aplicativo executável completo:
fonte
ß
(S acentuado em alemão; coloca em maiúscula emSS
) e também em alguns outros caracteres (consulte a fonte deString.regionMatches
, que tenta as duas conversões).StringUtils.containsIgnoreCase()
é que tanto a minha solução quanto a Apache usam umregionMatches()
método (em um ciclo), mas mesmo isso não é o mesmo que eu chamoString.regionMatches()
e o Apache chamaCharSequenceUtils.regionMatches()
.CharSequenceUtils.regionMatches
apenas ligaString.regionMatches
na verdade. Enfim, meu objetivo era fornecer as informações de que, se alguém já estiver usando o StringUtils lib, ele poderá chamá-lo, porque parece ser uma maneira eficiente de você provar isso com seu benchmark. Se eu não estivesse usando a biblioteca Apache, definitivamente usaria o seu método;)Uma maneira mais simples de fazer isso (sem se preocupar com a correspondência de padrões) seria converter os dois
String
em minúsculas:fonte
Sim, isso é possível:
Este código retornará a String "TRUE!" pois descobriu que seus personagens estavam contidos.
fonte
s2
. Não falando sobre detalhes como esse, este não é compilado e, se o fizer, retornará uma string.Você pode usar expressões regulares e funciona:
fonte
Aqui estão alguns compatíveis com Unicode que você pode criar se você usar o ICU4j. Eu acho que "ignorar maiúsculas e minúsculas" é questionável para os nomes dos métodos, porque, embora as comparações de força primária ignorem maiúsculas e minúsculas, elas são descritas como as especificidades dependentes da localidade. Mas espero que seja dependente da localidade da maneira que o usuário esperaria.
fonte
Fiz um teste para encontrar uma correspondência que não diferencia maiúsculas de minúsculas de uma string. Eu tenho um vetor de 150.000 objetos, todos com uma String como um campo e queria encontrar o subconjunto que correspondesse a uma string. Eu tentei três métodos:
Converter tudo em minúsculas
Use o método String correspondências ()
Use expressões regulares
Os resultados do tempo são:
Nenhuma tentativa de correspondência: 20 ms
Para diminuir a correspondência: 182 msegs
Correspondências de sequência: 278 msegs
Expressão regular: 65 ms
A expressão regular parece ser a mais rápida para este caso de uso.
fonte
Existe uma maneira concisa e simples, usando o sinalizador regex (sem distinção entre maiúsculas e minúsculas {i}):
fonte
Não sei qual é a sua pergunta principal, mas sim, .contains diferencia maiúsculas de minúsculas.
fonte
Basicamente, é um método que usa duas strings. Supõe-se que seja uma versão que não diferencia maiúsculas de minúsculas de contains (). Ao usar o método contains, você deseja ver se uma sequência está contida na outra.
Esse método pega a string "sub" e verifica se é igual às substrings da string do contêiner que são iguais em comprimento ao "sub". Se você observar o
for
loop, verá que ele itera em substrings (que são o comprimento do "sub") sobre a string do contêiner.Cada iteração verifica se a subcadeia de caracteres da string do contêiner está
equalsIgnoreCase
no sub.fonte
Se você precisar pesquisar uma sequência ASCII em outra sequência ASCII, como uma URL , encontrará minha solução melhor. Eu testei o método do icza e o meu pela velocidade e aqui estão os resultados:
O código:
fonte
fonte
fonte
Podemos usar stream com anyMatch e contém Java 8
fonte
ou você pode usar uma abordagem simples e apenas converter o caso da string em caso de substring e, em seguida, use o método contains.
fonte
fonte
Você poderia simplesmente fazer algo assim:
fonte