Browse Source

Avoid temporary String creation in StringUtils.starts/endsWithIgnoreCase

Issue: SPR-16095
pull/1582/head
Juergen Hoeller 8 years ago
parent
commit
99d39eb2ee
  1. 63
      spring-core/src/main/java/org/springframework/util/StringUtils.java
  2. 116
      spring-core/src/test/java/org/springframework/util/StringUtilsTests.java

63
spring-core/src/main/java/org/springframework/util/StringUtils.java

@ -135,17 +135,7 @@ public abstract class StringUtils { @@ -135,17 +135,7 @@ public abstract class StringUtils {
* @see Character#isWhitespace
*/
public static boolean hasText(CharSequence str) {
if (!hasLength(str)) {
return false;
}
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
return (hasLength(str) && containsText(str));
}
/**
@ -159,7 +149,17 @@ public abstract class StringUtils { @@ -159,7 +149,17 @@ public abstract class StringUtils {
* @see #hasText(CharSequence)
*/
public static boolean hasText(String str) {
return (str != null && !str.isEmpty() && hasText((CharSequence) str));
return (hasLength(str) && containsText(str));
}
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
/**
@ -310,7 +310,6 @@ public abstract class StringUtils { @@ -310,7 +310,6 @@ public abstract class StringUtils {
return sb.toString();
}
/**
* Test if the given {@code String} starts with the specified prefix,
* ignoring upper/lower case.
@ -319,19 +318,8 @@ public abstract class StringUtils { @@ -319,19 +318,8 @@ public abstract class StringUtils {
* @see java.lang.String#startsWith
*/
public static boolean startsWithIgnoreCase(String str, String prefix) {
if (str == null || prefix == null) {
return false;
}
if (str.startsWith(prefix)) {
return true;
}
if (str.length() < prefix.length()) {
return false;
}
String lcStr = str.substring(0, prefix.length()).toLowerCase();
String lcPrefix = prefix.toLowerCase();
return lcStr.equals(lcPrefix);
return (str != null && prefix != null && str.length() >= prefix.length() &&
str.regionMatches(true, 0, prefix, 0, prefix.length()));
}
/**
@ -342,19 +330,8 @@ public abstract class StringUtils { @@ -342,19 +330,8 @@ public abstract class StringUtils {
* @see java.lang.String#endsWith
*/
public static boolean endsWithIgnoreCase(String str, String suffix) {
if (str == null || suffix == null) {
return false;
}
if (str.endsWith(suffix)) {
return true;
}
if (str.length() < suffix.length()) {
return false;
}
String lcStr = str.substring(str.length() - suffix.length()).toLowerCase();
String lcSuffix = suffix.toLowerCase();
return lcStr.equals(lcSuffix);
return (str != null && suffix != null && str.length() >= suffix.length() &&
str.regionMatches(true, str.length() - suffix.length(), suffix, 0, suffix.length()));
}
/**
@ -365,9 +342,11 @@ public abstract class StringUtils { @@ -365,9 +342,11 @@ public abstract class StringUtils {
* @param substring the substring to match at the given index
*/
public static boolean substringMatch(CharSequence str, int index, CharSequence substring) {
for (int j = 0; j < substring.length(); j++) {
int i = index + j;
if (i >= str.length() || str.charAt(i) != substring.charAt(j)) {
if (index + substring.length() > str.length()) {
return false;
}
for (int i = 0; i < substring.length(); i++) {
if (str.charAt(index + i) != substring.charAt(i)) {
return false;
}
}

116
spring-core/src/test/java/org/springframework/util/StringUtilsTests.java

@ -32,24 +32,24 @@ import static org.junit.Assert.*; @@ -32,24 +32,24 @@ import static org.junit.Assert.*;
public class StringUtilsTests {
@Test
public void testHasTextBlank() throws Exception {
public void testHasTextBlank() {
String blank = " ";
assertEquals(false, StringUtils.hasText(blank));
}
@Test
public void testHasTextNullEmpty() throws Exception {
public void testHasTextNullEmpty() {
assertEquals(false, StringUtils.hasText(null));
assertEquals(false, StringUtils.hasText(""));
}
@Test
public void testHasTextValid() throws Exception {
public void testHasTextValid() {
assertEquals(true, StringUtils.hasText("t"));
}
@Test
public void testContainsWhitespace() throws Exception {
public void testContainsWhitespace() {
assertFalse(StringUtils.containsWhitespace(null));
assertFalse(StringUtils.containsWhitespace(""));
assertFalse(StringUtils.containsWhitespace("a"));
@ -62,7 +62,7 @@ public class StringUtilsTests { @@ -62,7 +62,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimWhitespace() throws Exception {
public void testTrimWhitespace() {
assertEquals(null, StringUtils.trimWhitespace(null));
assertEquals("", StringUtils.trimWhitespace(""));
assertEquals("", StringUtils.trimWhitespace(" "));
@ -75,7 +75,7 @@ public class StringUtilsTests { @@ -75,7 +75,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimAllWhitespace() throws Exception {
public void testTrimAllWhitespace() {
assertEquals("", StringUtils.trimAllWhitespace(""));
assertEquals("", StringUtils.trimAllWhitespace(" "));
assertEquals("", StringUtils.trimAllWhitespace("\t"));
@ -87,7 +87,7 @@ public class StringUtilsTests { @@ -87,7 +87,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimLeadingWhitespace() throws Exception {
public void testTrimLeadingWhitespace() {
assertEquals(null, StringUtils.trimLeadingWhitespace(null));
assertEquals("", StringUtils.trimLeadingWhitespace(""));
assertEquals("", StringUtils.trimLeadingWhitespace(" "));
@ -100,7 +100,7 @@ public class StringUtilsTests { @@ -100,7 +100,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimTrailingWhitespace() throws Exception {
public void testTrimTrailingWhitespace() {
assertEquals(null, StringUtils.trimTrailingWhitespace(null));
assertEquals("", StringUtils.trimTrailingWhitespace(""));
assertEquals("", StringUtils.trimTrailingWhitespace(" "));
@ -113,7 +113,7 @@ public class StringUtilsTests { @@ -113,7 +113,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimLeadingCharacter() throws Exception {
public void testTrimLeadingCharacter() {
assertEquals(null, StringUtils.trimLeadingCharacter(null, ' '));
assertEquals("", StringUtils.trimLeadingCharacter("", ' '));
assertEquals("", StringUtils.trimLeadingCharacter(" ", ' '));
@ -126,7 +126,7 @@ public class StringUtilsTests { @@ -126,7 +126,7 @@ public class StringUtilsTests {
}
@Test
public void testTrimTrailingCharacter() throws Exception {
public void testTrimTrailingCharacter() {
assertEquals(null, StringUtils.trimTrailingCharacter(null, ' '));
assertEquals("", StringUtils.trimTrailingCharacter("", ' '));
assertEquals("", StringUtils.trimTrailingCharacter(" ", ' '));
@ -138,6 +138,60 @@ public class StringUtilsTests { @@ -138,6 +138,60 @@ public class StringUtilsTests {
assertEquals(" a b c", StringUtils.trimTrailingCharacter(" a b c ", ' '));
}
@Test
public void testStartsWithIgnoreCase() {
String prefix = "fOo";
assertTrue(StringUtils.startsWithIgnoreCase("foo", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("Foo", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("foobar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("foobarbar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("Foobar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("FoobarBar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("foObar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("FOObar", prefix));
assertTrue(StringUtils.startsWithIgnoreCase("fOobar", prefix));
assertFalse(StringUtils.startsWithIgnoreCase(null, prefix));
assertFalse(StringUtils.startsWithIgnoreCase("fOobar", null));
assertFalse(StringUtils.startsWithIgnoreCase("b", prefix));
assertFalse(StringUtils.startsWithIgnoreCase("barfoo", prefix));
assertFalse(StringUtils.startsWithIgnoreCase("barfoobar", prefix));
}
@Test
public void testEndsWithIgnoreCase() {
String suffix = "fOo";
assertTrue(StringUtils.endsWithIgnoreCase("foo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("Foo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barbarfoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barFoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barBarFoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfoO", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barFOO", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfOo", suffix));
assertFalse(StringUtils.endsWithIgnoreCase(null, suffix));
assertFalse(StringUtils.endsWithIgnoreCase("barfOo", null));
assertFalse(StringUtils.endsWithIgnoreCase("b", suffix));
assertFalse(StringUtils.endsWithIgnoreCase("foobar", suffix));
assertFalse(StringUtils.endsWithIgnoreCase("barfoobar", suffix));
}
@Test
public void testSubstringMatch() {
assertTrue(StringUtils.substringMatch("foo", 0, "foo"));
assertTrue(StringUtils.substringMatch("foo", 1, "oo"));
assertTrue(StringUtils.substringMatch("foo", 2, "o"));
assertFalse(StringUtils.substringMatch("foo", 0, "fOo"));
assertFalse(StringUtils.substringMatch("foo", 1, "fOo"));
assertFalse(StringUtils.substringMatch("foo", 2, "fOo"));
assertFalse(StringUtils.substringMatch("foo", 3, "fOo"));
assertFalse(StringUtils.substringMatch("foo", 1, "Oo"));
assertFalse(StringUtils.substringMatch("foo", 2, "Oo"));
assertFalse(StringUtils.substringMatch("foo", 3, "Oo"));
assertFalse(StringUtils.substringMatch("foo", 2, "O"));
assertFalse(StringUtils.substringMatch("foo", 3, "O"));
}
@Test
public void testCountOccurrencesOf() {
assertTrue("nullx2 = 0",
@ -166,7 +220,7 @@ public class StringUtilsTests { @@ -166,7 +220,7 @@ public class StringUtilsTests {
}
@Test
public void testReplace() throws Exception {
public void testReplace() {
String inString = "a6AazAaa77abaa";
String oldPattern = "aa";
String newPattern = "foo";
@ -189,7 +243,7 @@ public class StringUtilsTests { @@ -189,7 +243,7 @@ public class StringUtilsTests {
}
@Test
public void testDelete() throws Exception {
public void testDelete() {
String inString = "The quick brown fox jumped over the lazy dog";
String noThe = StringUtils.delete(inString, "the");
@ -216,7 +270,7 @@ public class StringUtilsTests { @@ -216,7 +270,7 @@ public class StringUtilsTests {
}
@Test
public void testDeleteAny() throws Exception {
public void testDeleteAny() {
String inString = "Able was I ere I saw Elba";
String res = StringUtils.deleteAny(inString, "I");
@ -301,7 +355,6 @@ public class StringUtilsTests { @@ -301,7 +355,6 @@ public class StringUtilsTests {
@Test
public void testStripFilenameExtension() {
assertEquals(null, StringUtils.stripFilenameExtension(null));
assertEquals("", StringUtils.stripFilenameExtension(""));
assertEquals("myfile", StringUtils.stripFilenameExtension("myfile"));
assertEquals("myfile", StringUtils.stripFilenameExtension("myfile."));
@ -580,26 +633,9 @@ public class StringUtilsTests { @@ -580,26 +633,9 @@ public class StringUtilsTests {
assertTrue("Output equals input", Arrays.equals(sa, components));
}
@Test
public void testEndsWithIgnoreCase() {
String suffix = "fOo";
assertTrue(StringUtils.endsWithIgnoreCase("foo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("Foo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barbarfoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barFoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barBarFoo", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfoO", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barFOO", suffix));
assertTrue(StringUtils.endsWithIgnoreCase("barfOo", suffix));
assertFalse(StringUtils.endsWithIgnoreCase(null, suffix));
assertFalse(StringUtils.endsWithIgnoreCase("barfOo", null));
assertFalse(StringUtils.endsWithIgnoreCase("b", suffix));
}
@Test
public void testParseLocaleStringSunnyDay() throws Exception {
public void testParseLocaleStringSunnyDay() {
Locale expectedLocale = Locale.UK;
Locale locale = StringUtils.parseLocaleString(expectedLocale.toString());
assertNotNull("When given a bona-fide Locale string, must not return null.", locale);
@ -607,19 +643,19 @@ public class StringUtilsTests { @@ -607,19 +643,19 @@ public class StringUtilsTests {
}
@Test
public void testParseLocaleStringWithMalformedLocaleString() throws Exception {
public void testParseLocaleStringWithMalformedLocaleString() {
Locale locale = StringUtils.parseLocaleString("_banjo_on_my_knee");
assertNotNull("When given a malformed Locale string, must not return null.", locale);
}
@Test
public void testParseLocaleStringWithEmptyLocaleStringYieldsNullLocale() throws Exception {
public void testParseLocaleStringWithEmptyLocaleStringYieldsNullLocale() {
Locale locale = StringUtils.parseLocaleString("");
assertNull("When given an empty Locale string, must return null.", locale);
}
@Test // SPR-8637
public void testParseLocaleWithMultiSpecialCharactersInVariant() throws Exception {
public void testParseLocaleWithMultiSpecialCharactersInVariant() {
String variant = "proper-northern";
String localeString = "en_GB_" + variant;
Locale locale = StringUtils.parseLocaleString(localeString);
@ -627,7 +663,7 @@ public class StringUtilsTests { @@ -627,7 +663,7 @@ public class StringUtilsTests {
}
@Test // SPR-3671
public void testParseLocaleWithMultiValuedVariant() throws Exception {
public void testParseLocaleWithMultiValuedVariant() {
String variant = "proper_northern";
String localeString = "en_GB_" + variant;
Locale locale = StringUtils.parseLocaleString(localeString);
@ -635,7 +671,7 @@ public class StringUtilsTests { @@ -635,7 +671,7 @@ public class StringUtilsTests {
}
@Test // SPR-3671
public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparators() throws Exception {
public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparators() {
String variant = "proper northern";
String localeString = "en GB " + variant;
Locale locale = StringUtils.parseLocaleString(localeString);
@ -643,7 +679,7 @@ public class StringUtilsTests { @@ -643,7 +679,7 @@ public class StringUtilsTests {
}
@Test // SPR-3671
public void testParseLocaleWithMultiValuedVariantUsingMixtureOfUnderscoresAndSpacesAsSeparators() throws Exception {
public void testParseLocaleWithMultiValuedVariantUsingMixtureOfUnderscoresAndSpacesAsSeparators() {
String variant = "proper northern";
String localeString = "en_GB_" + variant;
Locale locale = StringUtils.parseLocaleString(localeString);
@ -651,7 +687,7 @@ public class StringUtilsTests { @@ -651,7 +687,7 @@ public class StringUtilsTests {
}
@Test // SPR-3671
public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
public void testParseLocaleWithMultiValuedVariantUsingSpacesAsSeparatorsWithLotsOfLeadingWhitespace() {
String variant = "proper northern";
String localeString = "en GB " + variant; // lots of whitespace
Locale locale = StringUtils.parseLocaleString(localeString);
@ -659,7 +695,7 @@ public class StringUtilsTests { @@ -659,7 +695,7 @@ public class StringUtilsTests {
}
@Test // SPR-3671
public void testParseLocaleWithMultiValuedVariantUsingUnderscoresAsSeparatorsWithLotsOfLeadingWhitespace() throws Exception {
public void testParseLocaleWithMultiValuedVariantUsingUnderscoresAsSeparatorsWithLotsOfLeadingWhitespace() {
String variant = "proper_northern";
String localeString = "en_GB_____" + variant; // lots of underscores
Locale locale = StringUtils.parseLocaleString(localeString);

Loading…
Cancel
Save