indexOf Case Sensitive?
indexof(string)方法是否区分大小写?如果有,是否有不区分大小写的版本?
Is the indexOf(String) method case sensitive?
是的,区分大小写:
1 2 3 4 5 | @Test public void indexOfIsCaseSensitive() { assertTrue("Hello World!".indexOf("Hello") != -1); assertTrue("Hello World!".indexOf("hello") == -1); } |
If so, is there a case insensitive version of it?
不,没有。在调用indexof之前,可以将两个字符串都转换为小写:
1 2 3 4 5 | @Test public void caseInsensitiveIndexOf() { assertTrue("Hello World!".toLowerCase().indexOf("Hello".toLowerCase()) != -1); assertTrue("Hello World!".toLowerCase().indexOf("hello".toLowerCase()) != -1); } |
Apache Commons Lang库的StringUtils类中有一个ignore case方法
indexofignorecase(charsequence str、charsequence searchstr)
是的,
我发现最好的解决案例不敏感的方法是:
1 2 |
这将导致不区分大小写的
这里是我的解决方案,它不分配任何堆内存,因此它应该比这里提到的大多数其他实现快得多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public static int indexOfIgnoreCase(final String haystack, final String needle) { if (needle.isEmpty() || haystack.isEmpty()) { // Fallback to legacy behavior. return haystack.indexOf(needle); } for (int i = 0; i < haystack.length(); ++i) { // Early out, if possible. if (i + needle.length() > haystack.length()) { return -1; } // Attempt to match substring starting at position i of haystack. int j = 0; int ii = i; while (ii < haystack.length() && j < needle.length()) { char c = Character.toLowerCase(haystack.charAt(ii)); char c2 = Character.toLowerCase(needle.charAt(j)); if (c != c2) { break; } j++; ii++; } // Walked all the way to the end of the needle, return the start // position that this was found. if (j == needle.length()) { return i; } } return -1; } |
下面是验证正确行为的单元测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Test public void testIndexOfIgnoreCase() { assertThat(StringUtils.indexOfIgnoreCase("A","A"), is(0)); assertThat(StringUtils.indexOfIgnoreCase("a","A"), is(0)); assertThat(StringUtils.indexOfIgnoreCase("A","a"), is(0)); assertThat(StringUtils.indexOfIgnoreCase("a","a"), is(0)); assertThat(StringUtils.indexOfIgnoreCase("a","ba"), is(-1)); assertThat(StringUtils.indexOfIgnoreCase("ba","a"), is(1)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue"," Royal Blue"), is(-1)); assertThat(StringUtils.indexOfIgnoreCase(" Royal Blue","Royal Blue"), is(1)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","royal"), is(0)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","oyal"), is(1)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","al"), is(3)); assertThat(StringUtils.indexOfIgnoreCase("","royal"), is(-1)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue",""), is(0)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","BLUE"), is(6)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","BIGLONGSTRING"), is(-1)); assertThat(StringUtils.indexOfIgnoreCase("Royal Blue","Royal Blue LONGSTRING"), is(-1)); } |
是的,区分大小写。通过在搜索之前将字符串和字符串参数都转换为大写,可以执行不区分大小写的
1 2 3 |
请注意,在某些情况下,touppercase可能不起作用。例如:
1 2 3 4 |
IDXU将是20岁,这是错误的!IDXL将是19,这是正确的。导致问题的原因是tha touppercase()转换"?"将字符分为两个字符,"ss",这将取消索引。
因此,请始终使用Tolowercase()。
返回索引值后,您在做什么?
如果您使用它来操作字符串,那么您是否可以不使用正则表达式来代替它?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import static org.junit.Assert.assertEquals; import org.junit.Test; public class StringIndexOfRegexpTest { @Test public void testNastyIndexOfBasedReplace() { final String source ="Hello World"; final int index = source.toLowerCase().indexOf("hello".toLowerCase()); final String target ="Hi".concat(source.substring(index +"hello".length(), source.length())); assertEquals("Hi World", target); } @Test public void testSimpleRegexpBasedReplace() { final String source ="Hello World"; final String target = source.replaceFirst("(?i)hello","Hi"); assertEquals("Hi World", target); } } |
有同样的问题。我尝试了正则表达式和apache stringutils.indexofignorecase-method,但两者都非常慢…所以我自己写了一个简短的方法…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public static int indexOfIgnoreCase(final String chkstr, final String searchStr, int i) { if (chkstr != null && searchStr != null && i > -1) { int serchStrLength = searchStr.length(); char[] searchCharLc = new char[serchStrLength]; char[] searchCharUc = new char[serchStrLength]; searchStr.toUpperCase().getChars(0, serchStrLength, searchCharUc, 0); searchStr.toLowerCase().getChars(0, serchStrLength, searchCharLc, 0); int j = 0; for (int checkStrLength = chkstr.length(); i < checkStrLength; i++) { char charAt = chkstr.charAt(i); if (charAt == searchCharLc[j] || charAt == searchCharUc[j]) { if (++j == serchStrLength) { return i - j + 1; } } else { // faster than: else if (j != 0) { i = i - j; j = 0; } } } return -1; } |
根据我的测试,它更快…(至少如果您的搜索字符串比较短)。如果你有任何改进或错误的建议,最好告诉我…(因为我在应用程序中使用了此代码;-)
综上所述,3个解决方案:
- 使用tolowercase()或touppercase
- 使用Apache的StringUtils
- 使用正则表达式
现在,我想知道哪一个是最快的?我猜平均来说是第一个。
1 2 3 4 | @Test public void testIndexofCaseSensitive() { TestCase.assertEquals(-1,"abcDef".indexOf("d") ); } |
我刚看过资料来源。它比较字符,因此区分大小写。
是的,我相当肯定。使用标准库的一种方法是:
1 | int index = str.toUpperCase().indexOf("FOO"); |
第一个问题已经回答了很多次。是的,
如果您需要区分区域设置的
1 2 3 4 5 6 7 8 9 10 | private int indexOf(String original, String search) { Collator collator = Collator.getInstance(); collator.setStrength(Collator.PRIMARY); for (int i = 0; i <= original.length() - search.length(); i++) { if (collator.equals(search, original.substring(i, i + search.length()))) { return i; } } return -1; } |
但写一本并不难:
1 2 3 4 5 6 7 8 9 | public class CaseInsensitiveIndexOfTest extends TestCase { public void testOne() throws Exception { assertEquals(2, caseInsensitiveIndexOf("ABC","xxabcdef")); } public static int caseInsensitiveIndexOf(String substring, String string) { return string.toLowerCase().indexOf(substring.toLowerCase()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | static string Search(string factMessage, string b) { int index = factMessage.IndexOf(b, StringComparison.CurrentCultureIgnoreCase); string line = null; int i = index; if (i == -1) { return"not matched"; } else { while (factMessage[i] != ' ') { line = line + factMessage[i]; i++; } return line; } } |
将两个字符串都转换为小写通常不是什么大问题,但如果其中一些字符串较长,则速度会很慢。如果你在一个循环中这样做的话,那将是非常糟糕的。出于这个原因,我建议使用
indexof区分大小写。这是因为它使用equals方法比较列表中的元素。对于contains和remove,也是这样。