From d776d2688968a3da89f050235819936fae1436ae Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Tue, 21 Oct 2003 23:23:06 +0000 Subject: [PATCH] Improve performance of BooleanUtils.toBoolean(String) git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@137686 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/commons/lang/BooleanUtils.java | 80 ++++++++++++++++--- .../apache/commons/lang/BooleanUtilsTest.java | 38 +++++++-- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/src/java/org/apache/commons/lang/BooleanUtils.java b/src/java/org/apache/commons/lang/BooleanUtils.java index 4b2a06fe1..14b160770 100644 --- a/src/java/org/apache/commons/lang/BooleanUtils.java +++ b/src/java/org/apache/commons/lang/BooleanUtils.java @@ -66,7 +66,7 @@ * @author Matthew Hawthorne * @author Gary Gregory * @since 2.0 - * @version $Id: BooleanUtils.java,v 1.16 2003/09/23 19:45:14 fredrik Exp $ + * @version $Id: BooleanUtils.java,v 1.17 2003/10/21 23:23:06 scolebourne Exp $ */ public class BooleanUtils { @@ -502,12 +502,14 @@ public static Integer toIntegerObject(Boolean bool, Integer trueValue, Integer f * Otherwise, null is returned.

* *
+     *   BooleanUtils.toBooleanObject(null)    = null
      *   BooleanUtils.toBooleanObject("true")  = Boolean.TRUE
      *   BooleanUtils.toBooleanObject("false") = Boolean.FALSE
      *   BooleanUtils.toBooleanObject("on")    = Boolean.TRUE
      *   BooleanUtils.toBooleanObject("ON")    = Boolean.TRUE
      *   BooleanUtils.toBooleanObject("off")   = Boolean.FALSE
      *   BooleanUtils.toBooleanObject("oFf")   = Boolean.FALSE
+     *   BooleanUtils.toBooleanObject("blue")  = null
      * 
* * @param str the String to check @@ -574,34 +576,94 @@ public static Boolean toBooleanObject(String str, String trueString, String fals // String to boolean methods //----------------------------------------------------------------------- /** - *

Converts a String to a boolean.

+ *

Converts a String to a boolean (optimised for performance).

* *

'true', 'on' or 'yes' * (case insensitive) will return true. Otherwise, * false is returned.

+ * + *

This method performs 4 times faster (JDK1.4) than + * Boolean.valueOf(String). However, this method accepts + * 'on' and 'yes' as true values. * *

+     *   BooleanUtils.toBoolean(null)    = false
      *   BooleanUtils.toBoolean("true")  = true
+     *   BooleanUtils.toBoolean("TRUE")  = true
+     *   BooleanUtils.toBoolean("tRUe")  = true
      *   BooleanUtils.toBoolean("on")    = true
      *   BooleanUtils.toBoolean("yes")   = true
      *   BooleanUtils.toBoolean("false") = false
+     *   BooleanUtils.toBoolean("x gti") = false
      * 
* * @param str the String to check * @return the boolean value of the string, false if no match */ public static boolean toBoolean(String str) { - if ("true".equalsIgnoreCase(str)) { - return true; - } else if ("on".equalsIgnoreCase(str)) { - return true; - } else if ("yes".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 true; } - // no match + 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'); + } + } + 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; } - + +// public static void main(String[] args) { +// long start = System.currentTimeMillis(); +// boolean flag = true; +// int count = 0; +// for (int i = 0; i < 100000000; i++) { +// flag = toBoolean("YES"); +// } +// long end = System.currentTimeMillis(); +// System.out.println((end - start) + " " + flag + " " + count); +// } + /** *

Converts a String to a Boolean throwing an exception if no match found.

* diff --git a/src/test/org/apache/commons/lang/BooleanUtilsTest.java b/src/test/org/apache/commons/lang/BooleanUtilsTest.java index c2db56e5b..ee35b6847 100644 --- a/src/test/org/apache/commons/lang/BooleanUtilsTest.java +++ b/src/test/org/apache/commons/lang/BooleanUtilsTest.java @@ -66,7 +66,7 @@ * * @author Stephen Colebourne * @author Matthew Hawthorne - * @version $Id: BooleanUtilsTest.java,v 1.7 2003/08/18 02:22:25 bayard Exp $ + * @version $Id: BooleanUtilsTest.java,v 1.8 2003/10/21 23:23:06 scolebourne Exp $ */ public class BooleanUtilsTest extends TestCase { @@ -308,13 +308,39 @@ public void test_toBoolean_String() { assertEquals(false, BooleanUtils.toBoolean("")); assertEquals(false, BooleanUtils.toBoolean("off")); assertEquals(false, BooleanUtils.toBoolean("oof")); - assertEquals(true, BooleanUtils.toBoolean("true")); - assertEquals(true, BooleanUtils.toBoolean("yes")); - assertEquals(true, BooleanUtils.toBoolean("on")); + assertEquals(false, BooleanUtils.toBoolean("yep")); + assertEquals(false, BooleanUtils.toBoolean("trux")); + assertEquals(false, BooleanUtils.toBoolean("false")); + assertEquals(false, BooleanUtils.toBoolean("a")); + assertEquals(true, BooleanUtils.toBoolean("true")); // interned handled differently + assertEquals(true, BooleanUtils.toBoolean(new StringBuffer("tr").append("ue").toString())); + assertEquals(true, BooleanUtils.toBoolean("truE")); + assertEquals(true, BooleanUtils.toBoolean("trUe")); + assertEquals(true, BooleanUtils.toBoolean("trUE")); + assertEquals(true, BooleanUtils.toBoolean("tRue")); + assertEquals(true, BooleanUtils.toBoolean("tRuE")); + assertEquals(true, BooleanUtils.toBoolean("tRUe")); + assertEquals(true, BooleanUtils.toBoolean("tRUE")); assertEquals(true, BooleanUtils.toBoolean("TRUE")); - assertEquals(true, BooleanUtils.toBoolean("ON")); - assertEquals(true, BooleanUtils.toBoolean("YES")); + assertEquals(true, BooleanUtils.toBoolean("TRUe")); + assertEquals(true, BooleanUtils.toBoolean("TRuE")); + assertEquals(true, BooleanUtils.toBoolean("TRue")); + assertEquals(true, BooleanUtils.toBoolean("TrUE")); + assertEquals(true, BooleanUtils.toBoolean("TrUe")); assertEquals(true, BooleanUtils.toBoolean("TruE")); + assertEquals(true, BooleanUtils.toBoolean("True")); + assertEquals(true, BooleanUtils.toBoolean("on")); + assertEquals(true, BooleanUtils.toBoolean("oN")); + assertEquals(true, BooleanUtils.toBoolean("On")); + assertEquals(true, BooleanUtils.toBoolean("ON")); + assertEquals(true, BooleanUtils.toBoolean("yes")); + assertEquals(true, BooleanUtils.toBoolean("yeS")); + assertEquals(true, BooleanUtils.toBoolean("yEs")); + assertEquals(true, BooleanUtils.toBoolean("yES")); + assertEquals(true, BooleanUtils.toBoolean("Yes")); + assertEquals(true, BooleanUtils.toBoolean("YeS")); + assertEquals(true, BooleanUtils.toBoolean("YEs")); + assertEquals(true, BooleanUtils.toBoolean("YES")); } public void test_toBoolean_String_String_String() {