说我有两个字符串,
String s1 = "AbBaCca";
String s2 = "bac";
我想执行一项检查,返回s2
中包含的s1
。我可以这样做:
return s1.contains(s2);
我很确定contains()
区分大小写,但是我无法通过阅读文档来确定这一点。如果是,那么我想我最好的方法就是:
return s1.toLowerCase().contains(s2.toLowerCase());
除此之外,还有另一种(可能更好的)方法可以在不关心区分大小写的情况下实现这一目标吗?
答案 0 :(得分:300)
是,包含区分大小写。您可以将java.util.regex.Pattern与CASE_INSENSITIVE标志一起用于不区分大小写的匹配:
Pattern.compile(Pattern.quote(wantedStr), Pattern.CASE_INSENSITIVE).matcher(source).find();
编辑:如果s2包含正则表达式特殊字符(其中有很多),首先引用它是很重要的。我已经纠正了我的答案,因为这是人们会看到的第一个答案,但是自从他指出这一点以来就投票给Matt Quail。
答案 1 :(得分:246)
the answer by Dave L.的一个问题是s2包含正则表达式标记,例如\d
等。
你想在s2上调用Pattern.quote():
Pattern.compile(Pattern.quote(s2), Pattern.CASE_INSENSITIVE).matcher(s1).find();
答案 2 :(得分:133)
您可以使用
org.apache.commons.lang3.StringUtils.containsIgnoreCase("AbBaCca", "bac");
Apache Commons库对于这类事情非常有用。而且这个特殊的可能比正则表达式更好,因为正则表达式在性能方面总是很昂贵。
答案 3 :(得分:106)
String.regionMatches()
使用regexp可能会相对较慢。如果您只是想检查一个案例,那么(缓慢)并不重要。但是如果你有一个数组或数千或数十万个字符串的集合,那么事情就会变得很慢。
下面介绍的解决方案并不使用正则表达式,也不使用toLowerCase()
(这也很慢,因为它会创建另一个字符串,并在检查后将它们抛弃)。
该解决方案建立在似乎未知的String.regionMatches()方法的基础之上。它检查2 String
个区域是否匹配,但重要的是它还有一个带有方便的ignoreCase
参数的重载。
public static boolean containsIgnoreCase(String src, String what) {
final int length = what.length();
if (length == 0)
return true; // Empty string is contained
final char firstLo = Character.toLowerCase(what.charAt(0));
final char firstUp = Character.toUpperCase(what.charAt(0));
for (int i = src.length() - length; i >= 0; i--) {
// Quick check before calling the more expensive regionMatches() method:
final char ch = src.charAt(i);
if (ch != firstLo && ch != firstUp)
continue;
if (src.regionMatches(true, i, what, 0, length))
return true;
}
return false;
}
这种速度分析并不意味着是火箭科学,只是粗略描述不同方法的速度。
我比较了5种方法。
String.contains()
。String.contains()
。这个解决方案已经不那么灵活了,因为它测试了一个预先定义的子字符串。Pattern.compile().matcher().find()
...)Pattern
。此解决方案已经不那么灵活,因为它会测试预定义的子字符串。结果(通过调用方法1000万次):
Pattern
:1845 ms 表中的结果:
RELATIVE SPEED 1/RELATIVE SPEED
METHOD EXEC TIME TO SLOWEST TO FASTEST (#1)
------------------------------------------------------------------------------
1. Using regionMatches() 670 ms 10.7x 1.0x
2. 2x lowercase+contains 2829 ms 2.5x 4.2x
3. 1x lowercase+contains cache 2446 ms 2.9x 3.7x
4. Regexp 7180 ms 1.0x 10.7x
5. Regexp+cached pattern 1845 ms 3.9x 2.8x
与使用正常表达相比,使用contains()
,快10倍时,我们的方法快4倍 快3倍即使Pattern
已预先缓存(并且失去了检查任意子字符串的灵活性)。
如果您对如何执行分析感兴趣,请参阅完整的可运行应用程序:
import java.util.regex.Pattern;
public class ContainsAnalysis {
// Case 1 utilizing String.regionMatches()
public static boolean containsIgnoreCase(String src, String what) {
final int length = what.length();
if (length == 0)
return true; // Empty string is contained
final char firstLo = Character.toLowerCase(what.charAt(0));
final char firstUp = Character.toUpperCase(what.charAt(0));
for (int i = src.length() - length; i >= 0; i--) {
// Quick check before calling the more expensive regionMatches()
// method:
final char ch = src.charAt(i);
if (ch != firstLo && ch != firstUp)
continue;
if (src.regionMatches(true, i, what, 0, length))
return true;
}
return false;
}
// Case 2 with 2x toLowerCase() and contains()
public static boolean containsConverting(String src, String what) {
return src.toLowerCase().contains(what.toLowerCase());
}
// The cached substring for case 3
private static final String S = "i am".toLowerCase();
// Case 3 with pre-cached substring and 1x toLowerCase() and contains()
public static boolean containsConverting(String src) {
return src.toLowerCase().contains(S);
}
// Case 4 with regexp
public static boolean containsIgnoreCaseRegexp(String src, String what) {
return Pattern.compile(Pattern.quote(what), Pattern.CASE_INSENSITIVE)
.matcher(src).find();
}
// The cached pattern for case 5
private static final Pattern P = Pattern.compile(
Pattern.quote("i am"), Pattern.CASE_INSENSITIVE);
// Case 5 with pre-cached Pattern
public static boolean containsIgnoreCaseRegexp(String src) {
return P.matcher(src).find();
}
// Main method: perfroms speed analysis on different contains methods
// (case ignored)
public static void main(String[] args) throws Exception {
final String src = "Hi, I am Adam";
final String what = "i am";
long start, end;
final int N = 10_000_000;
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCase(src, what);
end = System.nanoTime();
System.out.println("Case 1 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsConverting(src, what);
end = System.nanoTime();
System.out.println("Case 2 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsConverting(src);
end = System.nanoTime();
System.out.println("Case 3 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCaseRegexp(src, what);
end = System.nanoTime();
System.out.println("Case 4 took " + ((end - start) / 1000000) + "ms");
start = System.nanoTime();
for (int i = 0; i < N; i++)
containsIgnoreCaseRegexp(src);
end = System.nanoTime();
System.out.println("Case 5 took " + ((end - start) / 1000000) + "ms");
}
}
答案 4 :(得分:18)
更简单的方法(不用担心模式匹配)会将String
转换为小写:
String foobar = "fooBar";
String bar = "FOO";
if (foobar.toLowerCase().contains(bar.toLowerCase()) {
System.out.println("It's a match!");
}
答案 5 :(得分:16)
是的,这是可以实现的:
String s1 = "abBaCca";
String s2 = "bac";
String s1Lower = s1;
//s1Lower is exact same string, now convert it to lowercase, I left the s1 intact for print purposes if needed
s1Lower = s1Lower.toLowerCase();
String trueStatement = "FALSE!";
if (s1Lower.contains(s2)) {
//THIS statement will be TRUE
trueStatement = "TRUE!"
}
return trueStatement;
此代码将返回字符串“TRUE!”因为它发现你的角色被包含了。
答案 6 :(得分:6)
您可以使用regular expressions,它可以运作:
boolean found = s1.matches("(?i).*" + s2+ ".*");
答案 7 :(得分:3)
我做了一个测试,找到一个字符串不区分大小写的匹配项。我有一个150,000个对象的Vector,所有对象都有一个字符串作为一个字段,并希望找到匹配字符串的子集。我尝试了三种方法:
将全部转换为小写
for (SongInformation song: songs) {
if (song.artist.toLowerCase().indexOf(pattern.toLowercase() > -1) {
...
}
}
使用String matches()方法
for (SongInformation song: songs) {
if (song.artist.matches("(?i).*" + pattern + ".*")) {
...
}
}
使用正则表达式
Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher("");
for (SongInformation song: songs) {
m.reset(song.artist);
if (m.find()) {
...
}
}
时间结果是:
未尝试匹配:20 msecs
降低匹配:182 msecs
字符串匹配:278 msecs
正则表达式:65 msecs
对于这个用例,正则表达式看起来是最快的。
答案 8 :(得分:3)
如果您使用ICU4j,可以使用一些非常友好的Unicode。我想&#34;忽略案例&#34;对于方法名称是有问题的,因为虽然主要强度比较确实忽略了大小写,但它被描述为与区域设置相关的细节。但它有望以某种方式依赖于语言环境。
public static boolean containsIgnoreCase(String haystack, String needle) {
return indexOfIgnoreCase(haystack, needle) >= 0;
}
public static int indexOfIgnoreCase(String haystack, String needle) {
StringSearch stringSearch = new StringSearch(needle, haystack);
stringSearch.getCollator().setStrength(Collator.PRIMARY);
return stringSearch.first();
}
答案 9 :(得分:1)
使用 toLowerCase() 或 toUpperCase() 方法和测试将两个字符串转换为小写或大写的一种方法。
public class Sample {
public static void main(String args[]){
String str = "Hello Welcome to insensitive Container";
String test = "Java Testing";
Boolean bool = str.toLowerCase().contains(test.toLowerCase());
System.out.println(bool);
}
}
这是使用带有 CASE_INSENSITIVE 标志的 java.util.regex.Pattern 进行不区分大小写匹配的另一种方法。
Pattern.compile(Pattern.quote(s2), Pattern.CASE_INSENSITIVE).matcher(s1).find();
答案 10 :(得分:1)
"AbCd".toLowerCase().contains("abcD".toLowerCase())
答案 11 :(得分:1)
我不确定你的主要问题是什么,但是,.contains是区分大小写的。
答案 12 :(得分:0)
String container = " Case SeNsitive ";
String sub = "sen";
if (rcontains(container, sub)) {
System.out.println("no case");
}
public static Boolean rcontains(String container, String sub) {
Boolean b = false;
for (int a = 0; a < container.length() - sub.length() + 1; a++) {
//System.out.println(sub + " to " + container.substring(a, a+sub.length()));
if (sub.equalsIgnoreCase(container.substring(a, a + sub.length()))) {
b = true;
}
}
return b;
}
基本上,这是一个需要两个字符串的方法。它应该是contains()的不区分大小写的版本。使用contains方法时,您希望查看另一个字符串是否包含。
此方法接受字符串“sub”并检查它是否等于容器字符串的子字符串,其长度与“sub”相等。如果查看for
循环,您将看到它在容器字符串上的子字符串(即“sub”的长度)中进行迭代。
每次迭代检查容器字符串的子字符串是否为equalsIgnoreCase
。
答案 13 :(得分:0)
如果您必须在另一个ASCII字符串中搜索ASCII字符串,例如URL,您会发现我的解决方案更好。我已经测试了icza的方法和我的速度,结果如下:
代码:
public static String lowerCaseAscii(String s) {
if (s == null)
return null;
int len = s.length();
char[] buf = new char[len];
s.getChars(0, len, buf, 0);
for (int i=0; i<len; i++) {
if (buf[i] >= 'A' && buf[i] <= 'Z')
buf[i] += 0x20;
}
return new String(buf);
}
public static boolean containsIgnoreCaseAscii(String str, String searchStr) {
return StringUtils.contains(lowerCaseAscii(str), lowerCaseAscii(searchStr));
}
答案 14 :(得分:0)
:://Synchro.bat
:://SachaDee 2014
@echo off&cls
:: We set Folders to synchonized
set "Folders= C:\HackooTest E:\Backup\Folder1 E:\Backup\Folder2 E:\Backup\Folder3"
for %%a in (%Folders%) do (
for %%b in (%Folders%) do (
if not "%%a"=="%%b" (
set "VAR%%a%%b=%%a %%b"
)
)
)
for /f "tokens=2,3 delims== " %%a in ('set VAR') Do (
echo xcopy "%%a" "%%b" /E /D /C /Y /I
)
pause
答案 15 :(得分:0)
我们可以将流与anyMatch一起使用,并包含Java 8
public class Test2 {
public static void main(String[] args) {
String a = "Gina Gini Protijayi Soudipta";
String b = "Gini";
System.out.println(WordPresentOrNot(a, b));
}// main
private static boolean WordPresentOrNot(String a, String b) {
//contains is case sensitive. That's why change it to upper or lower case. Then check
// Here we are using stream with anyMatch
boolean match = Arrays.stream(a.toLowerCase().split(" ")).anyMatch(b.toLowerCase()::contains);
return match;
}
}
答案 16 :(得分:0)
使用regex标志(不区分大小写的{i}),有一种简单明了的方法:
String s1 = "hello abc efg";
String s2 = "ABC";
s1.matches(".*(?i)"+s2+".*");
/*
* .* denotes every character except line break
* (?i) denotes case insensitivity flag enabled for s2 (String)
* */
答案 17 :(得分:0)
或者您可以使用一种简单的方法,将字符串的大小写转换为子字符串的大小写,然后使用contains方法。
答案 18 :(得分:-1)
你可以简单地做这样的事情:
String s1 = "AbBaCca";
String s2 = "bac";
String toLower = s1.toLowerCase();
return toLower.contains(s2);
答案 19 :(得分:-1)
String x="abCd";
System.out.println(Pattern.compile("c",Pattern.CASE_INSENSITIVE).matcher(x).find());