Refactoring toBoolean(String) and toBooleanObject(String) so that the latter has the same optimizations. I did this by pointing the former to the latter. I had to rewrite the optimizations a bit so they didn't auto-return as the latter considers null and false to be different. I also had to add specific support for false, no and off for the same reason. LANG-633

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@965963 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Henri Yandell 2010-07-20 19:10:34 +00:00
parent 731c0040fe
commit d482154d50
2 changed files with 84 additions and 63 deletions

View File

@ -544,20 +544,84 @@ public class BooleanUtils {
* <code>null</code> if no match or <code>null</code> input
*/
public static Boolean toBooleanObject(String str) {
if ("true".equalsIgnoreCase(str)) {
// Previously used equalsIgnoreCase, which was fast for interned 'true'.
// Non interned 'true' matched 15 times slower.
//
// Optimisation provides same performance as before for interned 'true'.
// Similar performance for null, 'false', and other strings not length 2/3/4.
// 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
if (str == "true") {
return Boolean.TRUE;
} else if ("false".equalsIgnoreCase(str)) {
return Boolean.FALSE;
} else if ("on".equalsIgnoreCase(str)) {
return Boolean.TRUE;
} else if ("off".equalsIgnoreCase(str)) {
return Boolean.FALSE;
} else if ("yes".equalsIgnoreCase(str)) {
return Boolean.TRUE;
} else if ("no".equalsIgnoreCase(str)) {
return Boolean.FALSE;
}
// no match
if (str == null) {
return null;
}
switch (str.length()) {
case 2: {
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
if ((ch0 == 'o' || ch0 == 'O') &&
(ch1 == 'n' || ch1 == 'N') )
{
return true;
}
if ((ch0 == 'n' || ch0 == 'N') &&
(ch1 == 'o' || ch1 == 'O') )
{
return false;
}
break;
}
case 3: {
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
char ch2 = str.charAt(2);
if ((ch0 == 'y' || ch0 == 'Y') &&
(ch1 == 'e' || ch1 == 'E') &&
(ch2 == 's' || ch2 == 'S') )
{
return true;
}
if ((ch0 == 'o' || ch0 == 'O') &&
(ch1 == 'f' || ch1 == 'F') &&
(ch2 == 'f' || ch2 == 'F') )
{
return false;
}
break;
}
case 4: {
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
char ch2 = str.charAt(2);
char ch3 = str.charAt(3);
if ((ch0 == 't' || ch0 == 'T') &&
(ch1 == 'r' || ch1 == 'R') &&
(ch2 == 'u' || ch2 == 'U') &&
(ch3 == 'e' || ch3 == 'E') )
{
return true;
}
break;
}
case 5: {
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
char ch2 = str.charAt(2);
char ch3 = str.charAt(3);
char ch4 = str.charAt(4);
if ((ch0 == 'f' || ch0 == 'F') &&
(ch1 == 'a' || ch1 == 'A') &&
(ch2 == 'l' || ch2 == 'L') &&
(ch3 == 's' || ch3 == 'S') &&
(ch4 == 'e' || ch4 == 'E') )
{
return false;
}
break;
}
}
return null;
}
@ -631,57 +695,7 @@ public class BooleanUtils {
* @return the boolean value of the string, <code>false</code> if no match
*/
public static boolean toBoolean(String str) {
// Previously used equalsIgnoreCase, which was fast for interned 'true'.
// Non interned 'true' matched 15 times slower.
//
// Optimisation provides same performance as before for interned 'true'.
// Similar performance for null, 'false', and other strings not length 2/3/4.
// 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
if (str == "true") {
return true;
}
if (str == null) {
return false;
}
switch (str.length()) {
case 2: {
char ch0 = str.charAt(0);
char ch1 = str.charAt(1);
return
(ch0 == 'o' || ch0 == 'O') &&
(ch1 == 'n' || ch1 == 'N');
}
case 3: {
char ch = str.charAt(0);
if (ch == 'y') {
return
(str.charAt(1) == 'e' || str.charAt(1) == 'E') &&
(str.charAt(2) == 's' || str.charAt(2) == 'S');
}
if (ch == 'Y') {
return
(str.charAt(1) == 'E' || str.charAt(1) == 'e') &&
(str.charAt(2) == 'S' || str.charAt(2) == 's');
}
return false;
}
case 4: {
char ch = str.charAt(0);
if (ch == 't') {
return
(str.charAt(1) == 'r' || str.charAt(1) == 'R') &&
(str.charAt(2) == 'u' || str.charAt(2) == 'U') &&
(str.charAt(3) == 'e' || str.charAt(3) == 'E');
}
if (ch == 'T') {
return
(str.charAt(1) == 'R' || str.charAt(1) == 'r') &&
(str.charAt(2) == 'U' || str.charAt(2) == 'u') &&
(str.charAt(3) == 'E' || str.charAt(3) == 'e');
}
}
}
return false;
return toBooleanObject(str) == Boolean.TRUE;
}
/**

View File

@ -241,6 +241,9 @@ public class BooleanUtilsTest extends TestCase {
assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("ON"));
assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("YES"));
assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("TruE"));
assertEquals(null, BooleanUtils.toBooleanObject("ab"));
assertEquals(null, BooleanUtils.toBooleanObject("yoo"));
}
public void test_toBooleanObject_String_String_String_String() {
@ -306,6 +309,10 @@ public class BooleanUtilsTest extends TestCase {
assertEquals(true, BooleanUtils.toBoolean("YES"));
assertEquals(false, BooleanUtils.toBoolean("yes?"));
assertEquals(false, BooleanUtils.toBoolean("tru"));
assertEquals(false, BooleanUtils.toBoolean("no"));
assertEquals(false, BooleanUtils.toBoolean("off"));
assertEquals(false, BooleanUtils.toBoolean("yoo"));
}
public void test_toBoolean_String_String_String() {