• java开发_org.apache.commons.lang.StringUtils工具类源码


    在之前写了一篇关于""和null区别的文章。

    下面是文章的地址:

    http://www.cnblogs.com/hongten/archive/2012/11/08/java_null.html

    下面看看org.apache.commons.lang.StringUtils工具类源码

       1 /*
       2  * Licensed to the Apache Software Foundation (ASF) under one or more
       3  * contributor license agreements.  See the NOTICE file distributed with
       4  * this work for additional information regarding copyright ownership.
       5  * The ASF licenses this file to You under the Apache License, Version 2.0
       6  * (the "License"); you may not use this file except in compliance with
       7  * the License.  You may obtain a copy of the License at
       8  * 
       9  *      http://www.apache.org/licenses/LICENSE-2.0
      10  * 
      11  * Unless required by applicable law or agreed to in writing, software
      12  * distributed under the License is distributed on an "AS IS" BASIS,
      13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14  * See the License for the specific language governing permissions and
      15  * limitations under the License.
      16  */
      17 package org.apache.commons.lang;
      18 
      19 import java.util.ArrayList;
      20 import java.util.Collection;
      21 import java.util.Iterator;
      22 import java.util.List;
      23 import java.util.Locale;
      24 
      25 import org.apache.commons.lang.text.StrBuilder;
      26 
      27 /**
      28  * <p>Operations on {@link java.lang.String} that are
      29  * <code>null</code> safe.</p>
      30  *
      31  * <ul>
      32  *  <li><b>IsEmpty/IsBlank</b>
      33  *      - checks if a String contains text</li>
      34  *  <li><b>Trim/Strip</b>
      35  *      - removes leading and trailing whitespace</li>
      36  *  <li><b>Equals</b>
      37  *      - compares two strings null-safe</li>
      38  *  <li><b>startsWith</b>
      39  *      - check if a String starts with a prefix null-safe</li>
      40  *  <li><b>endsWith</b>
      41  *      - check if a String ends with a suffix null-safe</li>
      42  *  <li><b>IndexOf/LastIndexOf/Contains</b>
      43  *      - null-safe index-of checks
      44  *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
      45  *      - index-of any of a set of Strings</li>
      46  *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
      47  *      - does String contains only/none/any of these characters</li>
      48  *  <li><b>Substring/Left/Right/Mid</b>
      49  *      - null-safe substring extractions</li>
      50  *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
      51  *      - substring extraction relative to other strings</li>
      52  *  <li><b>Split/Join</b>
      53  *      - splits a String into an array of substrings and vice versa</li>
      54  *  <li><b>Remove/Delete</b>
      55  *      - removes part of a String</li>
      56  *  <li><b>Replace/Overlay</b>
      57  *      - Searches a String and replaces one String with another</li>
      58  *  <li><b>Chomp/Chop</b>
      59  *      - removes the last part of a String</li>
      60  *  <li><b>LeftPad/RightPad/Center/Repeat</b>
      61  *      - pads a String</li>
      62  *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
      63  *      - changes the case of a String</li>
      64  *  <li><b>CountMatches</b>
      65  *      - counts the number of occurrences of one String in another</li>
      66  *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
      67  *      - checks the characters in a String</li>
      68  *  <li><b>DefaultString</b>
      69  *      - protects against a null input String</li>
      70  *  <li><b>Reverse/ReverseDelimited</b>
      71  *      - reverses a String</li>
      72  *  <li><b>Abbreviate</b>
      73  *      - abbreviates a string using ellipsis</li>
      74  *  <li><b>Difference</b>
      75  *      - compares Strings and reports on their differences</li>
      76  *  <li><b>LevensteinDistance</b>
      77  *      - the number of changes needed to change one String into another</li>
      78  * </ul>
      79  *
      80  * <p>The <code>StringUtils</code> class defines certain words related to
      81  * String handling.</p>
      82  *
      83  * <ul>
      84  *  <li>null - <code>null</code></li>
      85  *  <li>empty - a zero-length string (<code>""</code>)</li>
      86  *  <li>space - the space character (<code>' '</code>, char 32)</li>
      87  *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
      88  *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
      89  * </ul>
      90  *
      91  * <p><code>StringUtils</code> handles <code>null</code> input Strings quietly.
      92  * That is to say that a <code>null</code> input will return <code>null</code>.
      93  * Where a <code>boolean</code> or <code>int</code> is being returned
      94  * details vary by method.</p>
      95  *
      96  * <p>A side effect of the <code>null</code> handling is that a
      97  * <code>NullPointerException</code> should be considered a bug in
      98  * <code>StringUtils</code> (except for deprecated methods).</p>
      99  *
     100  * <p>Methods in this class give sample code to explain their operation.
     101  * The symbol <code>*</code> is used to indicate any input including <code>null</code>.</p>
     102  *
     103  * <p>#ThreadSafe#</p>
     104  * @see java.lang.String
     105  * @author Apache Software Foundation
     106  * @author <a href="http://jakarta.apache.org/turbine/">Apache Jakarta Turbine</a>
     107  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
     108  * @author Daniel L. Rall
     109  * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
     110  * @author <a href="mailto:ed@apache.org">Ed Korthof</a>
     111  * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
     112  * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
     113  * @author Holger Krauth
     114  * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
     115  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
     116  * @author Arun Mammen Thomas
     117  * @author Gary Gregory
     118  * @author Phil Steitz
     119  * @author Al Chou
     120  * @author Michael Davey
     121  * @author Reuben Sivan
     122  * @author Chris Hyzer
     123  * @author Scott Johnson
     124  * @since 1.0
     125  * @version $Id: StringUtils.java 1058365 2011-01-13 00:04:49Z niallp $
     126  */
     127 //@Immutable
     128 public class StringUtils {
     129     // Performance testing notes (JDK 1.4, Jul03, scolebourne)
     130     // Whitespace:
     131     // Character.isWhitespace() is faster than WHITESPACE.indexOf()
     132     // where WHITESPACE is a string of all whitespace characters
     133     //
     134     // Character access:
     135     // String.charAt(n) versus toCharArray(), then array[n]
     136     // String.charAt(n) is about 15% worse for a 10K string
     137     // They are about equal for a length 50 string
     138     // String.charAt(n) is about 4 times better for a length 3 string
     139     // String.charAt(n) is best bet overall
     140     //
     141     // Append:
     142     // String.concat about twice as fast as StringBuffer.append
     143     // (not sure who tested this)
     144 
     145     /**
     146      * The empty String <code>""</code>.
     147      * @since 2.0
     148      */
     149     public static final String EMPTY = "";
     150 
     151     /**
     152      * Represents a failed index search.
     153      * @since 2.1
     154      */
     155     public static final int INDEX_NOT_FOUND = -1;
     156 
     157     /**
     158      * <p>The maximum size to which the padding constant(s) can expand.</p>
     159      */
     160     private static final int PAD_LIMIT = 8192;
     161 
     162     /**
     163      * <p><code>StringUtils</code> instances should NOT be constructed in
     164      * standard programming. Instead, the class should be used as
     165      * <code>StringUtils.trim(" foo ");</code>.</p>
     166      *
     167      * <p>This constructor is public to permit tools that require a JavaBean
     168      * instance to operate.</p>
     169      */
     170     public StringUtils() {
     171         super();
     172     }
     173 
     174     // Empty checks
     175     //-----------------------------------------------------------------------
     176     /**
     177      * <p>Checks if a String is empty ("") or null.</p>
     178      *
     179      * <pre>
     180      * StringUtils.isEmpty(null)      = true
     181      * StringUtils.isEmpty("")        = true
     182      * StringUtils.isEmpty(" ")       = false
     183      * StringUtils.isEmpty("bob")     = false
     184      * StringUtils.isEmpty("  bob  ") = false
     185      * </pre>
     186      *
     187      * <p>NOTE: This method changed in Lang version 2.0.
     188      * It no longer trims the String.
     189      * That functionality is available in isBlank().</p>
     190      *
     191      * @param str  the String to check, may be null
     192      * @return <code>true</code> if the String is empty or null
     193      */
     194     public static boolean isEmpty(String str) {
     195         return str == null || str.length() == 0;
     196     }
     197 
     198     /**
     199      * <p>Checks if a String is not empty ("") and not null.</p>
     200      *
     201      * <pre>
     202      * StringUtils.isNotEmpty(null)      = false
     203      * StringUtils.isNotEmpty("")        = false
     204      * StringUtils.isNotEmpty(" ")       = true
     205      * StringUtils.isNotEmpty("bob")     = true
     206      * StringUtils.isNotEmpty("  bob  ") = true
     207      * </pre>
     208      *
     209      * @param str  the String to check, may be null
     210      * @return <code>true</code> if the String is not empty and not null
     211      */
     212     public static boolean isNotEmpty(String str) {
     213         return !StringUtils.isEmpty(str);
     214     }
     215 
     216     /**
     217      * <p>Checks if a String is whitespace, empty ("") or null.</p>
     218      *
     219      * <pre>
     220      * StringUtils.isBlank(null)      = true
     221      * StringUtils.isBlank("")        = true
     222      * StringUtils.isBlank(" ")       = true
     223      * StringUtils.isBlank("bob")     = false
     224      * StringUtils.isBlank("  bob  ") = false
     225      * </pre>
     226      *
     227      * @param str  the String to check, may be null
     228      * @return <code>true</code> if the String is null, empty or whitespace
     229      * @since 2.0
     230      */
     231     public static boolean isBlank(String str) {
     232         int strLen;
     233         if (str == null || (strLen = str.length()) == 0) {
     234             return true;
     235         }
     236         for (int i = 0; i < strLen; i++) {
     237             if ((Character.isWhitespace(str.charAt(i)) == false)) {
     238                 return false;
     239             }
     240         }
     241         return true;
     242     }
     243 
     244     /**
     245      * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>
     246      *
     247      * <pre>
     248      * StringUtils.isNotBlank(null)      = false
     249      * StringUtils.isNotBlank("")        = false
     250      * StringUtils.isNotBlank(" ")       = false
     251      * StringUtils.isNotBlank("bob")     = true
     252      * StringUtils.isNotBlank("  bob  ") = true
     253      * </pre>
     254      *
     255      * @param str  the String to check, may be null
     256      * @return <code>true</code> if the String is
     257      *  not empty and not null and not whitespace
     258      * @since 2.0
     259      */
     260     public static boolean isNotBlank(String str) {
     261         return !StringUtils.isBlank(str);
     262     }
     263 
     264     // Trim
     265     //-----------------------------------------------------------------------
     266     /**
     267      * <p>Removes control characters (char &lt;= 32) from both
     268      * ends of this String, handling <code>null</code> by returning
     269      * an empty String ("").</p>
     270      *
     271      * <pre>
     272      * StringUtils.clean(null)          = ""
     273      * StringUtils.clean("")            = ""
     274      * StringUtils.clean("abc")         = "abc"
     275      * StringUtils.clean("    abc    ") = "abc"
     276      * StringUtils.clean("     ")       = ""
     277      * </pre>
     278      *
     279      * @see java.lang.String#trim()
     280      * @param str  the String to clean, may be null
     281      * @return the trimmed text, never <code>null</code>
     282      * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
     283      *             Method will be removed in Commons Lang 3.0.
     284      */
     285     public static String clean(String str) {
     286         return str == null ? EMPTY : str.trim();
     287     }
     288 
     289     /**
     290      * <p>Removes control characters (char &lt;= 32) from both
     291      * ends of this String, handling <code>null</code> by returning
     292      * <code>null</code>.</p>
     293      *
     294      * <p>The String is trimmed using {@link String#trim()}.
     295      * Trim removes start and end characters &lt;= 32.
     296      * To strip whitespace use {@link #strip(String)}.</p>
     297      *
     298      * <p>To trim your choice of characters, use the
     299      * {@link #strip(String, String)} methods.</p>
     300      *
     301      * <pre>
     302      * StringUtils.trim(null)          = null
     303      * StringUtils.trim("")            = ""
     304      * StringUtils.trim("     ")       = ""
     305      * StringUtils.trim("abc")         = "abc"
     306      * StringUtils.trim("    abc    ") = "abc"
     307      * </pre>
     308      *
     309      * @param str  the String to be trimmed, may be null
     310      * @return the trimmed string, <code>null</code> if null String input
     311      */
     312     public static String trim(String str) {
     313         return str == null ? null : str.trim();
     314     }
     315 
     316     /**
     317      * <p>Removes control characters (char &lt;= 32) from both
     318      * ends of this String returning <code>null</code> if the String is
     319      * empty ("") after the trim or if it is <code>null</code>.
     320      *
     321      * <p>The String is trimmed using {@link String#trim()}.
     322      * Trim removes start and end characters &lt;= 32.
     323      * To strip whitespace use {@link #stripToNull(String)}.</p>
     324      *
     325      * <pre>
     326      * StringUtils.trimToNull(null)          = null
     327      * StringUtils.trimToNull("")            = null
     328      * StringUtils.trimToNull("     ")       = null
     329      * StringUtils.trimToNull("abc")         = "abc"
     330      * StringUtils.trimToNull("    abc    ") = "abc"
     331      * </pre>
     332      *
     333      * @param str  the String to be trimmed, may be null
     334      * @return the trimmed String,
     335      *  <code>null</code> if only chars &lt;= 32, empty or null String input
     336      * @since 2.0
     337      */
     338     public static String trimToNull(String str) {
     339         String ts = trim(str);
     340         return isEmpty(ts) ? null : ts;
     341     }
     342 
     343     /**
     344      * <p>Removes control characters (char &lt;= 32) from both
     345      * ends of this String returning an empty String ("") if the String
     346      * is empty ("") after the trim or if it is <code>null</code>.
     347      *
     348      * <p>The String is trimmed using {@link String#trim()}.
     349      * Trim removes start and end characters &lt;= 32.
     350      * To strip whitespace use {@link #stripToEmpty(String)}.</p>
     351      *
     352      * <pre>
     353      * StringUtils.trimToEmpty(null)          = ""
     354      * StringUtils.trimToEmpty("")            = ""
     355      * StringUtils.trimToEmpty("     ")       = ""
     356      * StringUtils.trimToEmpty("abc")         = "abc"
     357      * StringUtils.trimToEmpty("    abc    ") = "abc"
     358      * </pre>
     359      *
     360      * @param str  the String to be trimmed, may be null
     361      * @return the trimmed String, or an empty String if <code>null</code> input
     362      * @since 2.0
     363      */
     364     public static String trimToEmpty(String str) {
     365         return str == null ? EMPTY : str.trim();
     366     }
     367 
     368     // Stripping
     369     //-----------------------------------------------------------------------
     370     /**
     371      * <p>Strips whitespace from the start and end of a String.</p>
     372      *
     373      * <p>This is similar to {@link #trim(String)} but removes whitespace.
     374      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
     375      *
     376      * <p>A <code>null</code> input String returns <code>null</code>.</p>
     377      *
     378      * <pre>
     379      * StringUtils.strip(null)     = null
     380      * StringUtils.strip("")       = ""
     381      * StringUtils.strip("   ")    = ""
     382      * StringUtils.strip("abc")    = "abc"
     383      * StringUtils.strip("  abc")  = "abc"
     384      * StringUtils.strip("abc  ")  = "abc"
     385      * StringUtils.strip(" abc ")  = "abc"
     386      * StringUtils.strip(" ab c ") = "ab c"
     387      * </pre>
     388      *
     389      * @param str  the String to remove whitespace from, may be null
     390      * @return the stripped String, <code>null</code> if null String input
     391      */
     392     public static String strip(String str) {
     393         return strip(str, null);
     394     }
     395 
     396     /**
     397      * <p>Strips whitespace from the start and end of a String  returning
     398      * <code>null</code> if the String is empty ("") after the strip.</p>
     399      *
     400      * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
     401      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
     402      *
     403      * <pre>
     404      * StringUtils.stripToNull(null)     = null
     405      * StringUtils.stripToNull("")       = null
     406      * StringUtils.stripToNull("   ")    = null
     407      * StringUtils.stripToNull("abc")    = "abc"
     408      * StringUtils.stripToNull("  abc")  = "abc"
     409      * StringUtils.stripToNull("abc  ")  = "abc"
     410      * StringUtils.stripToNull(" abc ")  = "abc"
     411      * StringUtils.stripToNull(" ab c ") = "ab c"
     412      * </pre>
     413      *
     414      * @param str  the String to be stripped, may be null
     415      * @return the stripped String,
     416      *  <code>null</code> if whitespace, empty or null String input
     417      * @since 2.0
     418      */
     419     public static String stripToNull(String str) {
     420         if (str == null) {
     421             return null;
     422         }
     423         str = strip(str, null);
     424         return str.length() == 0 ? null : str;
     425     }
     426 
     427     /**
     428      * <p>Strips whitespace from the start and end of a String  returning
     429      * an empty String if <code>null</code> input.</p>
     430      *
     431      * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
     432      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
     433      *
     434      * <pre>
     435      * StringUtils.stripToEmpty(null)     = ""
     436      * StringUtils.stripToEmpty("")       = ""
     437      * StringUtils.stripToEmpty("   ")    = ""
     438      * StringUtils.stripToEmpty("abc")    = "abc"
     439      * StringUtils.stripToEmpty("  abc")  = "abc"
     440      * StringUtils.stripToEmpty("abc  ")  = "abc"
     441      * StringUtils.stripToEmpty(" abc ")  = "abc"
     442      * StringUtils.stripToEmpty(" ab c ") = "ab c"
     443      * </pre>
     444      *
     445      * @param str  the String to be stripped, may be null
     446      * @return the trimmed String, or an empty String if <code>null</code> input
     447      * @since 2.0
     448      */
     449     public static String stripToEmpty(String str) {
     450         return str == null ? EMPTY : strip(str, null);
     451     }
     452 
     453     /**
     454      * <p>Strips any of a set of characters from the start and end of a String.
     455      * This is similar to {@link String#trim()} but allows the characters
     456      * to be stripped to be controlled.</p>
     457      *
     458      * <p>A <code>null</code> input String returns <code>null</code>.
     459      * An empty string ("") input returns the empty string.</p>
     460      *
     461      * <p>If the stripChars String is <code>null</code>, whitespace is
     462      * stripped as defined by {@link Character#isWhitespace(char)}.
     463      * Alternatively use {@link #strip(String)}.</p>
     464      *
     465      * <pre>
     466      * StringUtils.strip(null, *)          = null
     467      * StringUtils.strip("", *)            = ""
     468      * StringUtils.strip("abc", null)      = "abc"
     469      * StringUtils.strip("  abc", null)    = "abc"
     470      * StringUtils.strip("abc  ", null)    = "abc"
     471      * StringUtils.strip(" abc ", null)    = "abc"
     472      * StringUtils.strip("  abcyx", "xyz") = "  abc"
     473      * </pre>
     474      *
     475      * @param str  the String to remove characters from, may be null
     476      * @param stripChars  the characters to remove, null treated as whitespace
     477      * @return the stripped String, <code>null</code> if null String input
     478      */
     479     public static String strip(String str, String stripChars) {
     480         if (isEmpty(str)) {
     481             return str;
     482         }
     483         str = stripStart(str, stripChars);
     484         return stripEnd(str, stripChars);
     485     }
     486 
     487     /**
     488      * <p>Strips any of a set of characters from the start of a String.</p>
     489      *
     490      * <p>A <code>null</code> input String returns <code>null</code>.
     491      * An empty string ("") input returns the empty string.</p>
     492      *
     493      * <p>If the stripChars String is <code>null</code>, whitespace is
     494      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
     495      *
     496      * <pre>
     497      * StringUtils.stripStart(null, *)          = null
     498      * StringUtils.stripStart("", *)            = ""
     499      * StringUtils.stripStart("abc", "")        = "abc"
     500      * StringUtils.stripStart("abc", null)      = "abc"
     501      * StringUtils.stripStart("  abc", null)    = "abc"
     502      * StringUtils.stripStart("abc  ", null)    = "abc  "
     503      * StringUtils.stripStart(" abc ", null)    = "abc "
     504      * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
     505      * </pre>
     506      *
     507      * @param str  the String to remove characters from, may be null
     508      * @param stripChars  the characters to remove, null treated as whitespace
     509      * @return the stripped String, <code>null</code> if null String input
     510      */
     511     public static String stripStart(String str, String stripChars) {
     512         int strLen;
     513         if (str == null || (strLen = str.length()) == 0) {
     514             return str;
     515         }
     516         int start = 0;
     517         if (stripChars == null) {
     518             while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
     519                 start++;
     520             }
     521         } else if (stripChars.length() == 0) {
     522             return str;
     523         } else {
     524             while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND)) {
     525                 start++;
     526             }
     527         }
     528         return str.substring(start);
     529     }
     530 
     531     /**
     532      * <p>Strips any of a set of characters from the end of a String.</p>
     533      *
     534      * <p>A <code>null</code> input String returns <code>null</code>.
     535      * An empty string ("") input returns the empty string.</p>
     536      *
     537      * <p>If the stripChars String is <code>null</code>, whitespace is
     538      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
     539      *
     540      * <pre>
     541      * StringUtils.stripEnd(null, *)          = null
     542      * StringUtils.stripEnd("", *)            = ""
     543      * StringUtils.stripEnd("abc", "")        = "abc"
     544      * StringUtils.stripEnd("abc", null)      = "abc"
     545      * StringUtils.stripEnd("  abc", null)    = "  abc"
     546      * StringUtils.stripEnd("abc  ", null)    = "abc"
     547      * StringUtils.stripEnd(" abc ", null)    = " abc"
     548      * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
     549      * StringUtils.stripEnd("120.00", ".0")   = "12"
     550      * </pre>
     551      *
     552      * @param str  the String to remove characters from, may be null
     553      * @param stripChars  the set of characters to remove, null treated as whitespace
     554      * @return the stripped String, <code>null</code> if null String input
     555      */
     556     public static String stripEnd(String str, String stripChars) {
     557         int end;
     558         if (str == null || (end = str.length()) == 0) {
     559             return str;
     560         }
     561 
     562         if (stripChars == null) {
     563             while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
     564                 end--;
     565             }
     566         } else if (stripChars.length() == 0) {
     567             return str;
     568         } else {
     569             while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND)) {
     570                 end--;
     571             }
     572         }
     573         return str.substring(0, end);
     574     }
     575 
     576     // StripAll
     577     //-----------------------------------------------------------------------
     578     /**
     579      * <p>Strips whitespace from the start and end of every String in an array.
     580      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
     581      *
     582      * <p>A new array is returned each time, except for length zero.
     583      * A <code>null</code> array will return <code>null</code>.
     584      * An empty array will return itself.
     585      * A <code>null</code> array entry will be ignored.</p>
     586      *
     587      * <pre>
     588      * StringUtils.stripAll(null)             = null
     589      * StringUtils.stripAll([])               = []
     590      * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
     591      * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
     592      * </pre>
     593      *
     594      * @param strs  the array to remove whitespace from, may be null
     595      * @return the stripped Strings, <code>null</code> if null array input
     596      */
     597     public static String[] stripAll(String[] strs) {
     598         return stripAll(strs, null);
     599     }
     600 
     601     /**
     602      * <p>Strips any of a set of characters from the start and end of every
     603      * String in an array.</p>
     604      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
     605      *
     606      * <p>A new array is returned each time, except for length zero.
     607      * A <code>null</code> array will return <code>null</code>.
     608      * An empty array will return itself.
     609      * A <code>null</code> array entry will be ignored.
     610      * A <code>null</code> stripChars will strip whitespace as defined by
     611      * {@link Character#isWhitespace(char)}.</p>
     612      *
     613      * <pre>
     614      * StringUtils.stripAll(null, *)                = null
     615      * StringUtils.stripAll([], *)                  = []
     616      * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
     617      * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
     618      * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
     619      * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
     620      * </pre>
     621      *
     622      * @param strs  the array to remove characters from, may be null
     623      * @param stripChars  the characters to remove, null treated as whitespace
     624      * @return the stripped Strings, <code>null</code> if null array input
     625      */
     626     public static String[] stripAll(String[] strs, String stripChars) {
     627         int strsLen;
     628         if (strs == null || (strsLen = strs.length) == 0) {
     629             return strs;
     630         }
     631         String[] newArr = new String[strsLen];
     632         for (int i = 0; i < strsLen; i++) {
     633             newArr[i] = strip(strs[i], stripChars);
     634         }
     635         return newArr;
     636     }
     637 
     638     // Equals
     639     //-----------------------------------------------------------------------
     640     /**
     641      * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
     642      *
     643      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
     644      * references are considered to be equal. The comparison is case sensitive.</p>
     645      *
     646      * <pre>
     647      * StringUtils.equals(null, null)   = true
     648      * StringUtils.equals(null, "abc")  = false
     649      * StringUtils.equals("abc", null)  = false
     650      * StringUtils.equals("abc", "abc") = true
     651      * StringUtils.equals("abc", "ABC") = false
     652      * </pre>
     653      *
     654      * @see java.lang.String#equals(Object)
     655      * @param str1  the first String, may be null
     656      * @param str2  the second String, may be null
     657      * @return <code>true</code> if the Strings are equal, case sensitive, or
     658      *  both <code>null</code>
     659      */
     660     public static boolean equals(String str1, String str2) {
     661         return str1 == null ? str2 == null : str1.equals(str2);
     662     }
     663 
     664     /**
     665      * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring
     666      * the case.</p>
     667      *
     668      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
     669      * references are considered equal. Comparison is case insensitive.</p>
     670      *
     671      * <pre>
     672      * StringUtils.equalsIgnoreCase(null, null)   = true
     673      * StringUtils.equalsIgnoreCase(null, "abc")  = false
     674      * StringUtils.equalsIgnoreCase("abc", null)  = false
     675      * StringUtils.equalsIgnoreCase("abc", "abc") = true
     676      * StringUtils.equalsIgnoreCase("abc", "ABC") = true
     677      * </pre>
     678      *
     679      * @see java.lang.String#equalsIgnoreCase(String)
     680      * @param str1  the first String, may be null
     681      * @param str2  the second String, may be null
     682      * @return <code>true</code> if the Strings are equal, case insensitive, or
     683      *  both <code>null</code>
     684      */
     685     public static boolean equalsIgnoreCase(String str1, String str2) {
     686         return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
     687     }
     688 
     689     // IndexOf
     690     //-----------------------------------------------------------------------
     691     /**
     692      * <p>Finds the first index within a String, handling <code>null</code>.
     693      * This method uses {@link String#indexOf(int)}.</p>
     694      *
     695      * <p>A <code>null</code> or empty ("") String will return <code>INDEX_NOT_FOUND (-1)</code>.</p>
     696      *
     697      * <pre>
     698      * StringUtils.indexOf(null, *)         = -1
     699      * StringUtils.indexOf("", *)           = -1
     700      * StringUtils.indexOf("aabaabaa", 'a') = 0
     701      * StringUtils.indexOf("aabaabaa", 'b') = 2
     702      * </pre>
     703      *
     704      * @param str  the String to check, may be null
     705      * @param searchChar  the character to find
     706      * @return the first index of the search character,
     707      *  -1 if no match or <code>null</code> string input
     708      * @since 2.0
     709      */
     710     public static int indexOf(String str, char searchChar) {
     711         if (isEmpty(str)) {
     712             return INDEX_NOT_FOUND;
     713         }
     714         return str.indexOf(searchChar);
     715     }
     716 
     717     /**
     718      * <p>Finds the first index within a String from a start position,
     719      * handling <code>null</code>.
     720      * This method uses {@link String#indexOf(int, int)}.</p>
     721      *
     722      * <p>A <code>null</code> or empty ("") String will return <code>(INDEX_NOT_FOUND) -1</code>.
     723      * A negative start position is treated as zero.
     724      * A start position greater than the string length returns <code>-1</code>.</p>
     725      *
     726      * <pre>
     727      * StringUtils.indexOf(null, *, *)          = -1
     728      * StringUtils.indexOf("", *, *)            = -1
     729      * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
     730      * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
     731      * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
     732      * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
     733      * </pre>
     734      *
     735      * @param str  the String to check, may be null
     736      * @param searchChar  the character to find
     737      * @param startPos  the start position, negative treated as zero
     738      * @return the first index of the search character,
     739      *  -1 if no match or <code>null</code> string input
     740      * @since 2.0
     741      */
     742     public static int indexOf(String str, char searchChar, int startPos) {
     743         if (isEmpty(str)) {
     744             return INDEX_NOT_FOUND;
     745         }
     746         return str.indexOf(searchChar, startPos);
     747     }
     748 
     749     /**
     750      * <p>Finds the first index within a String, handling <code>null</code>.
     751      * This method uses {@link String#indexOf(String)}.</p>
     752      *
     753      * <p>A <code>null</code> String will return <code>-1</code>.</p>
     754      *
     755      * <pre>
     756      * StringUtils.indexOf(null, *)          = -1
     757      * StringUtils.indexOf(*, null)          = -1
     758      * StringUtils.indexOf("", "")           = 0
     759      * StringUtils.indexOf("", *)            = -1 (except when * = "")
     760      * StringUtils.indexOf("aabaabaa", "a")  = 0
     761      * StringUtils.indexOf("aabaabaa", "b")  = 2
     762      * StringUtils.indexOf("aabaabaa", "ab") = 1
     763      * StringUtils.indexOf("aabaabaa", "")   = 0
     764      * </pre>
     765      *
     766      * @param str  the String to check, may be null
     767      * @param searchStr  the String to find, may be null
     768      * @return the first index of the search String,
     769      *  -1 if no match or <code>null</code> string input
     770      * @since 2.0
     771      */
     772     public static int indexOf(String str, String searchStr) {
     773         if (str == null || searchStr == null) {
     774             return INDEX_NOT_FOUND;
     775         }
     776         return str.indexOf(searchStr);
     777     }
     778 
     779     /**
     780      * <p>Finds the n-th index within a String, handling <code>null</code>.
     781      * This method uses {@link String#indexOf(String)}.</p>
     782      *
     783      * <p>A <code>null</code> String will return <code>-1</code>.</p>
     784      *
     785      * <pre>
     786      * StringUtils.ordinalIndexOf(null, *, *)          = -1
     787      * StringUtils.ordinalIndexOf(*, null, *)          = -1
     788      * StringUtils.ordinalIndexOf("", "", *)           = 0
     789      * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
     790      * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
     791      * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
     792      * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
     793      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
     794      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
     795      * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
     796      * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
     797      * </pre>
     798      *
     799      * <p>Note that 'head(String str, int n)' may be implemented as: </p>
     800      *
     801      * <pre>
     802      *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
     803      * </pre>
     804      *
     805      * @param str  the String to check, may be null
     806      * @param searchStr  the String to find, may be null
     807      * @param ordinal  the n-th <code>searchStr</code> to find
     808      * @return the n-th index of the search String,
     809      *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
     810      * @since 2.1
     811      */
     812     public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
     813         return ordinalIndexOf(str, searchStr, ordinal, false);
     814     }
     815 
     816     /**
     817      * <p>Finds the n-th index within a String, handling <code>null</code>.
     818      * This method uses {@link String#indexOf(String)}.</p>
     819      *
     820      * <p>A <code>null</code> String will return <code>-1</code>.</p>
     821      *
     822      * @param str  the String to check, may be null
     823      * @param searchStr  the String to find, may be null
     824      * @param ordinal  the n-th <code>searchStr</code> to find
     825      * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
     826      * @return the n-th index of the search String,
     827      *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
     828      */
     829     // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
     830     private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {
     831         if (str == null || searchStr == null || ordinal <= 0) {
     832             return INDEX_NOT_FOUND;
     833         }
     834         if (searchStr.length() == 0) {
     835             return lastIndex ? str.length() : 0;
     836         }
     837         int found = 0;
     838         int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
     839         do {
     840             if(lastIndex) {
     841                 index = str.lastIndexOf(searchStr, index - 1);
     842             } else {
     843                 index = str.indexOf(searchStr, index + 1);
     844             }
     845             if (index < 0) {
     846                 return index;
     847             }
     848             found++;
     849         } while (found < ordinal);
     850         return index;
     851     }
     852 
     853     /**
     854      * <p>Finds the first index within a String, handling <code>null</code>.
     855      * This method uses {@link String#indexOf(String, int)}.</p>
     856      *
     857      * <p>A <code>null</code> String will return <code>-1</code>.
     858      * A negative start position is treated as zero.
     859      * An empty ("") search String always matches.
     860      * A start position greater than the string length only matches
     861      * an empty search String.</p>
     862      *
     863      * <pre>
     864      * StringUtils.indexOf(null, *, *)          = -1
     865      * StringUtils.indexOf(*, null, *)          = -1
     866      * StringUtils.indexOf("", "", 0)           = 0
     867      * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
     868      * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
     869      * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
     870      * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
     871      * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
     872      * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
     873      * StringUtils.indexOf("aabaabaa", "b", -1) = 2
     874      * StringUtils.indexOf("aabaabaa", "", 2)   = 2
     875      * StringUtils.indexOf("abc", "", 9)        = 3
     876      * </pre>
     877      *
     878      * @param str  the String to check, may be null
     879      * @param searchStr  the String to find, may be null
     880      * @param startPos  the start position, negative treated as zero
     881      * @return the first index of the search String,
     882      *  -1 if no match or <code>null</code> string input
     883      * @since 2.0
     884      */
     885     public static int indexOf(String str, String searchStr, int startPos) {
     886         if (str == null || searchStr == null) {
     887             return INDEX_NOT_FOUND;
     888         }
     889         // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
     890         if (searchStr.length() == 0 && startPos >= str.length()) {
     891             return str.length();
     892         }
     893         return str.indexOf(searchStr, startPos);
     894     }
     895 
     896     /**
     897      * <p>Case in-sensitive find of the first index within a String.</p>
     898      *
     899      * <p>A <code>null</code> String will return <code>-1</code>.
     900      * A negative start position is treated as zero.
     901      * An empty ("") search String always matches.
     902      * A start position greater than the string length only matches
     903      * an empty search String.</p>
     904      *
     905      * <pre>
     906      * StringUtils.indexOfIgnoreCase(null, *)          = -1
     907      * StringUtils.indexOfIgnoreCase(*, null)          = -1
     908      * StringUtils.indexOfIgnoreCase("", "")           = 0
     909      * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
     910      * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
     911      * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
     912      * </pre>
     913      *
     914      * @param str  the String to check, may be null
     915      * @param searchStr  the String to find, may be null
     916      * @return the first index of the search String,
     917      *  -1 if no match or <code>null</code> string input
     918      * @since 2.5
     919      */
     920     public static int indexOfIgnoreCase(String str, String searchStr) {
     921         return indexOfIgnoreCase(str, searchStr, 0);
     922     }
     923 
     924     /**
     925      * <p>Case in-sensitive find of the first index within a String
     926      * from the specified position.</p>
     927      *
     928      * <p>A <code>null</code> String will return <code>-1</code>.
     929      * A negative start position is treated as zero.
     930      * An empty ("") search String always matches.
     931      * A start position greater than the string length only matches
     932      * an empty search String.</p>
     933      *
     934      * <pre>
     935      * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
     936      * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
     937      * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
     938      * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
     939      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
     940      * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
     941      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
     942      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
     943      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
     944      * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
     945      * StringUtils.indexOfIgnoreCase("abc", "", 9)        = 3
     946      * </pre>
     947      *
     948      * @param str  the String to check, may be null
     949      * @param searchStr  the String to find, may be null
     950      * @param startPos  the start position, negative treated as zero
     951      * @return the first index of the search String,
     952      *  -1 if no match or <code>null</code> string input
     953      * @since 2.5
     954      */
     955     public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {
     956         if (str == null || searchStr == null) {
     957             return INDEX_NOT_FOUND;
     958         }
     959         if (startPos < 0) {
     960             startPos = 0;
     961         }
     962         int endLimit = (str.length() - searchStr.length()) + 1;
     963         if (startPos > endLimit) {
     964             return INDEX_NOT_FOUND;
     965         }
     966         if (searchStr.length() == 0) {
     967             return startPos;
     968         }
     969         for (int i = startPos; i < endLimit; i++) {
     970             if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
     971                 return i;
     972             }
     973         }
     974         return INDEX_NOT_FOUND;
     975     }
     976 
     977     // LastIndexOf
     978     //-----------------------------------------------------------------------
     979     /**
     980      * <p>Finds the last index within a String, handling <code>null</code>.
     981      * This method uses {@link String#lastIndexOf(int)}.</p>
     982      *
     983      * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>
     984      *
     985      * <pre>
     986      * StringUtils.lastIndexOf(null, *)         = -1
     987      * StringUtils.lastIndexOf("", *)           = -1
     988      * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
     989      * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
     990      * </pre>
     991      *
     992      * @param str  the String to check, may be null
     993      * @param searchChar  the character to find
     994      * @return the last index of the search character,
     995      *  -1 if no match or <code>null</code> string input
     996      * @since 2.0
     997      */
     998     public static int lastIndexOf(String str, char searchChar) {
     999         if (isEmpty(str)) {
    1000             return INDEX_NOT_FOUND;
    1001         }
    1002         return str.lastIndexOf(searchChar);
    1003     }
    1004 
    1005     /**
    1006      * <p>Finds the last index within a String from a start position,
    1007      * handling <code>null</code>.
    1008      * This method uses {@link String#lastIndexOf(int, int)}.</p>
    1009      *
    1010      * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.
    1011      * A negative start position returns <code>-1</code>.
    1012      * A start position greater than the string length searches the whole string.</p>
    1013      *
    1014      * <pre>
    1015      * StringUtils.lastIndexOf(null, *, *)          = -1
    1016      * StringUtils.lastIndexOf("", *,  *)           = -1
    1017      * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
    1018      * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
    1019      * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
    1020      * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
    1021      * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
    1022      * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
    1023      * </pre>
    1024      *
    1025      * @param str  the String to check, may be null
    1026      * @param searchChar  the character to find
    1027      * @param startPos  the start position
    1028      * @return the last index of the search character,
    1029      *  -1 if no match or <code>null</code> string input
    1030      * @since 2.0
    1031      */
    1032     public static int lastIndexOf(String str, char searchChar, int startPos) {
    1033         if (isEmpty(str)) {
    1034             return INDEX_NOT_FOUND;
    1035         }
    1036         return str.lastIndexOf(searchChar, startPos);
    1037     }
    1038 
    1039     /**
    1040      * <p>Finds the last index within a String, handling <code>null</code>.
    1041      * This method uses {@link String#lastIndexOf(String)}.</p>
    1042      *
    1043      * <p>A <code>null</code> String will return <code>-1</code>.</p>
    1044      *
    1045      * <pre>
    1046      * StringUtils.lastIndexOf(null, *)          = -1
    1047      * StringUtils.lastIndexOf(*, null)          = -1
    1048      * StringUtils.lastIndexOf("", "")           = 0
    1049      * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
    1050      * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
    1051      * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
    1052      * StringUtils.lastIndexOf("aabaabaa", "")   = 8
    1053      * </pre>
    1054      *
    1055      * @param str  the String to check, may be null
    1056      * @param searchStr  the String to find, may be null
    1057      * @return the last index of the search String,
    1058      *  -1 if no match or <code>null</code> string input
    1059      * @since 2.0
    1060      */
    1061     public static int lastIndexOf(String str, String searchStr) {
    1062         if (str == null || searchStr == null) {
    1063             return INDEX_NOT_FOUND;
    1064         }
    1065         return str.lastIndexOf(searchStr);
    1066     }
    1067 
    1068     /**
    1069      * <p>Finds the n-th last index within a String, handling <code>null</code>.
    1070      * This method uses {@link String#lastIndexOf(String)}.</p>
    1071      *
    1072      * <p>A <code>null</code> String will return <code>-1</code>.</p>
    1073      *
    1074      * <pre>
    1075      * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
    1076      * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
    1077      * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
    1078      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
    1079      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
    1080      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
    1081      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
    1082      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
    1083      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
    1084      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
    1085      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
    1086      * </pre>
    1087      *
    1088      * <p>Note that 'tail(String str, int n)' may be implemented as: </p>
    1089      *
    1090      * <pre>
    1091      *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
    1092      * </pre>
    1093      *
    1094      * @param str  the String to check, may be null
    1095      * @param searchStr  the String to find, may be null
    1096      * @param ordinal  the n-th last <code>searchStr</code> to find
    1097      * @return the n-th last index of the search String,
    1098      *  <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input
    1099      * @since 2.5
    1100      */
    1101     public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {
    1102         return ordinalIndexOf(str, searchStr, ordinal, true);
    1103     }
    1104 
    1105     /**
    1106      * <p>Finds the first index within a String, handling <code>null</code>.
    1107      * This method uses {@link String#lastIndexOf(String, int)}.</p>
    1108      *
    1109      * <p>A <code>null</code> String will return <code>-1</code>.
    1110      * A negative start position returns <code>-1</code>.
    1111      * An empty ("") search String always matches unless the start position is negative.
    1112      * A start position greater than the string length searches the whole string.</p>
    1113      *
    1114      * <pre>
    1115      * StringUtils.lastIndexOf(null, *, *)          = -1
    1116      * StringUtils.lastIndexOf(*, null, *)          = -1
    1117      * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
    1118      * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
    1119      * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
    1120      * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
    1121      * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
    1122      * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
    1123      * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
    1124      * </pre>
    1125      *
    1126      * @param str  the String to check, may be null
    1127      * @param searchStr  the String to find, may be null
    1128      * @param startPos  the start position, negative treated as zero
    1129      * @return the first index of the search String,
    1130      *  -1 if no match or <code>null</code> string input
    1131      * @since 2.0
    1132      */
    1133     public static int lastIndexOf(String str, String searchStr, int startPos) {
    1134         if (str == null || searchStr == null) {
    1135             return INDEX_NOT_FOUND;
    1136         }
    1137         return str.lastIndexOf(searchStr, startPos);
    1138     }
    1139 
    1140     /**
    1141      * <p>Case in-sensitive find of the last index within a String.</p>
    1142      *
    1143      * <p>A <code>null</code> String will return <code>-1</code>.
    1144      * A negative start position returns <code>-1</code>.
    1145      * An empty ("") search String always matches unless the start position is negative.
    1146      * A start position greater than the string length searches the whole string.</p>
    1147      *
    1148      * <pre>
    1149      * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
    1150      * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
    1151      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
    1152      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
    1153      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
    1154      * </pre>
    1155      *
    1156      * @param str  the String to check, may be null
    1157      * @param searchStr  the String to find, may be null
    1158      * @return the first index of the search String,
    1159      *  -1 if no match or <code>null</code> string input
    1160      * @since 2.5
    1161      */
    1162     public static int lastIndexOfIgnoreCase(String str, String searchStr) {
    1163         if (str == null || searchStr == null) {
    1164             return INDEX_NOT_FOUND;
    1165         }
    1166         return lastIndexOfIgnoreCase(str, searchStr, str.length());
    1167     }
    1168 
    1169     /**
    1170      * <p>Case in-sensitive find of the last index within a String
    1171      * from the specified position.</p>
    1172      *
    1173      * <p>A <code>null</code> String will return <code>-1</code>.
    1174      * A negative start position returns <code>-1</code>.
    1175      * An empty ("") search String always matches unless the start position is negative.
    1176      * A start position greater than the string length searches the whole string.</p>
    1177      *
    1178      * <pre>
    1179      * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
    1180      * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
    1181      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
    1182      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
    1183      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
    1184      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
    1185      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
    1186      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    1187      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
    1188      * </pre>
    1189      *
    1190      * @param str  the String to check, may be null
    1191      * @param searchStr  the String to find, may be null
    1192      * @param startPos  the start position
    1193      * @return the first index of the search String,
    1194      *  -1 if no match or <code>null</code> string input
    1195      * @since 2.5
    1196      */
    1197     public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {
    1198         if (str == null || searchStr == null) {
    1199             return INDEX_NOT_FOUND;
    1200         }
    1201         if (startPos > (str.length() - searchStr.length())) {
    1202             startPos = str.length() - searchStr.length();
    1203         }
    1204         if (startPos < 0) {
    1205             return INDEX_NOT_FOUND;
    1206         }
    1207         if (searchStr.length() == 0) {
    1208             return startPos;
    1209         }
    1210 
    1211         for (int i = startPos; i >= 0; i--) {
    1212             if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {
    1213                 return i;
    1214             }
    1215         }
    1216         return INDEX_NOT_FOUND;
    1217     }
    1218 
    1219     // Contains
    1220     //-----------------------------------------------------------------------
    1221     /**
    1222      * <p>Checks if String contains a search character, handling <code>null</code>.
    1223      * This method uses {@link String#indexOf(int)}.</p>
    1224      *
    1225      * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>
    1226      *
    1227      * <pre>
    1228      * StringUtils.contains(null, *)    = false
    1229      * StringUtils.contains("", *)      = false
    1230      * StringUtils.contains("abc", 'a') = true
    1231      * StringUtils.contains("abc", 'z') = false
    1232      * </pre>
    1233      *
    1234      * @param str  the String to check, may be null
    1235      * @param searchChar  the character to find
    1236      * @return true if the String contains the search character,
    1237      *  false if not or <code>null</code> string input
    1238      * @since 2.0
    1239      */
    1240     public static boolean contains(String str, char searchChar) {
    1241         if (isEmpty(str)) {
    1242             return false;
    1243         }
    1244         return str.indexOf(searchChar) >= 0;
    1245     }
    1246 
    1247     /**
    1248      * <p>Checks if String contains a search String, handling <code>null</code>.
    1249      * This method uses {@link String#indexOf(String)}.</p>
    1250      *
    1251      * <p>A <code>null</code> String will return <code>false</code>.</p>
    1252      *
    1253      * <pre>
    1254      * StringUtils.contains(null, *)     = false
    1255      * StringUtils.contains(*, null)     = false
    1256      * StringUtils.contains("", "")      = true
    1257      * StringUtils.contains("abc", "")   = true
    1258      * StringUtils.contains("abc", "a")  = true
    1259      * StringUtils.contains("abc", "z")  = false
    1260      * </pre>
    1261      *
    1262      * @param str  the String to check, may be null
    1263      * @param searchStr  the String to find, may be null
    1264      * @return true if the String contains the search String,
    1265      *  false if not or <code>null</code> string input
    1266      * @since 2.0
    1267      */
    1268     public static boolean contains(String str, String searchStr) {
    1269         if (str == null || searchStr == null) {
    1270             return false;
    1271         }
    1272         return str.indexOf(searchStr) >= 0;
    1273     }
    1274 
    1275     /**
    1276      * <p>Checks if String contains a search String irrespective of case,
    1277      * handling <code>null</code>. Case-insensitivity is defined as by
    1278      * {@link String#equalsIgnoreCase(String)}.
    1279      *
    1280      * <p>A <code>null</code> String will return <code>false</code>.</p>
    1281      *
    1282      * <pre>
    1283      * StringUtils.contains(null, *) = false
    1284      * StringUtils.contains(*, null) = false
    1285      * StringUtils.contains("", "") = true
    1286      * StringUtils.contains("abc", "") = true
    1287      * StringUtils.contains("abc", "a") = true
    1288      * StringUtils.contains("abc", "z") = false
    1289      * StringUtils.contains("abc", "A") = true
    1290      * StringUtils.contains("abc", "Z") = false
    1291      * </pre>
    1292      *
    1293      * @param str  the String to check, may be null
    1294      * @param searchStr  the String to find, may be null
    1295      * @return true if the String contains the search String irrespective of
    1296      * case or false if not or <code>null</code> string input
    1297      */
    1298     public static boolean containsIgnoreCase(String str, String searchStr) {
    1299         if (str == null || searchStr == null) {
    1300             return false;
    1301         }
    1302         int len = searchStr.length();
    1303         int max = str.length() - len;
    1304         for (int i = 0; i <= max; i++) {
    1305             if (str.regionMatches(true, i, searchStr, 0, len)) {
    1306                 return true;
    1307             }
    1308         }
    1309         return false;
    1310     }
    1311 
    1312     // IndexOfAny chars
    1313     //-----------------------------------------------------------------------
    1314     /**
    1315      * <p>Search a String to find the first index of any
    1316      * character in the given set of characters.</p>
    1317      *
    1318      * <p>A <code>null</code> String will return <code>-1</code>.
    1319      * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
    1320      *
    1321      * <pre>
    1322      * StringUtils.indexOfAny(null, *)                = -1
    1323      * StringUtils.indexOfAny("", *)                  = -1
    1324      * StringUtils.indexOfAny(*, null)                = -1
    1325      * StringUtils.indexOfAny(*, [])                  = -1
    1326      * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
    1327      * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
    1328      * StringUtils.indexOfAny("aba", ['z'])           = -1
    1329      * </pre>
    1330      *
    1331      * @param str  the String to check, may be null
    1332      * @param searchChars  the chars to search for, may be null
    1333      * @return the index of any of the chars, -1 if no match or null input
    1334      * @since 2.0
    1335      */
    1336     public static int indexOfAny(String str, char[] searchChars) {
    1337         if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1338             return INDEX_NOT_FOUND;
    1339         }
    1340         int csLen = str.length();
    1341         int csLast = csLen - 1;
    1342         int searchLen = searchChars.length;
    1343         int searchLast = searchLen - 1;
    1344         for (int i = 0; i < csLen; i++) {
    1345             char ch = str.charAt(i);
    1346             for (int j = 0; j < searchLen; j++) {
    1347                 if (searchChars[j] == ch) {
    1348                     if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
    1349                         // ch is a supplementary character
    1350                         if (searchChars[j + 1] == str.charAt(i + 1)) {
    1351                             return i;
    1352                         }
    1353                     } else {
    1354                         return i;
    1355                     }
    1356                 }
    1357             }
    1358         }
    1359         return INDEX_NOT_FOUND;
    1360     }
    1361 
    1362     /**
    1363      * <p>Search a String to find the first index of any
    1364      * character in the given set of characters.</p>
    1365      *
    1366      * <p>A <code>null</code> String will return <code>-1</code>.
    1367      * A <code>null</code> search string will return <code>-1</code>.</p>
    1368      *
    1369      * <pre>
    1370      * StringUtils.indexOfAny(null, *)            = -1
    1371      * StringUtils.indexOfAny("", *)              = -1
    1372      * StringUtils.indexOfAny(*, null)            = -1
    1373      * StringUtils.indexOfAny(*, "")              = -1
    1374      * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
    1375      * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
    1376      * StringUtils.indexOfAny("aba","z")          = -1
    1377      * </pre>
    1378      *
    1379      * @param str  the String to check, may be null
    1380      * @param searchChars  the chars to search for, may be null
    1381      * @return the index of any of the chars, -1 if no match or null input
    1382      * @since 2.0
    1383      */
    1384     public static int indexOfAny(String str, String searchChars) {
    1385         if (isEmpty(str) || isEmpty(searchChars)) {
    1386             return INDEX_NOT_FOUND;
    1387         }
    1388         return indexOfAny(str, searchChars.toCharArray());
    1389     }
    1390 
    1391     // ContainsAny
    1392     //-----------------------------------------------------------------------
    1393     /**
    1394      * <p>Checks if the String contains any character in the given
    1395      * set of characters.</p>
    1396      *
    1397      * <p>A <code>null</code> String will return <code>false</code>.
    1398      * A <code>null</code> or zero length search array will return <code>false</code>.</p>
    1399      *
    1400      * <pre>
    1401      * StringUtils.containsAny(null, *)                = false
    1402      * StringUtils.containsAny("", *)                  = false
    1403      * StringUtils.containsAny(*, null)                = false
    1404      * StringUtils.containsAny(*, [])                  = false
    1405      * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
    1406      * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
    1407      * StringUtils.containsAny("aba", ['z'])           = false
    1408      * </pre>
    1409      *
    1410      * @param str  the String to check, may be null
    1411      * @param searchChars  the chars to search for, may be null
    1412      * @return the <code>true</code> if any of the chars are found,
    1413      * <code>false</code> if no match or null input
    1414      * @since 2.4
    1415      */
    1416     public static boolean containsAny(String str, char[] searchChars) {
    1417         if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1418             return false;
    1419         }
    1420         int csLength = str.length();
    1421         int searchLength = searchChars.length;
    1422         int csLast = csLength - 1;
    1423         int searchLast = searchLength - 1;
    1424         for (int i = 0; i < csLength; i++) {
    1425             char ch = str.charAt(i);
    1426             for (int j = 0; j < searchLength; j++) {
    1427                 if (searchChars[j] == ch) {
    1428                     if (CharUtils.isHighSurrogate(ch)) {
    1429                         if (j == searchLast) {
    1430                             // missing low surrogate, fine, like String.indexOf(String)
    1431                             return true;
    1432                         }
    1433                         if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
    1434                             return true;
    1435                         }
    1436                     } else {
    1437                         // ch is in the Basic Multilingual Plane
    1438                         return true;
    1439                     }
    1440                 }
    1441             }
    1442         }
    1443         return false;
    1444     }
    1445 
    1446     /**
    1447      * <p>
    1448      * Checks if the String contains any character in the given set of characters.
    1449      * </p>
    1450      * 
    1451      * <p>
    1452      * A <code>null</code> String will return <code>false</code>. A <code>null</code> search string will return
    1453      * <code>false</code>.
    1454      * </p>
    1455      * 
    1456      * <pre>
    1457      * StringUtils.containsAny(null, *)            = false
    1458      * StringUtils.containsAny("", *)              = false
    1459      * StringUtils.containsAny(*, null)            = false
    1460      * StringUtils.containsAny(*, "")              = false
    1461      * StringUtils.containsAny("zzabyycdxx", "za") = true
    1462      * StringUtils.containsAny("zzabyycdxx", "by") = true
    1463      * StringUtils.containsAny("aba","z")          = false
    1464      * </pre>
    1465      * 
    1466      * @param str
    1467      *            the String to check, may be null
    1468      * @param searchChars
    1469      *            the chars to search for, may be null
    1470      * @return the <code>true</code> if any of the chars are found, <code>false</code> if no match or null input
    1471      * @since 2.4
    1472      */
    1473     public static boolean containsAny(String str, String searchChars) {
    1474         if (searchChars == null) {
    1475             return false;
    1476         }
    1477         return containsAny(str, searchChars.toCharArray());
    1478     }
    1479 
    1480     // IndexOfAnyBut chars
    1481     //-----------------------------------------------------------------------
    1482     /**
    1483      * <p>Search a String to find the first index of any
    1484      * character not in the given set of characters.</p>
    1485      *
    1486      * <p>A <code>null</code> String will return <code>-1</code>.
    1487      * A <code>null</code> or zero length search array will return <code>-1</code>.</p>
    1488      *
    1489      * <pre>
    1490      * StringUtils.indexOfAnyBut(null, *)                              = -1
    1491      * StringUtils.indexOfAnyBut("", *)                                = -1
    1492      * StringUtils.indexOfAnyBut(*, null)                              = -1
    1493      * StringUtils.indexOfAnyBut(*, [])                                = -1
    1494      * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
    1495      * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
    1496      * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1
    1497      * </pre>
    1498      *
    1499      * @param str  the String to check, may be null
    1500      * @param searchChars  the chars to search for, may be null
    1501      * @return the index of any of the chars, -1 if no match or null input
    1502      * @since 2.0
    1503      */
    1504     public static int indexOfAnyBut(String str, char[] searchChars) {
    1505         if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {
    1506             return INDEX_NOT_FOUND;
    1507         }
    1508         int csLen = str.length();
    1509         int csLast = csLen - 1;
    1510         int searchLen = searchChars.length;
    1511         int searchLast = searchLen - 1;
    1512         outer:
    1513         for (int i = 0; i < csLen; i++) {
    1514             char ch = str.charAt(i);
    1515             for (int j = 0; j < searchLen; j++) {
    1516                 if (searchChars[j] == ch) {
    1517                     if (i < csLast && j < searchLast && CharUtils.isHighSurrogate(ch)) {
    1518                         if (searchChars[j + 1] == str.charAt(i + 1)) {
    1519                             continue outer;
    1520                         }
    1521                     } else {
    1522                         continue outer;
    1523                     }
    1524                 }
    1525             }
    1526             return i;
    1527         }
    1528         return INDEX_NOT_FOUND;
    1529     }
    1530 
    1531     /**
    1532      * <p>Search a String to find the first index of any
    1533      * character not in the given set of characters.</p>
    1534      *
    1535      * <p>A <code>null</code> String will return <code>-1</code>.
    1536      * A <code>null</code> or empty search string will return <code>-1</code>.</p>
    1537      *
    1538      * <pre>
    1539      * StringUtils.indexOfAnyBut(null, *)            = -1
    1540      * StringUtils.indexOfAnyBut("", *)              = -1
    1541      * StringUtils.indexOfAnyBut(*, null)            = -1
    1542      * StringUtils.indexOfAnyBut(*, "")              = -1
    1543      * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
    1544      * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
    1545      * StringUtils.indexOfAnyBut("aba","ab")         = -1
    1546      * </pre>
    1547      *
    1548      * @param str  the String to check, may be null
    1549      * @param searchChars  the chars to search for, may be null
    1550      * @return the index of any of the chars, -1 if no match or null input
    1551      * @since 2.0
    1552      */
    1553     public static int indexOfAnyBut(String str, String searchChars) {
    1554         if (isEmpty(str) || isEmpty(searchChars)) {
    1555             return INDEX_NOT_FOUND;
    1556         }
    1557         int strLen = str.length();
    1558         for (int i = 0; i < strLen; i++) {
    1559             char ch = str.charAt(i);
    1560             boolean chFound = searchChars.indexOf(ch) >= 0;
    1561             if (i + 1 < strLen && CharUtils.isHighSurrogate(ch)) {
    1562                 char ch2 = str.charAt(i + 1);
    1563                 if (chFound && searchChars.indexOf(ch2) < 0) {
    1564                     return i;
    1565                 }
    1566             } else {
    1567                 if (!chFound) {
    1568                     return i;
    1569                 }
    1570             }
    1571         }
    1572         return INDEX_NOT_FOUND;
    1573     }
    1574 
    1575     // ContainsOnly
    1576     //-----------------------------------------------------------------------
    1577     /**
    1578      * <p>Checks if the String contains only certain characters.</p>
    1579      *
    1580      * <p>A <code>null</code> String will return <code>false</code>.
    1581      * A <code>null</code> valid character array will return <code>false</code>.
    1582      * An empty String (length()=0) always returns <code>true</code>.</p>
    1583      *
    1584      * <pre>
    1585      * StringUtils.containsOnly(null, *)       = false
    1586      * StringUtils.containsOnly(*, null)       = false
    1587      * StringUtils.containsOnly("", *)         = true
    1588      * StringUtils.containsOnly("ab", '')      = false
    1589      * StringUtils.containsOnly("abab", 'abc') = true
    1590      * StringUtils.containsOnly("ab1", 'abc')  = false
    1591      * StringUtils.containsOnly("abz", 'abc')  = false
    1592      * </pre>
    1593      *
    1594      * @param str  the String to check, may be null
    1595      * @param valid  an array of valid chars, may be null
    1596      * @return true if it only contains valid chars and is non-null
    1597      */
    1598     public static boolean containsOnly(String str, char[] valid) {
    1599         // All these pre-checks are to maintain API with an older version
    1600         if ((valid == null) || (str == null)) {
    1601             return false;
    1602         }
    1603         if (str.length() == 0) {
    1604             return true;
    1605         }
    1606         if (valid.length == 0) {
    1607             return false;
    1608         }
    1609         return indexOfAnyBut(str, valid) == INDEX_NOT_FOUND;
    1610     }
    1611 
    1612     /**
    1613      * <p>Checks if the String contains only certain characters.</p>
    1614      *
    1615      * <p>A <code>null</code> String will return <code>false</code>.
    1616      * A <code>null</code> valid character String will return <code>false</code>.
    1617      * An empty String (length()=0) always returns <code>true</code>.</p>
    1618      *
    1619      * <pre>
    1620      * StringUtils.containsOnly(null, *)       = false
    1621      * StringUtils.containsOnly(*, null)       = false
    1622      * StringUtils.containsOnly("", *)         = true
    1623      * StringUtils.containsOnly("ab", "")      = false
    1624      * StringUtils.containsOnly("abab", "abc") = true
    1625      * StringUtils.containsOnly("ab1", "abc")  = false
    1626      * StringUtils.containsOnly("abz", "abc")  = false
    1627      * </pre>
    1628      *
    1629      * @param str  the String to check, may be null
    1630      * @param validChars  a String of valid chars, may be null
    1631      * @return true if it only contains valid chars and is non-null
    1632      * @since 2.0
    1633      */
    1634     public static boolean containsOnly(String str, String validChars) {
    1635         if (str == null || validChars == null) {
    1636             return false;
    1637         }
    1638         return containsOnly(str, validChars.toCharArray());
    1639     }
    1640 
    1641     // ContainsNone
    1642     //-----------------------------------------------------------------------
    1643     /**
    1644      * <p>Checks that the String does not contain certain characters.</p>
    1645      *
    1646      * <p>A <code>null</code> String will return <code>true</code>.
    1647      * A <code>null</code> invalid character array will return <code>true</code>.
    1648      * An empty String (length()=0) always returns true.</p>
    1649      *
    1650      * <pre>
    1651      * StringUtils.containsNone(null, *)       = true
    1652      * StringUtils.containsNone(*, null)       = true
    1653      * StringUtils.containsNone("", *)         = true
    1654      * StringUtils.containsNone("ab", '')      = true
    1655      * StringUtils.containsNone("abab", 'xyz') = true
    1656      * StringUtils.containsNone("ab1", 'xyz')  = true
    1657      * StringUtils.containsNone("abz", 'xyz')  = false
    1658      * </pre>
    1659      *
    1660      * @param str  the String to check, may be null
    1661      * @param searchChars  an array of invalid chars, may be null
    1662      * @return true if it contains none of the invalid chars, or is null
    1663      * @since 2.0
    1664      */
    1665     public static boolean containsNone(String str, char[] searchChars) {
    1666         if (str == null || searchChars == null) {
    1667             return true;
    1668         }
    1669         int csLen = str.length();
    1670         int csLast = csLen - 1;
    1671         int searchLen = searchChars.length;
    1672         int searchLast = searchLen - 1;
    1673         for (int i = 0; i < csLen; i++) {
    1674             char ch = str.charAt(i);
    1675             for (int j = 0; j < searchLen; j++) {
    1676                 if (searchChars[j] == ch) {
    1677                     if (CharUtils.isHighSurrogate(ch)) {
    1678                         if (j == searchLast) {
    1679                             // missing low surrogate, fine, like String.indexOf(String)
    1680                             return false;
    1681                         }
    1682                         if (i < csLast && searchChars[j + 1] == str.charAt(i + 1)) {
    1683                             return false;
    1684                         }
    1685                     } else {
    1686                         // ch is in the Basic Multilingual Plane
    1687                         return false;
    1688                     }
    1689                 }
    1690             }
    1691         }
    1692         return true;
    1693     }
    1694 
    1695     /**
    1696      * <p>Checks that the String does not contain certain characters.</p>
    1697      *
    1698      * <p>A <code>null</code> String will return <code>true</code>.
    1699      * A <code>null</code> invalid character array will return <code>true</code>.
    1700      * An empty String ("") always returns true.</p>
    1701      *
    1702      * <pre>
    1703      * StringUtils.containsNone(null, *)       = true
    1704      * StringUtils.containsNone(*, null)       = true
    1705      * StringUtils.containsNone("", *)         = true
    1706      * StringUtils.containsNone("ab", "")      = true
    1707      * StringUtils.containsNone("abab", "xyz") = true
    1708      * StringUtils.containsNone("ab1", "xyz")  = true
    1709      * StringUtils.containsNone("abz", "xyz")  = false
    1710      * </pre>
    1711      *
    1712      * @param str  the String to check, may be null
    1713      * @param invalidChars  a String of invalid chars, may be null
    1714      * @return true if it contains none of the invalid chars, or is null
    1715      * @since 2.0
    1716      */
    1717     public static boolean containsNone(String str, String invalidChars) {
    1718         if (str == null || invalidChars == null) {
    1719             return true;
    1720         }
    1721         return containsNone(str, invalidChars.toCharArray());
    1722     }
    1723 
    1724     // IndexOfAny strings
    1725     //-----------------------------------------------------------------------
    1726     /**
    1727      * <p>Find the first index of any of a set of potential substrings.</p>
    1728      *
    1729      * <p>A <code>null</code> String will return <code>-1</code>.
    1730      * A <code>null</code> or zero length search array will return <code>-1</code>.
    1731      * A <code>null</code> search array entry will be ignored, but a search
    1732      * array containing "" will return <code>0</code> if <code>str</code> is not
    1733      * null. This method uses {@link String#indexOf(String)}.</p>
    1734      *
    1735      * <pre>
    1736      * StringUtils.indexOfAny(null, *)                     = -1
    1737      * StringUtils.indexOfAny(*, null)                     = -1
    1738      * StringUtils.indexOfAny(*, [])                       = -1
    1739      * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"])   = 2
    1740      * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"])   = 2
    1741      * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"])   = -1
    1742      * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
    1743      * StringUtils.indexOfAny("zzabyycdxx", [""])          = 0
    1744      * StringUtils.indexOfAny("", [""])                    = 0
    1745      * StringUtils.indexOfAny("", ["a"])                   = -1
    1746      * </pre>
    1747      *
    1748      * @param str  the String to check, may be null
    1749      * @param searchStrs  the Strings to search for, may be null
    1750      * @return the first index of any of the searchStrs in str, -1 if no match
    1751      */
    1752     public static int indexOfAny(String str, String[] searchStrs) {
    1753         if ((str == null) || (searchStrs == null)) {
    1754             return INDEX_NOT_FOUND;
    1755         }
    1756         int sz = searchStrs.length;
    1757 
    1758         // String's can't have a MAX_VALUEth index.
    1759         int ret = Integer.MAX_VALUE;
    1760 
    1761         int tmp = 0;
    1762         for (int i = 0; i < sz; i++) {
    1763             String search = searchStrs[i];
    1764             if (search == null) {
    1765                 continue;
    1766             }
    1767             tmp = str.indexOf(search);
    1768             if (tmp == INDEX_NOT_FOUND) {
    1769                 continue;
    1770             }
    1771 
    1772             if (tmp < ret) {
    1773                 ret = tmp;
    1774             }
    1775         }
    1776 
    1777         return (ret == Integer.MAX_VALUE) ? INDEX_NOT_FOUND : ret;
    1778     }
    1779 
    1780     /**
    1781      * <p>Find the latest index of any of a set of potential substrings.</p>
    1782      *
    1783      * <p>A <code>null</code> String will return <code>-1</code>.
    1784      * A <code>null</code> search array will return <code>-1</code>.
    1785      * A <code>null</code> or zero length search array entry will be ignored,
    1786      * but a search array containing "" will return the length of <code>str</code>
    1787      * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>
    1788      *
    1789      * <pre>
    1790      * StringUtils.lastIndexOfAny(null, *)                   = -1
    1791      * StringUtils.lastIndexOfAny(*, null)                   = -1
    1792      * StringUtils.lastIndexOfAny(*, [])                     = -1
    1793      * StringUtils.lastIndexOfAny(*, [null])                 = -1
    1794      * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
    1795      * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
    1796      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
    1797      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
    1798      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""])   = 10
    1799      * </pre>
    1800      *
    1801      * @param str  the String to check, may be null
    1802      * @param searchStrs  the Strings to search for, may be null
    1803      * @return the last index of any of the Strings, -1 if no match
    1804      */
    1805     public static int lastIndexOfAny(String str, String[] searchStrs) {
    1806         if ((str == null) || (searchStrs == null)) {
    1807             return INDEX_NOT_FOUND;
    1808         }
    1809         int sz = searchStrs.length;
    1810         int ret = INDEX_NOT_FOUND;
    1811         int tmp = 0;
    1812         for (int i = 0; i < sz; i++) {
    1813             String search = searchStrs[i];
    1814             if (search == null) {
    1815                 continue;
    1816             }
    1817             tmp = str.lastIndexOf(search);
    1818             if (tmp > ret) {
    1819                 ret = tmp;
    1820             }
    1821         }
    1822         return ret;
    1823     }
    1824 
    1825     // Substring
    1826     //-----------------------------------------------------------------------
    1827     /**
    1828      * <p>Gets a substring from the specified String avoiding exceptions.</p>
    1829      *
    1830      * <p>A negative start position can be used to start <code>n</code>
    1831      * characters from the end of the String.</p>
    1832      *
    1833      * <p>A <code>null</code> String will return <code>null</code>.
    1834      * An empty ("") String will return "".</p>
    1835      *
    1836      * <pre>
    1837      * StringUtils.substring(null, *)   = null
    1838      * StringUtils.substring("", *)     = ""
    1839      * StringUtils.substring("abc", 0)  = "abc"
    1840      * StringUtils.substring("abc", 2)  = "c"
    1841      * StringUtils.substring("abc", 4)  = ""
    1842      * StringUtils.substring("abc", -2) = "bc"
    1843      * StringUtils.substring("abc", -4) = "abc"
    1844      * </pre>
    1845      *
    1846      * @param str  the String to get the substring from, may be null
    1847      * @param start  the position to start from, negative means
    1848      *  count back from the end of the String by this many characters
    1849      * @return substring from start position, <code>null</code> if null String input
    1850      */
    1851     public static String substring(String str, int start) {
    1852         if (str == null) {
    1853             return null;
    1854         }
    1855 
    1856         // handle negatives, which means last n characters
    1857         if (start < 0) {
    1858             start = str.length() + start; // remember start is negative
    1859         }
    1860 
    1861         if (start < 0) {
    1862             start = 0;
    1863         }
    1864         if (start > str.length()) {
    1865             return EMPTY;
    1866         }
    1867 
    1868         return str.substring(start);
    1869     }
    1870 
    1871     /**
    1872      * <p>Gets a substring from the specified String avoiding exceptions.</p>
    1873      *
    1874      * <p>A negative start position can be used to start/end <code>n</code>
    1875      * characters from the end of the String.</p>
    1876      *
    1877      * <p>The returned substring starts with the character in the <code>start</code>
    1878      * position and ends before the <code>end</code> position. All position counting is
    1879      * zero-based -- i.e., to start at the beginning of the string use
    1880      * <code>start = 0</code>. Negative start and end positions can be used to
    1881      * specify offsets relative to the end of the String.</p>
    1882      *
    1883      * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""
    1884      * is returned.</p>
    1885      *
    1886      * <pre>
    1887      * StringUtils.substring(null, *, *)    = null
    1888      * StringUtils.substring("", * ,  *)    = "";
    1889      * StringUtils.substring("abc", 0, 2)   = "ab"
    1890      * StringUtils.substring("abc", 2, 0)   = ""
    1891      * StringUtils.substring("abc", 2, 4)   = "c"
    1892      * StringUtils.substring("abc", 4, 6)   = ""
    1893      * StringUtils.substring("abc", 2, 2)   = ""
    1894      * StringUtils.substring("abc", -2, -1) = "b"
    1895      * StringUtils.substring("abc", -4, 2)  = "ab"
    1896      * </pre>
    1897      *
    1898      * @param str  the String to get the substring from, may be null
    1899      * @param start  the position to start from, negative means
    1900      *  count back from the end of the String by this many characters
    1901      * @param end  the position to end at (exclusive), negative means
    1902      *  count back from the end of the String by this many characters
    1903      * @return substring from start position to end positon,
    1904      *  <code>null</code> if null String input
    1905      */
    1906     public static String substring(String str, int start, int end) {
    1907         if (str == null) {
    1908             return null;
    1909         }
    1910 
    1911         // handle negatives
    1912         if (end < 0) {
    1913             end = str.length() + end; // remember end is negative
    1914         }
    1915         if (start < 0) {
    1916             start = str.length() + start; // remember start is negative
    1917         }
    1918 
    1919         // check length next
    1920         if (end > str.length()) {
    1921             end = str.length();
    1922         }
    1923 
    1924         // if start is greater than end, return ""
    1925         if (start > end) {
    1926             return EMPTY;
    1927         }
    1928 
    1929         if (start < 0) {
    1930             start = 0;
    1931         }
    1932         if (end < 0) {
    1933             end = 0;
    1934         }
    1935 
    1936         return str.substring(start, end);
    1937     }
    1938 
    1939     // Left/Right/Mid
    1940     //-----------------------------------------------------------------------
    1941     /**
    1942      * <p>Gets the leftmost <code>len</code> characters of a String.</p>
    1943      *
    1944      * <p>If <code>len</code> characters are not available, or the
    1945      * String is <code>null</code>, the String will be returned without
    1946      * an exception. An empty String is returned if len is negative.</p>
    1947      *
    1948      * <pre>
    1949      * StringUtils.left(null, *)    = null
    1950      * StringUtils.left(*, -ve)     = ""
    1951      * StringUtils.left("", *)      = ""
    1952      * StringUtils.left("abc", 0)   = ""
    1953      * StringUtils.left("abc", 2)   = "ab"
    1954      * StringUtils.left("abc", 4)   = "abc"
    1955      * </pre>
    1956      *
    1957      * @param str  the String to get the leftmost characters from, may be null
    1958      * @param len  the length of the required String
    1959      * @return the leftmost characters, <code>null</code> if null String input
    1960      */
    1961     public static String left(String str, int len) {
    1962         if (str == null) {
    1963             return null;
    1964         }
    1965         if (len < 0) {
    1966             return EMPTY;
    1967         }
    1968         if (str.length() <= len) {
    1969             return str;
    1970         }
    1971         return str.substring(0, len);
    1972     }
    1973 
    1974     /**
    1975      * <p>Gets the rightmost <code>len</code> characters of a String.</p>
    1976      *
    1977      * <p>If <code>len</code> characters are not available, or the String
    1978      * is <code>null</code>, the String will be returned without an
    1979      * an exception. An empty String is returned if len is negative.</p>
    1980      *
    1981      * <pre>
    1982      * StringUtils.right(null, *)    = null
    1983      * StringUtils.right(*, -ve)     = ""
    1984      * StringUtils.right("", *)      = ""
    1985      * StringUtils.right("abc", 0)   = ""
    1986      * StringUtils.right("abc", 2)   = "bc"
    1987      * StringUtils.right("abc", 4)   = "abc"
    1988      * </pre>
    1989      *
    1990      * @param str  the String to get the rightmost characters from, may be null
    1991      * @param len  the length of the required String
    1992      * @return the rightmost characters, <code>null</code> if null String input
    1993      */
    1994     public static String right(String str, int len) {
    1995         if (str == null) {
    1996             return null;
    1997         }
    1998         if (len < 0) {
    1999             return EMPTY;
    2000         }
    2001         if (str.length() <= len) {
    2002             return str;
    2003         }
    2004         return str.substring(str.length() - len);
    2005     }
    2006 
    2007     /**
    2008      * <p>Gets <code>len</code> characters from the middle of a String.</p>
    2009      *
    2010      * <p>If <code>len</code> characters are not available, the remainder
    2011      * of the String will be returned without an exception. If the
    2012      * String is <code>null</code>, <code>null</code> will be returned.
    2013      * An empty String is returned if len is negative or exceeds the
    2014      * length of <code>str</code>.</p>
    2015      *
    2016      * <pre>
    2017      * StringUtils.mid(null, *, *)    = null
    2018      * StringUtils.mid(*, *, -ve)     = ""
    2019      * StringUtils.mid("", 0, *)      = ""
    2020      * StringUtils.mid("abc", 0, 2)   = "ab"
    2021      * StringUtils.mid("abc", 0, 4)   = "abc"
    2022      * StringUtils.mid("abc", 2, 4)   = "c"
    2023      * StringUtils.mid("abc", 4, 2)   = ""
    2024      * StringUtils.mid("abc", -2, 2)  = "ab"
    2025      * </pre>
    2026      *
    2027      * @param str  the String to get the characters from, may be null
    2028      * @param pos  the position to start from, negative treated as zero
    2029      * @param len  the length of the required String
    2030      * @return the middle characters, <code>null</code> if null String input
    2031      */
    2032     public static String mid(String str, int pos, int len) {
    2033         if (str == null) {
    2034             return null;
    2035         }
    2036         if (len < 0 || pos > str.length()) {
    2037             return EMPTY;
    2038         }
    2039         if (pos < 0) {
    2040             pos = 0;
    2041         }
    2042         if (str.length() <= (pos + len)) {
    2043             return str.substring(pos);
    2044         }
    2045         return str.substring(pos, pos + len);
    2046     }
    2047 
    2048     // SubStringAfter/SubStringBefore
    2049     //-----------------------------------------------------------------------
    2050     /**
    2051      * <p>Gets the substring before the first occurrence of a separator.
    2052      * The separator is not returned.</p>
    2053      *
    2054      * <p>A <code>null</code> string input will return <code>null</code>.
    2055      * An empty ("") string input will return the empty string.
    2056      * A <code>null</code> separator will return the input string.</p>
    2057      *
    2058      * <p>If nothing is found, the string input is returned.</p>
    2059      *
    2060      * <pre>
    2061      * StringUtils.substringBefore(null, *)      = null
    2062      * StringUtils.substringBefore("", *)        = ""
    2063      * StringUtils.substringBefore("abc", "a")   = ""
    2064      * StringUtils.substringBefore("abcba", "b") = "a"
    2065      * StringUtils.substringBefore("abc", "c")   = "ab"
    2066      * StringUtils.substringBefore("abc", "d")   = "abc"
    2067      * StringUtils.substringBefore("abc", "")    = ""
    2068      * StringUtils.substringBefore("abc", null)  = "abc"
    2069      * </pre>
    2070      *
    2071      * @param str  the String to get a substring from, may be null
    2072      * @param separator  the String to search for, may be null
    2073      * @return the substring before the first occurrence of the separator,
    2074      *  <code>null</code> if null String input
    2075      * @since 2.0
    2076      */
    2077     public static String substringBefore(String str, String separator) {
    2078         if (isEmpty(str) || separator == null) {
    2079             return str;
    2080         }
    2081         if (separator.length() == 0) {
    2082             return EMPTY;
    2083         }
    2084         int pos = str.indexOf(separator);
    2085         if (pos == INDEX_NOT_FOUND) {
    2086             return str;
    2087         }
    2088         return str.substring(0, pos);
    2089     }
    2090 
    2091     /**
    2092      * <p>Gets the substring after the first occurrence of a separator.
    2093      * The separator is not returned.</p>
    2094      *
    2095      * <p>A <code>null</code> string input will return <code>null</code>.
    2096      * An empty ("") string input will return the empty string.
    2097      * A <code>null</code> separator will return the empty string if the
    2098      * input string is not <code>null</code>.</p>
    2099      *
    2100      * <p>If nothing is found, the empty string is returned.</p>
    2101      *
    2102      * <pre>
    2103      * StringUtils.substringAfter(null, *)      = null
    2104      * StringUtils.substringAfter("", *)        = ""
    2105      * StringUtils.substringAfter(*, null)      = ""
    2106      * StringUtils.substringAfter("abc", "a")   = "bc"
    2107      * StringUtils.substringAfter("abcba", "b") = "cba"
    2108      * StringUtils.substringAfter("abc", "c")   = ""
    2109      * StringUtils.substringAfter("abc", "d")   = ""
    2110      * StringUtils.substringAfter("abc", "")    = "abc"
    2111      * </pre>
    2112      *
    2113      * @param str  the String to get a substring from, may be null
    2114      * @param separator  the String to search for, may be null
    2115      * @return the substring after the first occurrence of the separator,
    2116      *  <code>null</code> if null String input
    2117      * @since 2.0
    2118      */
    2119     public static String substringAfter(String str, String separator) {
    2120         if (isEmpty(str)) {
    2121             return str;
    2122         }
    2123         if (separator == null) {
    2124             return EMPTY;
    2125         }
    2126         int pos = str.indexOf(separator);
    2127         if (pos == INDEX_NOT_FOUND) {
    2128             return EMPTY;
    2129         }
    2130         return str.substring(pos + separator.length());
    2131     }
    2132 
    2133     /**
    2134      * <p>Gets the substring before the last occurrence of a separator.
    2135      * The separator is not returned.</p>
    2136      *
    2137      * <p>A <code>null</code> string input will return <code>null</code>.
    2138      * An empty ("") string input will return the empty string.
    2139      * An empty or <code>null</code> separator will return the input string.</p>
    2140      *
    2141      * <p>If nothing is found, the string input is returned.</p>
    2142      *
    2143      * <pre>
    2144      * StringUtils.substringBeforeLast(null, *)      = null
    2145      * StringUtils.substringBeforeLast("", *)        = ""
    2146      * StringUtils.substringBeforeLast("abcba", "b") = "abc"
    2147      * StringUtils.substringBeforeLast("abc", "c")   = "ab"
    2148      * StringUtils.substringBeforeLast("a", "a")     = ""
    2149      * StringUtils.substringBeforeLast("a", "z")     = "a"
    2150      * StringUtils.substringBeforeLast("a", null)    = "a"
    2151      * StringUtils.substringBeforeLast("a", "")      = "a"
    2152      * </pre>
    2153      *
    2154      * @param str  the String to get a substring from, may be null
    2155      * @param separator  the String to search for, may be null
    2156      * @return the substring before the last occurrence of the separator,
    2157      *  <code>null</code> if null String input
    2158      * @since 2.0
    2159      */
    2160     public static String substringBeforeLast(String str, String separator) {
    2161         if (isEmpty(str) || isEmpty(separator)) {
    2162             return str;
    2163         }
    2164         int pos = str.lastIndexOf(separator);
    2165         if (pos == INDEX_NOT_FOUND) {
    2166             return str;
    2167         }
    2168         return str.substring(0, pos);
    2169     }
    2170 
    2171     /**
    2172      * <p>Gets the substring after the last occurrence of a separator.
    2173      * The separator is not returned.</p>
    2174      *
    2175      * <p>A <code>null</code> string input will return <code>null</code>.
    2176      * An empty ("") string input will return the empty string.
    2177      * An empty or <code>null</code> separator will return the empty string if
    2178      * the input string is not <code>null</code>.</p>
    2179      *
    2180      * <p>If nothing is found, the empty string is returned.</p>
    2181      *
    2182      * <pre>
    2183      * StringUtils.substringAfterLast(null, *)      = null
    2184      * StringUtils.substringAfterLast("", *)        = ""
    2185      * StringUtils.substringAfterLast(*, "")        = ""
    2186      * StringUtils.substringAfterLast(*, null)      = ""
    2187      * StringUtils.substringAfterLast("abc", "a")   = "bc"
    2188      * StringUtils.substringAfterLast("abcba", "b") = "a"
    2189      * StringUtils.substringAfterLast("abc", "c")   = ""
    2190      * StringUtils.substringAfterLast("a", "a")     = ""
    2191      * StringUtils.substringAfterLast("a", "z")     = ""
    2192      * </pre>
    2193      *
    2194      * @param str  the String to get a substring from, may be null
    2195      * @param separator  the String to search for, may be null
    2196      * @return the substring after the last occurrence of the separator,
    2197      *  <code>null</code> if null String input
    2198      * @since 2.0
    2199      */
    2200     public static String substringAfterLast(String str, String separator) {
    2201         if (isEmpty(str)) {
    2202             return str;
    2203         }
    2204         if (isEmpty(separator)) {
    2205             return EMPTY;
    2206         }
    2207         int pos = str.lastIndexOf(separator);
    2208         if (pos == INDEX_NOT_FOUND || pos == (str.length() - separator.length())) {
    2209             return EMPTY;
    2210         }
    2211         return str.substring(pos + separator.length());
    2212     }
    2213 
    2214     // Substring between
    2215     //-----------------------------------------------------------------------
    2216     /**
    2217      * <p>Gets the String that is nested in between two instances of the
    2218      * same String.</p>
    2219      *
    2220      * <p>A <code>null</code> input String returns <code>null</code>.
    2221      * A <code>null</code> tag returns <code>null</code>.</p>
    2222      *
    2223      * <pre>
    2224      * StringUtils.substringBetween(null, *)            = null
    2225      * StringUtils.substringBetween("", "")             = ""
    2226      * StringUtils.substringBetween("", "tag")          = null
    2227      * StringUtils.substringBetween("tagabctag", null)  = null
    2228      * StringUtils.substringBetween("tagabctag", "")    = ""
    2229      * StringUtils.substringBetween("tagabctag", "tag") = "abc"
    2230      * </pre>
    2231      *
    2232      * @param str  the String containing the substring, may be null
    2233      * @param tag  the String before and after the substring, may be null
    2234      * @return the substring, <code>null</code> if no match
    2235      * @since 2.0
    2236      */
    2237     public static String substringBetween(String str, String tag) {
    2238         return substringBetween(str, tag, tag);
    2239     }
    2240 
    2241     /**
    2242      * <p>Gets the String that is nested in between two Strings.
    2243      * Only the first match is returned.</p>
    2244      *
    2245      * <p>A <code>null</code> input String returns <code>null</code>.
    2246      * A <code>null</code> open/close returns <code>null</code> (no match).
    2247      * An empty ("") open and close returns an empty string.</p>
    2248      *
    2249      * <pre>
    2250      * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
    2251      * StringUtils.substringBetween(null, *, *)          = null
    2252      * StringUtils.substringBetween(*, null, *)          = null
    2253      * StringUtils.substringBetween(*, *, null)          = null
    2254      * StringUtils.substringBetween("", "", "")          = ""
    2255      * StringUtils.substringBetween("", "", "]")         = null
    2256      * StringUtils.substringBetween("", "[", "]")        = null
    2257      * StringUtils.substringBetween("yabcz", "", "")     = ""
    2258      * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
    2259      * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
    2260      * </pre>
    2261      *
    2262      * @param str  the String containing the substring, may be null
    2263      * @param open  the String before the substring, may be null
    2264      * @param close  the String after the substring, may be null
    2265      * @return the substring, <code>null</code> if no match
    2266      * @since 2.0
    2267      */
    2268     public static String substringBetween(String str, String open, String close) {
    2269         if (str == null || open == null || close == null) {
    2270             return null;
    2271         }
    2272         int start = str.indexOf(open);
    2273         if (start != INDEX_NOT_FOUND) {
    2274             int end = str.indexOf(close, start + open.length());
    2275             if (end != INDEX_NOT_FOUND) {
    2276                 return str.substring(start + open.length(), end);
    2277             }
    2278         }
    2279         return null;
    2280     }
    2281 
    2282     /**
    2283      * <p>Searches a String for substrings delimited by a start and end tag,
    2284      * returning all matching substrings in an array.</p>
    2285      *
    2286      * <p>A <code>null</code> input String returns <code>null</code>.
    2287      * A <code>null</code> open/close returns <code>null</code> (no match).
    2288      * An empty ("") open/close returns <code>null</code> (no match).</p>
    2289      *
    2290      * <pre>
    2291      * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
    2292      * StringUtils.substringsBetween(null, *, *)            = null
    2293      * StringUtils.substringsBetween(*, null, *)            = null
    2294      * StringUtils.substringsBetween(*, *, null)            = null
    2295      * StringUtils.substringsBetween("", "[", "]")          = []
    2296      * </pre>
    2297      *
    2298      * @param str  the String containing the substrings, null returns null, empty returns empty
    2299      * @param open  the String identifying the start of the substring, empty returns null
    2300      * @param close  the String identifying the end of the substring, empty returns null
    2301      * @return a String Array of substrings, or <code>null</code> if no match
    2302      * @since 2.3
    2303      */
    2304     public static String[] substringsBetween(String str, String open, String close) {
    2305         if (str == null || isEmpty(open) || isEmpty(close)) {
    2306             return null;
    2307         }
    2308         int strLen = str.length();
    2309         if (strLen == 0) {
    2310             return ArrayUtils.EMPTY_STRING_ARRAY;
    2311         }
    2312         int closeLen = close.length();
    2313         int openLen = open.length();
    2314         List list = new ArrayList();
    2315         int pos = 0;
    2316         while (pos < (strLen - closeLen)) {
    2317             int start = str.indexOf(open, pos);
    2318             if (start < 0) {
    2319                 break;
    2320             }
    2321             start += openLen;
    2322             int end = str.indexOf(close, start);
    2323             if (end < 0) {
    2324                 break;
    2325             }
    2326             list.add(str.substring(start, end));
    2327             pos = end + closeLen;
    2328         }
    2329         if (list.isEmpty()) {
    2330             return null;
    2331         } 
    2332         return (String[]) list.toArray(new String [list.size()]);
    2333     }
    2334 
    2335     // Nested extraction
    2336     //-----------------------------------------------------------------------
    2337     /**
    2338      * <p>Gets the String that is nested in between two instances of the
    2339      * same String.</p>
    2340      *
    2341      * <p>A <code>null</code> input String returns <code>null</code>.
    2342      * A <code>null</code> tag returns <code>null</code>.</p>
    2343      *
    2344      * <pre>
    2345      * StringUtils.getNestedString(null, *)            = null
    2346      * StringUtils.getNestedString("", "")             = ""
    2347      * StringUtils.getNestedString("", "tag")          = null
    2348      * StringUtils.getNestedString("tagabctag", null)  = null
    2349      * StringUtils.getNestedString("tagabctag", "")    = ""
    2350      * StringUtils.getNestedString("tagabctag", "tag") = "abc"
    2351      * </pre>
    2352      *
    2353      * @param str  the String containing nested-string, may be null
    2354      * @param tag  the String before and after nested-string, may be null
    2355      * @return the nested String, <code>null</code> if no match
    2356      * @deprecated Use the better named {@link #substringBetween(String, String)}.
    2357      *             Method will be removed in Commons Lang 3.0.
    2358      */
    2359     public static String getNestedString(String str, String tag) {
    2360         return substringBetween(str, tag, tag);
    2361     }
    2362 
    2363     /**
    2364      * <p>Gets the String that is nested in between two Strings.
    2365      * Only the first match is returned.</p>
    2366      *
    2367      * <p>A <code>null</code> input String returns <code>null</code>.
    2368      * A <code>null</code> open/close returns <code>null</code> (no match).
    2369      * An empty ("") open/close returns an empty string.</p>
    2370      *
    2371      * <pre>
    2372      * StringUtils.getNestedString(null, *, *)          = null
    2373      * StringUtils.getNestedString("", "", "")          = ""
    2374      * StringUtils.getNestedString("", "", "tag")       = null
    2375      * StringUtils.getNestedString("", "tag", "tag")    = null
    2376      * StringUtils.getNestedString("yabcz", null, null) = null
    2377      * StringUtils.getNestedString("yabcz", "", "")     = ""
    2378      * StringUtils.getNestedString("yabcz", "y", "z")   = "abc"
    2379      * StringUtils.getNestedString("yabczyabcz", "y", "z")   = "abc"
    2380      * </pre>
    2381      *
    2382      * @param str  the String containing nested-string, may be null
    2383      * @param open  the String before nested-string, may be null
    2384      * @param close  the String after nested-string, may be null
    2385      * @return the nested String, <code>null</code> if no match
    2386      * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
    2387      *             Method will be removed in Commons Lang 3.0.
    2388      */
    2389     public static String getNestedString(String str, String open, String close) {
    2390         return substringBetween(str, open, close);
    2391     }
    2392 
    2393     // Splitting
    2394     //-----------------------------------------------------------------------
    2395     /**
    2396      * <p>Splits the provided text into an array, using whitespace as the
    2397      * separator.
    2398      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2399      *
    2400      * <p>The separator is not included in the returned String array.
    2401      * Adjacent separators are treated as one separator.
    2402      * For more control over the split use the StrTokenizer class.</p>
    2403      *
    2404      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2405      *
    2406      * <pre>
    2407      * StringUtils.split(null)       = null
    2408      * StringUtils.split("")         = []
    2409      * StringUtils.split("abc def")  = ["abc", "def"]
    2410      * StringUtils.split("abc  def") = ["abc", "def"]
    2411      * StringUtils.split(" abc ")    = ["abc"]
    2412      * </pre>
    2413      *
    2414      * @param str  the String to parse, may be null
    2415      * @return an array of parsed Strings, <code>null</code> if null String input
    2416      */
    2417     public static String[] split(String str) {
    2418         return split(str, null, -1);
    2419     }
    2420 
    2421     /**
    2422      * <p>Splits the provided text into an array, separator specified.
    2423      * This is an alternative to using StringTokenizer.</p>
    2424      *
    2425      * <p>The separator is not included in the returned String array.
    2426      * Adjacent separators are treated as one separator.
    2427      * For more control over the split use the StrTokenizer class.</p>
    2428      *
    2429      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2430      *
    2431      * <pre>
    2432      * StringUtils.split(null, *)         = null
    2433      * StringUtils.split("", *)           = []
    2434      * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
    2435      * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
    2436      * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
    2437      * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
    2438      * </pre>
    2439      *
    2440      * @param str  the String to parse, may be null
    2441      * @param separatorChar  the character used as the delimiter
    2442      * @return an array of parsed Strings, <code>null</code> if null String input
    2443      * @since 2.0
    2444      */
    2445     public static String[] split(String str, char separatorChar) {
    2446         return splitWorker(str, separatorChar, false);
    2447     }
    2448 
    2449     /**
    2450      * <p>Splits the provided text into an array, separators specified.
    2451      * This is an alternative to using StringTokenizer.</p>
    2452      *
    2453      * <p>The separator is not included in the returned String array.
    2454      * Adjacent separators are treated as one separator.
    2455      * For more control over the split use the StrTokenizer class.</p>
    2456      *
    2457      * <p>A <code>null</code> input String returns <code>null</code>.
    2458      * A <code>null</code> separatorChars splits on whitespace.</p>
    2459      *
    2460      * <pre>
    2461      * StringUtils.split(null, *)         = null
    2462      * StringUtils.split("", *)           = []
    2463      * StringUtils.split("abc def", null) = ["abc", "def"]
    2464      * StringUtils.split("abc def", " ")  = ["abc", "def"]
    2465      * StringUtils.split("abc  def", " ") = ["abc", "def"]
    2466      * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
    2467      * </pre>
    2468      *
    2469      * @param str  the String to parse, may be null
    2470      * @param separatorChars  the characters used as the delimiters,
    2471      *  <code>null</code> splits on whitespace
    2472      * @return an array of parsed Strings, <code>null</code> if null String input
    2473      */
    2474     public static String[] split(String str, String separatorChars) {
    2475         return splitWorker(str, separatorChars, -1, false);
    2476     }
    2477 
    2478     /**
    2479      * <p>Splits the provided text into an array with a maximum length,
    2480      * separators specified.</p>
    2481      *
    2482      * <p>The separator is not included in the returned String array.
    2483      * Adjacent separators are treated as one separator.</p>
    2484      *
    2485      * <p>A <code>null</code> input String returns <code>null</code>.
    2486      * A <code>null</code> separatorChars splits on whitespace.</p>
    2487      *
    2488      * <p>If more than <code>max</code> delimited substrings are found, the last
    2489      * returned string includes all characters after the first <code>max - 1</code>
    2490      * returned strings (including separator characters).</p>
    2491      *
    2492      * <pre>
    2493      * StringUtils.split(null, *, *)            = null
    2494      * StringUtils.split("", *, *)              = []
    2495      * StringUtils.split("ab de fg", null, 0)   = ["ab", "cd", "ef"]
    2496      * StringUtils.split("ab   de fg", null, 0) = ["ab", "cd", "ef"]
    2497      * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    2498      * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    2499      * </pre>
    2500      *
    2501      * @param str  the String to parse, may be null
    2502      * @param separatorChars  the characters used as the delimiters,
    2503      *  <code>null</code> splits on whitespace
    2504      * @param max  the maximum number of elements to include in the
    2505      *  array. A zero or negative value implies no limit
    2506      * @return an array of parsed Strings, <code>null</code> if null String input
    2507      */
    2508     public static String[] split(String str, String separatorChars, int max) {
    2509         return splitWorker(str, separatorChars, max, false);
    2510     }
    2511 
    2512     /**
    2513      * <p>Splits the provided text into an array, separator string specified.</p>
    2514      *
    2515      * <p>The separator(s) will not be included in the returned String array.
    2516      * Adjacent separators are treated as one separator.</p>
    2517      *
    2518      * <p>A <code>null</code> input String returns <code>null</code>.
    2519      * A <code>null</code> separator splits on whitespace.</p>
    2520      *
    2521      * <pre>
    2522      * StringUtils.splitByWholeSeparator(null, *)               = null
    2523      * StringUtils.splitByWholeSeparator("", *)                 = []
    2524      * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
    2525      * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
    2526      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    2527      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    2528      * </pre>
    2529      *
    2530      * @param str  the String to parse, may be null
    2531      * @param separator  String containing the String to be used as a delimiter,
    2532      *  <code>null</code> splits on whitespace
    2533      * @return an array of parsed Strings, <code>null</code> if null String was input
    2534      */
    2535     public static String[] splitByWholeSeparator(String str, String separator) {
    2536         return splitByWholeSeparatorWorker( str, separator, -1, false ) ;
    2537     }
    2538 
    2539     /**
    2540      * <p>Splits the provided text into an array, separator string specified.
    2541      * Returns a maximum of <code>max</code> substrings.</p>
    2542      *
    2543      * <p>The separator(s) will not be included in the returned String array.
    2544      * Adjacent separators are treated as one separator.</p>
    2545      *
    2546      * <p>A <code>null</code> input String returns <code>null</code>.
    2547      * A <code>null</code> separator splits on whitespace.</p>
    2548      *
    2549      * <pre>
    2550      * StringUtils.splitByWholeSeparator(null, *, *)               = null
    2551      * StringUtils.splitByWholeSeparator("", *, *)                 = []
    2552      * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
    2553      * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
    2554      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    2555      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    2556      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    2557      * </pre>
    2558      *
    2559      * @param str  the String to parse, may be null
    2560      * @param separator  String containing the String to be used as a delimiter,
    2561      *  <code>null</code> splits on whitespace
    2562      * @param max  the maximum number of elements to include in the returned
    2563      *  array. A zero or negative value implies no limit.
    2564      * @return an array of parsed Strings, <code>null</code> if null String was input
    2565      */
    2566     public static String[] splitByWholeSeparator( String str, String separator, int max ) {
    2567         return splitByWholeSeparatorWorker(str, separator, max, false);
    2568     }
    2569 
    2570     /**
    2571      * <p>Splits the provided text into an array, separator string specified. </p>
    2572      *
    2573      * <p>The separator is not included in the returned String array.
    2574      * Adjacent separators are treated as separators for empty tokens.
    2575      * For more control over the split use the StrTokenizer class.</p>
    2576      *
    2577      * <p>A <code>null</code> input String returns <code>null</code>.
    2578      * A <code>null</code> separator splits on whitespace.</p>
    2579      *
    2580      * <pre>
    2581      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
    2582      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
    2583      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
    2584      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
    2585      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    2586      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    2587      * </pre>
    2588      *
    2589      * @param str  the String to parse, may be null
    2590      * @param separator  String containing the String to be used as a delimiter,
    2591      *  <code>null</code> splits on whitespace
    2592      * @return an array of parsed Strings, <code>null</code> if null String was input
    2593      * @since 2.4
    2594      */
    2595     public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator) {
    2596         return splitByWholeSeparatorWorker(str, separator, -1, true);
    2597     }
    2598 
    2599     /**
    2600      * <p>Splits the provided text into an array, separator string specified.
    2601      * Returns a maximum of <code>max</code> substrings.</p>
    2602      *
    2603      * <p>The separator is not included in the returned String array.
    2604      * Adjacent separators are treated as separators for empty tokens.
    2605      * For more control over the split use the StrTokenizer class.</p>
    2606      *
    2607      * <p>A <code>null</code> input String returns <code>null</code>.
    2608      * A <code>null</code> separator splits on whitespace.</p>
    2609      *
    2610      * <pre>
    2611      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
    2612      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
    2613      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
    2614      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
    2615      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    2616      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    2617      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    2618      * </pre>
    2619      *
    2620      * @param str  the String to parse, may be null
    2621      * @param separator  String containing the String to be used as a delimiter,
    2622      *  <code>null</code> splits on whitespace
    2623      * @param max  the maximum number of elements to include in the returned
    2624      *  array. A zero or negative value implies no limit.
    2625      * @return an array of parsed Strings, <code>null</code> if null String was input
    2626      * @since 2.4
    2627      */
    2628     public static String[] splitByWholeSeparatorPreserveAllTokens(String str, String separator, int max) {
    2629         return splitByWholeSeparatorWorker(str, separator, max, true);
    2630     }
    2631 
    2632     /**
    2633      * Performs the logic for the <code>splitByWholeSeparatorPreserveAllTokens</code> methods.
    2634      *
    2635      * @param str  the String to parse, may be <code>null</code>
    2636      * @param separator  String containing the String to be used as a delimiter,
    2637      *  <code>null</code> splits on whitespace
    2638      * @param max  the maximum number of elements to include in the returned
    2639      *  array. A zero or negative value implies no limit.
    2640      * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2641      * treated as empty token separators; if <code>false</code>, adjacent
    2642      * separators are treated as one separator.
    2643      * @return an array of parsed Strings, <code>null</code> if null String input
    2644      * @since 2.4
    2645      */
    2646     private static String[] splitByWholeSeparatorWorker(String str, String separator, int max, 
    2647                                                         boolean preserveAllTokens) 
    2648     {
    2649         if (str == null) {
    2650             return null;
    2651         }
    2652 
    2653         int len = str.length();
    2654 
    2655         if (len == 0) {
    2656             return ArrayUtils.EMPTY_STRING_ARRAY;
    2657         }
    2658 
    2659         if ((separator == null) || (EMPTY.equals(separator))) {
    2660             // Split on whitespace.
    2661             return splitWorker(str, null, max, preserveAllTokens);
    2662         }
    2663 
    2664         int separatorLength = separator.length();
    2665 
    2666         ArrayList substrings = new ArrayList();
    2667         int numberOfSubstrings = 0;
    2668         int beg = 0;
    2669         int end = 0;
    2670         while (end < len) {
    2671             end = str.indexOf(separator, beg);
    2672 
    2673             if (end > -1) {
    2674                 if (end > beg) {
    2675                     numberOfSubstrings += 1;
    2676 
    2677                     if (numberOfSubstrings == max) {
    2678                         end = len;
    2679                         substrings.add(str.substring(beg));
    2680                     } else {
    2681                         // The following is OK, because String.substring( beg, end ) excludes
    2682                         // the character at the position 'end'.
    2683                         substrings.add(str.substring(beg, end));
    2684 
    2685                         // Set the starting point for the next search.
    2686                         // The following is equivalent to beg = end + (separatorLength - 1) + 1,
    2687                         // which is the right calculation:
    2688                         beg = end + separatorLength;
    2689                     }
    2690                 } else {
    2691                     // We found a consecutive occurrence of the separator, so skip it.
    2692                     if (preserveAllTokens) {
    2693                         numberOfSubstrings += 1;
    2694                         if (numberOfSubstrings == max) {
    2695                             end = len;
    2696                             substrings.add(str.substring(beg));
    2697                         } else {
    2698                             substrings.add(EMPTY);
    2699                         }
    2700                     }
    2701                     beg = end + separatorLength;
    2702                 }
    2703             } else {
    2704                 // String.substring( beg ) goes from 'beg' to the end of the String.
    2705                 substrings.add(str.substring(beg));
    2706                 end = len;
    2707             }
    2708         }
    2709 
    2710         return (String[]) substrings.toArray(new String[substrings.size()]);
    2711     }
    2712 
    2713     // -----------------------------------------------------------------------
    2714     /**
    2715      * <p>Splits the provided text into an array, using whitespace as the
    2716      * separator, preserving all tokens, including empty tokens created by 
    2717      * adjacent separators. This is an alternative to using StringTokenizer.
    2718      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2719      *
    2720      * <p>The separator is not included in the returned String array.
    2721      * Adjacent separators are treated as separators for empty tokens.
    2722      * For more control over the split use the StrTokenizer class.</p>
    2723      *
    2724      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2725      *
    2726      * <pre>
    2727      * StringUtils.splitPreserveAllTokens(null)       = null
    2728      * StringUtils.splitPreserveAllTokens("")         = []
    2729      * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
    2730      * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
    2731      * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
    2732      * </pre>
    2733      *
    2734      * @param str  the String to parse, may be <code>null</code>
    2735      * @return an array of parsed Strings, <code>null</code> if null String input
    2736      * @since 2.1
    2737      */
    2738     public static String[] splitPreserveAllTokens(String str) {
    2739         return splitWorker(str, null, -1, true);
    2740     }
    2741 
    2742     /**
    2743      * <p>Splits the provided text into an array, separator specified,
    2744      * preserving all tokens, including empty tokens created by adjacent
    2745      * separators. This is an alternative to using StringTokenizer.</p>
    2746      *
    2747      * <p>The separator is not included in the returned String array.
    2748      * Adjacent separators are treated as separators for empty tokens.
    2749      * For more control over the split use the StrTokenizer class.</p>
    2750      *
    2751      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    2752      *
    2753      * <pre>
    2754      * StringUtils.splitPreserveAllTokens(null, *)         = null
    2755      * StringUtils.splitPreserveAllTokens("", *)           = []
    2756      * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
    2757      * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
    2758      * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
    2759      * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
    2760      * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
    2761      * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
    2762      * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
    2763      * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
    2764      * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
    2765      * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
    2766      * </pre>
    2767      *
    2768      * @param str  the String to parse, may be <code>null</code>
    2769      * @param separatorChar  the character used as the delimiter,
    2770      *  <code>null</code> splits on whitespace
    2771      * @return an array of parsed Strings, <code>null</code> if null String input
    2772      * @since 2.1
    2773      */
    2774     public static String[] splitPreserveAllTokens(String str, char separatorChar) {
    2775         return splitWorker(str, separatorChar, true);
    2776     }
    2777 
    2778     /**
    2779      * Performs the logic for the <code>split</code> and 
    2780      * <code>splitPreserveAllTokens</code> methods that do not return a
    2781      * maximum array length.
    2782      *
    2783      * @param str  the String to parse, may be <code>null</code>
    2784      * @param separatorChar the separate character
    2785      * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2786      * treated as empty token separators; if <code>false</code>, adjacent
    2787      * separators are treated as one separator.
    2788      * @return an array of parsed Strings, <code>null</code> if null String input
    2789      */
    2790     private static String[] splitWorker(String str, char separatorChar, boolean preserveAllTokens) {
    2791         // Performance tuned for 2.0 (JDK1.4)
    2792 
    2793         if (str == null) {
    2794             return null;
    2795         }
    2796         int len = str.length();
    2797         if (len == 0) {
    2798             return ArrayUtils.EMPTY_STRING_ARRAY;
    2799         }
    2800         List list = new ArrayList();
    2801         int i = 0, start = 0;
    2802         boolean match = false;
    2803         boolean lastMatch = false;
    2804         while (i < len) {
    2805             if (str.charAt(i) == separatorChar) {
    2806                 if (match || preserveAllTokens) {
    2807                     list.add(str.substring(start, i));
    2808                     match = false;
    2809                     lastMatch = true;
    2810                 }
    2811                 start = ++i;
    2812                 continue;
    2813             }
    2814             lastMatch = false;
    2815             match = true;
    2816             i++;
    2817         }
    2818         if (match || (preserveAllTokens && lastMatch)) {
    2819             list.add(str.substring(start, i));
    2820         }
    2821         return (String[]) list.toArray(new String[list.size()]);
    2822     }
    2823 
    2824     /**
    2825      * <p>Splits the provided text into an array, separators specified, 
    2826      * preserving all tokens, including empty tokens created by adjacent
    2827      * separators. This is an alternative to using StringTokenizer.</p>
    2828      *
    2829      * <p>The separator is not included in the returned String array.
    2830      * Adjacent separators are treated as separators for empty tokens.
    2831      * For more control over the split use the StrTokenizer class.</p>
    2832      *
    2833      * <p>A <code>null</code> input String returns <code>null</code>.
    2834      * A <code>null</code> separatorChars splits on whitespace.</p>
    2835      *
    2836      * <pre>
    2837      * StringUtils.splitPreserveAllTokens(null, *)           = null
    2838      * StringUtils.splitPreserveAllTokens("", *)             = []
    2839      * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
    2840      * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
    2841      * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
    2842      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
    2843      * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
    2844      * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
    2845      * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
    2846      * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
    2847      * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
    2848      * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
    2849      * </pre>
    2850      *
    2851      * @param str  the String to parse, may be <code>null</code>
    2852      * @param separatorChars  the characters used as the delimiters,
    2853      *  <code>null</code> splits on whitespace
    2854      * @return an array of parsed Strings, <code>null</code> if null String input
    2855      * @since 2.1
    2856      */
    2857     public static String[] splitPreserveAllTokens(String str, String separatorChars) {
    2858         return splitWorker(str, separatorChars, -1, true);
    2859     }
    2860 
    2861     /**
    2862      * <p>Splits the provided text into an array with a maximum length,
    2863      * separators specified, preserving all tokens, including empty tokens 
    2864      * created by adjacent separators.</p>
    2865      *
    2866      * <p>The separator is not included in the returned String array.
    2867      * Adjacent separators are treated as separators for empty tokens.
    2868      * Adjacent separators are treated as one separator.</p>
    2869      *
    2870      * <p>A <code>null</code> input String returns <code>null</code>.
    2871      * A <code>null</code> separatorChars splits on whitespace.</p>
    2872      *
    2873      * <p>If more than <code>max</code> delimited substrings are found, the last
    2874      * returned string includes all characters after the first <code>max - 1</code>
    2875      * returned strings (including separator characters).</p>
    2876      *
    2877      * <pre>
    2878      * StringUtils.splitPreserveAllTokens(null, *, *)            = null
    2879      * StringUtils.splitPreserveAllTokens("", *, *)              = []
    2880      * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "cd", "ef"]
    2881      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "cd", "ef"]
    2882      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    2883      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    2884      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
    2885      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
    2886      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
    2887      * </pre>
    2888      *
    2889      * @param str  the String to parse, may be <code>null</code>
    2890      * @param separatorChars  the characters used as the delimiters,
    2891      *  <code>null</code> splits on whitespace
    2892      * @param max  the maximum number of elements to include in the
    2893      *  array. A zero or negative value implies no limit
    2894      * @return an array of parsed Strings, <code>null</code> if null String input
    2895      * @since 2.1
    2896      */
    2897     public static String[] splitPreserveAllTokens(String str, String separatorChars, int max) {
    2898         return splitWorker(str, separatorChars, max, true);
    2899     }
    2900 
    2901     /**
    2902      * Performs the logic for the <code>split</code> and 
    2903      * <code>splitPreserveAllTokens</code> methods that return a maximum array 
    2904      * length.
    2905      *
    2906      * @param str  the String to parse, may be <code>null</code>
    2907      * @param separatorChars the separate character
    2908      * @param max  the maximum number of elements to include in the
    2909      *  array. A zero or negative value implies no limit.
    2910      * @param preserveAllTokens if <code>true</code>, adjacent separators are
    2911      * treated as empty token separators; if <code>false</code>, adjacent
    2912      * separators are treated as one separator.
    2913      * @return an array of parsed Strings, <code>null</code> if null String input
    2914      */
    2915     private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
    2916         // Performance tuned for 2.0 (JDK1.4)
    2917         // Direct code is quicker than StringTokenizer.
    2918         // Also, StringTokenizer uses isSpace() not isWhitespace()
    2919 
    2920         if (str == null) {
    2921             return null;
    2922         }
    2923         int len = str.length();
    2924         if (len == 0) {
    2925             return ArrayUtils.EMPTY_STRING_ARRAY;
    2926         }
    2927         List list = new ArrayList();
    2928         int sizePlus1 = 1;
    2929         int i = 0, start = 0;
    2930         boolean match = false;
    2931         boolean lastMatch = false;
    2932         if (separatorChars == null) {
    2933             // Null separator means use whitespace
    2934             while (i < len) {
    2935                 if (Character.isWhitespace(str.charAt(i))) {
    2936                     if (match || preserveAllTokens) {
    2937                         lastMatch = true;
    2938                         if (sizePlus1++ == max) {
    2939                             i = len;
    2940                             lastMatch = false;
    2941                         }
    2942                         list.add(str.substring(start, i));
    2943                         match = false;
    2944                     }
    2945                     start = ++i;
    2946                     continue;
    2947                 }
    2948                 lastMatch = false;
    2949                 match = true;
    2950                 i++;
    2951             }
    2952         } else if (separatorChars.length() == 1) {
    2953             // Optimise 1 character case
    2954             char sep = separatorChars.charAt(0);
    2955             while (i < len) {
    2956                 if (str.charAt(i) == sep) {
    2957                     if (match || preserveAllTokens) {
    2958                         lastMatch = true;
    2959                         if (sizePlus1++ == max) {
    2960                             i = len;
    2961                             lastMatch = false;
    2962                         }
    2963                         list.add(str.substring(start, i));
    2964                         match = false;
    2965                     }
    2966                     start = ++i;
    2967                     continue;
    2968                 }
    2969                 lastMatch = false;
    2970                 match = true;
    2971                 i++;
    2972             }
    2973         } else {
    2974             // standard case
    2975             while (i < len) {
    2976                 if (separatorChars.indexOf(str.charAt(i)) >= 0) {
    2977                     if (match || preserveAllTokens) {
    2978                         lastMatch = true;
    2979                         if (sizePlus1++ == max) {
    2980                             i = len;
    2981                             lastMatch = false;
    2982                         }
    2983                         list.add(str.substring(start, i));
    2984                         match = false;
    2985                     }
    2986                     start = ++i;
    2987                     continue;
    2988                 }
    2989                 lastMatch = false;
    2990                 match = true;
    2991                 i++;
    2992             }
    2993         }
    2994         if (match || (preserveAllTokens && lastMatch)) {
    2995             list.add(str.substring(start, i));
    2996         }
    2997         return (String[]) list.toArray(new String[list.size()]);
    2998     }
    2999 
    3000     /**
    3001      * <p>Splits a String by Character type as returned by
    3002      * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3003      * characters of the same type are returned as complete tokens. 
    3004      * <pre>
    3005      * StringUtils.splitByCharacterType(null)         = null
    3006      * StringUtils.splitByCharacterType("")           = []
    3007      * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    3008      * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    3009      * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    3010      * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
    3011      * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
    3012      * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
    3013      * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
    3014      * </pre>
    3015      * @param str the String to split, may be <code>null</code>
    3016      * @return an array of parsed Strings, <code>null</code> if null String input
    3017      * @since 2.4
    3018      */
    3019     public static String[] splitByCharacterType(String str) {
    3020         return splitByCharacterType(str, false);
    3021     }
    3022 
    3023     /**
    3024      * <p>Splits a String by Character type as returned by
    3025      * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3026      * characters of the same type are returned as complete tokens, with the
    3027      * following exception: the character of type
    3028      * <code>Character.UPPERCASE_LETTER</code>, if any, immediately
    3029      * preceding a token of type <code>Character.LOWERCASE_LETTER</code>
    3030      * will belong to the following token rather than to the preceding, if any,
    3031      * <code>Character.UPPERCASE_LETTER</code> token. 
    3032      * <pre>
    3033      * StringUtils.splitByCharacterTypeCamelCase(null)         = null
    3034      * StringUtils.splitByCharacterTypeCamelCase("")           = []
    3035      * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    3036      * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    3037      * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    3038      * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
    3039      * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
    3040      * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
    3041      * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
    3042      * </pre>
    3043      * @param str the String to split, may be <code>null</code>
    3044      * @return an array of parsed Strings, <code>null</code> if null String input
    3045      * @since 2.4
    3046      */
    3047     public static String[] splitByCharacterTypeCamelCase(String str) {
    3048         return splitByCharacterType(str, true);
    3049     }
    3050 
    3051     /**
    3052      * <p>Splits a String by Character type as returned by
    3053      * <code>java.lang.Character.getType(char)</code>. Groups of contiguous
    3054      * characters of the same type are returned as complete tokens, with the
    3055      * following exception: if <code>camelCase</code> is <code>true</code>,
    3056      * the character of type <code>Character.UPPERCASE_LETTER</code>, if any,
    3057      * immediately preceding a token of type <code>Character.LOWERCASE_LETTER</code>
    3058      * will belong to the following token rather than to the preceding, if any,
    3059      * <code>Character.UPPERCASE_LETTER</code> token. 
    3060      * @param str the String to split, may be <code>null</code>
    3061      * @param camelCase whether to use so-called "camel-case" for letter types
    3062      * @return an array of parsed Strings, <code>null</code> if null String input
    3063      * @since 2.4
    3064      */
    3065     private static String[] splitByCharacterType(String str, boolean camelCase) {
    3066         if (str == null) {
    3067             return null;
    3068         }
    3069         if (str.length() == 0) {
    3070             return ArrayUtils.EMPTY_STRING_ARRAY;
    3071         }
    3072         char[] c = str.toCharArray();
    3073         List list = new ArrayList();
    3074         int tokenStart = 0;
    3075         int currentType = Character.getType(c[tokenStart]);
    3076         for (int pos = tokenStart + 1; pos < c.length; pos++) {
    3077             int type = Character.getType(c[pos]);
    3078             if (type == currentType) {
    3079                 continue;
    3080             }
    3081             if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
    3082                 int newTokenStart = pos - 1;
    3083                 if (newTokenStart != tokenStart) {
    3084                     list.add(new String(c, tokenStart, newTokenStart - tokenStart));
    3085                     tokenStart = newTokenStart;
    3086                 }
    3087             } else {
    3088                 list.add(new String(c, tokenStart, pos - tokenStart));
    3089                 tokenStart = pos;
    3090             }
    3091             currentType = type;
    3092         }
    3093         list.add(new String(c, tokenStart, c.length - tokenStart));
    3094         return (String[]) list.toArray(new String[list.size()]);
    3095     }
    3096 
    3097     // Joining
    3098     //-----------------------------------------------------------------------
    3099     /**
    3100      * <p>Joins the provided elements into a single String. </p>
    3101      *
    3102      * <p>No separator is added to the joined String.
    3103      * Null objects or empty string elements are represented by
    3104      * empty strings.</p>
    3105      *
    3106      * <pre>
    3107      * StringUtils.concatenate(null)            = null
    3108      * StringUtils.concatenate([])              = ""
    3109      * StringUtils.concatenate([null])          = ""
    3110      * StringUtils.concatenate(["a", "b", "c"]) = "abc"
    3111      * StringUtils.concatenate([null, "", "a"]) = "a"
    3112      * </pre>
    3113      *
    3114      * @param array  the array of values to concatenate, may be null
    3115      * @return the concatenated String, <code>null</code> if null array input
    3116      * @deprecated Use the better named {@link #join(Object[])} instead.
    3117      *             Method will be removed in Commons Lang 3.0.
    3118      */
    3119     public static String concatenate(Object[] array) {
    3120         return join(array, null);
    3121     }
    3122 
    3123     /**
    3124      * <p>Joins the elements of the provided array into a single String
    3125      * containing the provided list of elements.</p>
    3126      *
    3127      * <p>No separator is added to the joined String.
    3128      * Null objects or empty strings within the array are represented by
    3129      * empty strings.</p>
    3130      *
    3131      * <pre>
    3132      * StringUtils.join(null)            = null
    3133      * StringUtils.join([])              = ""
    3134      * StringUtils.join([null])          = ""
    3135      * StringUtils.join(["a", "b", "c"]) = "abc"
    3136      * StringUtils.join([null, "", "a"]) = "a"
    3137      * </pre>
    3138      *
    3139      * @param array  the array of values to join together, may be null
    3140      * @return the joined String, <code>null</code> if null array input
    3141      * @since 2.0
    3142      */
    3143     public static String join(Object[] array) {
    3144         return join(array, null);
    3145     }
    3146 
    3147     /**
    3148      * <p>Joins the elements of the provided array into a single String
    3149      * containing the provided list of elements.</p>
    3150      *
    3151      * <p>No delimiter is added before or after the list.
    3152      * Null objects or empty strings within the array are represented by
    3153      * empty strings.</p>
    3154      *
    3155      * <pre>
    3156      * StringUtils.join(null, *)               = null
    3157      * StringUtils.join([], *)                 = ""
    3158      * StringUtils.join([null], *)             = ""
    3159      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    3160      * StringUtils.join(["a", "b", "c"], null) = "abc"
    3161      * StringUtils.join([null, "", "a"], ';')  = ";;a"
    3162      * </pre>
    3163      *
    3164      * @param array  the array of values to join together, may be null
    3165      * @param separator  the separator character to use
    3166      * @return the joined String, <code>null</code> if null array input
    3167      * @since 2.0
    3168      */
    3169     public static String join(Object[] array, char separator) {
    3170         if (array == null) {
    3171             return null;
    3172         }
    3173 
    3174         return join(array, separator, 0, array.length);
    3175     }
    3176 
    3177     /**
    3178      * <p>Joins the elements of the provided array into a single String
    3179      * containing the provided list of elements.</p>
    3180      *
    3181      * <p>No delimiter is added before or after the list.
    3182      * Null objects or empty strings within the array are represented by
    3183      * empty strings.</p>
    3184      *
    3185      * <pre>
    3186      * StringUtils.join(null, *)               = null
    3187      * StringUtils.join([], *)                 = ""
    3188      * StringUtils.join([null], *)             = ""
    3189      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    3190      * StringUtils.join(["a", "b", "c"], null) = "abc"
    3191      * StringUtils.join([null, "", "a"], ';')  = ";;a"
    3192      * </pre>
    3193      *
    3194      * @param array  the array of values to join together, may be null
    3195      * @param separator  the separator character to use
    3196      * @param startIndex the first index to start joining from.  It is
    3197      * an error to pass in an end index past the end of the array
    3198      * @param endIndex the index to stop joining from (exclusive). It is
    3199      * an error to pass in an end index past the end of the array
    3200      * @return the joined String, <code>null</code> if null array input
    3201      * @since 2.0
    3202      */
    3203     public static String join(Object[] array, char separator, int startIndex, int endIndex) {
    3204         if (array == null) {
    3205             return null;
    3206         }
    3207         int bufSize = (endIndex - startIndex);
    3208         if (bufSize <= 0) {
    3209             return EMPTY;
    3210         }
    3211 
    3212         bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + 1);
    3213         StrBuilder buf = new StrBuilder(bufSize);
    3214 
    3215         for (int i = startIndex; i < endIndex; i++) {
    3216             if (i > startIndex) {
    3217                 buf.append(separator);
    3218             }
    3219             if (array[i] != null) {
    3220                 buf.append(array[i]);
    3221             }
    3222         }
    3223         return buf.toString();
    3224     }
    3225 
    3226 
    3227     /**
    3228      * <p>Joins the elements of the provided array into a single String
    3229      * containing the provided list of elements.</p>
    3230      *
    3231      * <p>No delimiter is added before or after the list.
    3232      * A <code>null</code> separator is the same as an empty String ("").
    3233      * Null objects or empty strings within the array are represented by
    3234      * empty strings.</p>
    3235      *
    3236      * <pre>
    3237      * StringUtils.join(null, *)                = null
    3238      * StringUtils.join([], *)                  = ""
    3239      * StringUtils.join([null], *)              = ""
    3240      * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    3241      * StringUtils.join(["a", "b", "c"], null)  = "abc"
    3242      * StringUtils.join(["a", "b", "c"], "")    = "abc"
    3243      * StringUtils.join([null, "", "a"], ',')   = ",,a"
    3244      * </pre>
    3245      *
    3246      * @param array  the array of values to join together, may be null
    3247      * @param separator  the separator character to use, null treated as ""
    3248      * @return the joined String, <code>null</code> if null array input
    3249      */
    3250     public static String join(Object[] array, String separator) {
    3251         if (array == null) {
    3252             return null;
    3253         }
    3254         return join(array, separator, 0, array.length);
    3255     }
    3256 
    3257     /**
    3258      * <p>Joins the elements of the provided array into a single String
    3259      * containing the provided list of elements.</p>
    3260      *
    3261      * <p>No delimiter is added before or after the list.
    3262      * A <code>null</code> separator is the same as an empty String ("").
    3263      * Null objects or empty strings within the array are represented by
    3264      * empty strings.</p>
    3265      *
    3266      * <pre>
    3267      * StringUtils.join(null, *)                = null
    3268      * StringUtils.join([], *)                  = ""
    3269      * StringUtils.join([null], *)              = ""
    3270      * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    3271      * StringUtils.join(["a", "b", "c"], null)  = "abc"
    3272      * StringUtils.join(["a", "b", "c"], "")    = "abc"
    3273      * StringUtils.join([null, "", "a"], ',')   = ",,a"
    3274      * </pre>
    3275      *
    3276      * @param array  the array of values to join together, may be null
    3277      * @param separator  the separator character to use, null treated as ""
    3278      * @param startIndex the first index to start joining from.  It is
    3279      * an error to pass in an end index past the end of the array
    3280      * @param endIndex the index to stop joining from (exclusive). It is
    3281      * an error to pass in an end index past the end of the array
    3282      * @return the joined String, <code>null</code> if null array input
    3283      */
    3284     public static String join(Object[] array, String separator, int startIndex, int endIndex) {
    3285         if (array == null) {
    3286             return null;
    3287         }
    3288         if (separator == null) {
    3289             separator = EMPTY;
    3290         }
    3291 
    3292         // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    3293         //           (Assuming that all Strings are roughly equally long)
    3294         int bufSize = (endIndex - startIndex);
    3295         if (bufSize <= 0) {
    3296             return EMPTY;
    3297         }
    3298 
    3299         bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length())
    3300                         + separator.length());
    3301 
    3302         StrBuilder buf = new StrBuilder(bufSize);
    3303 
    3304         for (int i = startIndex; i < endIndex; i++) {
    3305             if (i > startIndex) {
    3306                 buf.append(separator);
    3307             }
    3308             if (array[i] != null) {
    3309                 buf.append(array[i]);
    3310             }
    3311         }
    3312         return buf.toString();
    3313     }
    3314 
    3315     /**
    3316      * <p>Joins the elements of the provided <code>Iterator</code> into
    3317      * a single String containing the provided elements.</p>
    3318      *
    3319      * <p>No delimiter is added before or after the list. Null objects or empty
    3320      * strings within the iteration are represented by empty strings.</p>
    3321      *
    3322      * <p>See the examples here: {@link #join(Object[],char)}. </p>
    3323      *
    3324      * @param iterator  the <code>Iterator</code> of values to join together, may be null
    3325      * @param separator  the separator character to use
    3326      * @return the joined String, <code>null</code> if null iterator input
    3327      * @since 2.0
    3328      */
    3329     public static String join(Iterator iterator, char separator) {
    3330 
    3331         // handle null, zero and one elements before building a buffer
    3332         if (iterator == null) {
    3333             return null;
    3334         }
    3335         if (!iterator.hasNext()) {
    3336             return EMPTY;
    3337         }
    3338         Object first = iterator.next();
    3339         if (!iterator.hasNext()) {
    3340             return ObjectUtils.toString(first);
    3341         }
    3342 
    3343         // two or more elements
    3344         StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
    3345         if (first != null) {
    3346             buf.append(first);
    3347         }
    3348 
    3349         while (iterator.hasNext()) {
    3350             buf.append(separator);
    3351             Object obj = iterator.next();
    3352             if (obj != null) {
    3353                 buf.append(obj);
    3354             }
    3355         }
    3356 
    3357         return buf.toString();
    3358     }
    3359 
    3360     /**
    3361      * <p>Joins the elements of the provided <code>Iterator</code> into
    3362      * a single String containing the provided elements.</p>
    3363      *
    3364      * <p>No delimiter is added before or after the list.
    3365      * A <code>null</code> separator is the same as an empty String ("").</p>
    3366      *
    3367      * <p>See the examples here: {@link #join(Object[],String)}. </p>
    3368      *
    3369      * @param iterator  the <code>Iterator</code> of values to join together, may be null
    3370      * @param separator  the separator character to use, null treated as ""
    3371      * @return the joined String, <code>null</code> if null iterator input
    3372      */
    3373     public static String join(Iterator iterator, String separator) {
    3374 
    3375         // handle null, zero and one elements before building a buffer
    3376         if (iterator == null) {
    3377             return null;
    3378         }
    3379         if (!iterator.hasNext()) {
    3380             return EMPTY;
    3381         }
    3382         Object first = iterator.next();
    3383         if (!iterator.hasNext()) {
    3384             return ObjectUtils.toString(first);
    3385         }
    3386 
    3387         // two or more elements
    3388         StrBuilder buf = new StrBuilder(256); // Java default is 16, probably too small
    3389         if (first != null) {
    3390             buf.append(first);
    3391         }
    3392 
    3393         while (iterator.hasNext()) {
    3394             if (separator != null) {
    3395                 buf.append(separator);
    3396             }
    3397             Object obj = iterator.next();
    3398             if (obj != null) {
    3399                 buf.append(obj);
    3400             }
    3401         }
    3402         return buf.toString();
    3403     }
    3404 
    3405     /**
    3406      * <p>Joins the elements of the provided <code>Collection</code> into
    3407      * a single String containing the provided elements.</p>
    3408      *
    3409      * <p>No delimiter is added before or after the list. Null objects or empty
    3410      * strings within the iteration are represented by empty strings.</p>
    3411      *
    3412      * <p>See the examples here: {@link #join(Object[],char)}. </p>
    3413      *
    3414      * @param collection  the <code>Collection</code> of values to join together, may be null
    3415      * @param separator  the separator character to use
    3416      * @return the joined String, <code>null</code> if null iterator input
    3417      * @since 2.3
    3418      */
    3419     public static String join(Collection collection, char separator) {
    3420         if (collection == null) {
    3421             return null;
    3422         }
    3423         return join(collection.iterator(), separator);
    3424     }
    3425 
    3426     /**
    3427      * <p>Joins the elements of the provided <code>Collection</code> into
    3428      * a single String containing the provided elements.</p>
    3429      *
    3430      * <p>No delimiter is added before or after the list.
    3431      * A <code>null</code> separator is the same as an empty String ("").</p>
    3432      *
    3433      * <p>See the examples here: {@link #join(Object[],String)}. </p>
    3434      *
    3435      * @param collection  the <code>Collection</code> of values to join together, may be null
    3436      * @param separator  the separator character to use, null treated as ""
    3437      * @return the joined String, <code>null</code> if null iterator input
    3438      * @since 2.3
    3439      */
    3440     public static String join(Collection collection, String separator) {
    3441         if (collection == null) {
    3442             return null;
    3443         }
    3444         return join(collection.iterator(), separator);
    3445     }
    3446 
    3447     // Delete
    3448     //-----------------------------------------------------------------------
    3449     /**
    3450      * <p>Deletes all 'space' characters from a String as defined by
    3451      * {@link Character#isSpace(char)}.</p>
    3452      *
    3453      * <p>This is the only StringUtils method that uses the
    3454      * <code>isSpace</code> definition. You are advised to use
    3455      * {@link #deleteWhitespace(String)} instead as whitespace is much
    3456      * better localized.</p>
    3457      *
    3458      * <pre>
    3459      * StringUtils.deleteSpaces(null)           = null
    3460      * StringUtils.deleteSpaces("")             = ""
    3461      * StringUtils.deleteSpaces("abc")          = "abc"
    3462      * StringUtils.deleteSpaces(" \t  abc \n ") = "abc"
    3463      * StringUtils.deleteSpaces("ab  c")        = "abc"
    3464      * StringUtils.deleteSpaces("a\nb\tc     ") = "abc"
    3465      * </pre>
    3466      *
    3467      * <p>Spaces are defined as <code>{' ', '\t', '\r', '\n', '\b'}</code>
    3468      * in line with the deprecated <code>isSpace</code> method.</p>
    3469      *
    3470      * @param str  the String to delete spaces from, may be null
    3471      * @return the String without 'spaces', <code>null</code> if null String input
    3472      * @deprecated Use the better localized {@link #deleteWhitespace(String)}.
    3473      *             Method will be removed in Commons Lang 3.0.
    3474      */
    3475     public static String deleteSpaces(String str) {
    3476         if (str == null) {
    3477             return null;
    3478         }
    3479         return CharSetUtils.delete(str, " \t\r\n\b");
    3480     }
    3481 
    3482     /**
    3483      * <p>Deletes all whitespaces from a String as defined by
    3484      * {@link Character#isWhitespace(char)}.</p>
    3485      *
    3486      * <pre>
    3487      * StringUtils.deleteWhitespace(null)         = null
    3488      * StringUtils.deleteWhitespace("")           = ""
    3489      * StringUtils.deleteWhitespace("abc")        = "abc"
    3490      * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
    3491      * </pre>
    3492      *
    3493      * @param str  the String to delete whitespace from, may be null
    3494      * @return the String without whitespaces, <code>null</code> if null String input
    3495      */
    3496     public static String deleteWhitespace(String str) {
    3497         if (isEmpty(str)) {
    3498             return str;
    3499         }
    3500         int sz = str.length();
    3501         char[] chs = new char[sz];
    3502         int count = 0;
    3503         for (int i = 0; i < sz; i++) {
    3504             if (!Character.isWhitespace(str.charAt(i))) {
    3505                 chs[count++] = str.charAt(i);
    3506             }
    3507         }
    3508         if (count == sz) {
    3509             return str;
    3510         }
    3511         return new String(chs, 0, count);
    3512     }
    3513 
    3514     // Remove
    3515     //-----------------------------------------------------------------------
    3516     /**
    3517      * <p>Removes a substring only if it is at the begining of a source string,
    3518      * otherwise returns the source string.</p>
    3519      *
    3520      * <p>A <code>null</code> source string will return <code>null</code>.
    3521      * An empty ("") source string will return the empty string.
    3522      * A <code>null</code> search string will return the source string.</p>
    3523      *
    3524      * <pre>
    3525      * StringUtils.removeStart(null, *)      = null
    3526      * StringUtils.removeStart("", *)        = ""
    3527      * StringUtils.removeStart(*, null)      = *
    3528      * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
    3529      * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
    3530      * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
    3531      * StringUtils.removeStart("abc", "")    = "abc"
    3532      * </pre>
    3533      *
    3534      * @param str  the source String to search, may be null
    3535      * @param remove  the String to search for and remove, may be null
    3536      * @return the substring with the string removed if found,
    3537      *  <code>null</code> if null String input
    3538      * @since 2.1
    3539      */
    3540     public static String removeStart(String str, String remove) {
    3541         if (isEmpty(str) || isEmpty(remove)) {
    3542             return str;
    3543         }
    3544         if (str.startsWith(remove)){
    3545             return str.substring(remove.length());
    3546         }
    3547         return str;
    3548     }
    3549 
    3550     /**
    3551      * <p>Case insensitive removal of a substring if it is at the begining of a source string,
    3552      * otherwise returns the source string.</p>
    3553      *
    3554      * <p>A <code>null</code> source string will return <code>null</code>.
    3555      * An empty ("") source string will return the empty string.
    3556      * A <code>null</code> search string will return the source string.</p>
    3557      *
    3558      * <pre>
    3559      * StringUtils.removeStartIgnoreCase(null, *)      = null
    3560      * StringUtils.removeStartIgnoreCase("", *)        = ""
    3561      * StringUtils.removeStartIgnoreCase(*, null)      = *
    3562      * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
    3563      * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
    3564      * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
    3565      * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    3566      * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
    3567      * </pre>
    3568      *
    3569      * @param str  the source String to search, may be null
    3570      * @param remove  the String to search for (case insensitive) and remove, may be null
    3571      * @return the substring with the string removed if found,
    3572      *  <code>null</code> if null String input
    3573      * @since 2.4
    3574      */
    3575     public static String removeStartIgnoreCase(String str, String remove) {
    3576         if (isEmpty(str) || isEmpty(remove)) {
    3577             return str;
    3578         }
    3579         if (startsWithIgnoreCase(str, remove)) {
    3580             return str.substring(remove.length());
    3581         }
    3582         return str;
    3583     }
    3584 
    3585     /**
    3586      * <p>Removes a substring only if it is at the end of a source string,
    3587      * otherwise returns the source string.</p>
    3588      *
    3589      * <p>A <code>null</code> source string will return <code>null</code>.
    3590      * An empty ("") source string will return the empty string.
    3591      * A <code>null</code> search string will return the source string.</p>
    3592      *
    3593      * <pre>
    3594      * StringUtils.removeEnd(null, *)      = null
    3595      * StringUtils.removeEnd("", *)        = ""
    3596      * StringUtils.removeEnd(*, null)      = *
    3597      * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
    3598      * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
    3599      * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
    3600      * StringUtils.removeEnd("abc", "")    = "abc"
    3601      * </pre>
    3602      *
    3603      * @param str  the source String to search, may be null
    3604      * @param remove  the String to search for and remove, may be null
    3605      * @return the substring with the string removed if found,
    3606      *  <code>null</code> if null String input
    3607      * @since 2.1
    3608      */
    3609     public static String removeEnd(String str, String remove) {
    3610         if (isEmpty(str) || isEmpty(remove)) {
    3611             return str;
    3612         }
    3613         if (str.endsWith(remove)) {
    3614             return str.substring(0, str.length() - remove.length());
    3615         }
    3616         return str;
    3617     }
    3618 
    3619     /**
    3620      * <p>Case insensitive removal of a substring if it is at the end of a source string,
    3621      * otherwise returns the source string.</p>
    3622      *
    3623      * <p>A <code>null</code> source string will return <code>null</code>.
    3624      * An empty ("") source string will return the empty string.
    3625      * A <code>null</code> search string will return the source string.</p>
    3626      *
    3627      * <pre>
    3628      * StringUtils.removeEndIgnoreCase(null, *)      = null
    3629      * StringUtils.removeEndIgnoreCase("", *)        = ""
    3630      * StringUtils.removeEndIgnoreCase(*, null)      = *
    3631      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
    3632      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
    3633      * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    3634      * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
    3635      * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
    3636      * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
    3637      * </pre>
    3638      *
    3639      * @param str  the source String to search, may be null
    3640      * @param remove  the String to search for (case insensitive) and remove, may be null
    3641      * @return the substring with the string removed if found,
    3642      *  <code>null</code> if null String input
    3643      * @since 2.4
    3644      */
    3645     public static String removeEndIgnoreCase(String str, String remove) {
    3646         if (isEmpty(str) || isEmpty(remove)) {
    3647             return str;
    3648         }
    3649         if (endsWithIgnoreCase(str, remove)) {
    3650             return str.substring(0, str.length() - remove.length());
    3651         }
    3652         return str;
    3653     }
    3654 
    3655     /**
    3656      * <p>Removes all occurrences of a substring from within the source string.</p>
    3657      *
    3658      * <p>A <code>null</code> source string will return <code>null</code>.
    3659      * An empty ("") source string will return the empty string.
    3660      * A <code>null</code> remove string will return the source string.
    3661      * An empty ("") remove string will return the source string.</p>
    3662      *
    3663      * <pre>
    3664      * StringUtils.remove(null, *)        = null
    3665      * StringUtils.remove("", *)          = ""
    3666      * StringUtils.remove(*, null)        = *
    3667      * StringUtils.remove(*, "")          = *
    3668      * StringUtils.remove("queued", "ue") = "qd"
    3669      * StringUtils.remove("queued", "zz") = "queued"
    3670      * </pre>
    3671      *
    3672      * @param str  the source String to search, may be null
    3673      * @param remove  the String to search for and remove, may be null
    3674      * @return the substring with the string removed if found,
    3675      *  <code>null</code> if null String input
    3676      * @since 2.1
    3677      */
    3678     public static String remove(String str, String remove) {
    3679         if (isEmpty(str) || isEmpty(remove)) {
    3680             return str;
    3681         }
    3682         return replace(str, remove, EMPTY, -1);
    3683     }
    3684 
    3685     /**
    3686      * <p>Removes all occurrences of a character from within the source string.</p>
    3687      *
    3688      * <p>A <code>null</code> source string will return <code>null</code>.
    3689      * An empty ("") source string will return the empty string.</p>
    3690      *
    3691      * <pre>
    3692      * StringUtils.remove(null, *)       = null
    3693      * StringUtils.remove("", *)         = ""
    3694      * StringUtils.remove("queued", 'u') = "qeed"
    3695      * StringUtils.remove("queued", 'z') = "queued"
    3696      * </pre>
    3697      *
    3698      * @param str  the source String to search, may be null
    3699      * @param remove  the char to search for and remove, may be null
    3700      * @return the substring with the char removed if found,
    3701      *  <code>null</code> if null String input
    3702      * @since 2.1
    3703      */
    3704     public static String remove(String str, char remove) {
    3705         if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
    3706             return str;
    3707         }
    3708         char[] chars = str.toCharArray();
    3709         int pos = 0;
    3710         for (int i = 0; i < chars.length; i++) {
    3711             if (chars[i] != remove) {
    3712                 chars[pos++] = chars[i];
    3713             }
    3714         }
    3715         return new String(chars, 0, pos);
    3716     }
    3717 
    3718     // Replacing
    3719     //-----------------------------------------------------------------------
    3720     /**
    3721      * <p>Replaces a String with another String inside a larger String, once.</p>
    3722      *
    3723      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3724      *
    3725      * <pre>
    3726      * StringUtils.replaceOnce(null, *, *)        = null
    3727      * StringUtils.replaceOnce("", *, *)          = ""
    3728      * StringUtils.replaceOnce("any", null, *)    = "any"
    3729      * StringUtils.replaceOnce("any", *, null)    = "any"
    3730      * StringUtils.replaceOnce("any", "", *)      = "any"
    3731      * StringUtils.replaceOnce("aba", "a", null)  = "aba"
    3732      * StringUtils.replaceOnce("aba", "a", "")    = "ba"
    3733      * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
    3734      * </pre>
    3735      *
    3736      * @see #replace(String text, String searchString, String replacement, int max)
    3737      * @param text  text to search and replace in, may be null
    3738      * @param searchString  the String to search for, may be null
    3739      * @param replacement  the String to replace with, may be null
    3740      * @return the text with any replacements processed,
    3741      *  <code>null</code> if null String input
    3742      */
    3743     public static String replaceOnce(String text, String searchString, String replacement) {
    3744         return replace(text, searchString, replacement, 1);
    3745     }
    3746 
    3747     /**
    3748      * <p>Replaces all occurrences of a String within another String.</p>
    3749      *
    3750      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3751      *
    3752      * <pre>
    3753      * StringUtils.replace(null, *, *)        = null
    3754      * StringUtils.replace("", *, *)          = ""
    3755      * StringUtils.replace("any", null, *)    = "any"
    3756      * StringUtils.replace("any", *, null)    = "any"
    3757      * StringUtils.replace("any", "", *)      = "any"
    3758      * StringUtils.replace("aba", "a", null)  = "aba"
    3759      * StringUtils.replace("aba", "a", "")    = "b"
    3760      * StringUtils.replace("aba", "a", "z")   = "zbz"
    3761      * </pre>
    3762      *
    3763      * @see #replace(String text, String searchString, String replacement, int max)
    3764      * @param text  text to search and replace in, may be null
    3765      * @param searchString  the String to search for, may be null
    3766      * @param replacement  the String to replace it with, may be null
    3767      * @return the text with any replacements processed,
    3768      *  <code>null</code> if null String input
    3769      */
    3770     public static String replace(String text, String searchString, String replacement) {
    3771         return replace(text, searchString, replacement, -1);
    3772     }
    3773 
    3774     /**
    3775      * <p>Replaces a String with another String inside a larger String,
    3776      * for the first <code>max</code> values of the search String.</p>
    3777      *
    3778      * <p>A <code>null</code> reference passed to this method is a no-op.</p>
    3779      *
    3780      * <pre>
    3781      * StringUtils.replace(null, *, *, *)         = null
    3782      * StringUtils.replace("", *, *, *)           = ""
    3783      * StringUtils.replace("any", null, *, *)     = "any"
    3784      * StringUtils.replace("any", *, null, *)     = "any"
    3785      * StringUtils.replace("any", "", *, *)       = "any"
    3786      * StringUtils.replace("any", *, *, 0)        = "any"
    3787      * StringUtils.replace("abaa", "a", null, -1) = "abaa"
    3788      * StringUtils.replace("abaa", "a", "", -1)   = "b"
    3789      * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
    3790      * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
    3791      * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
    3792      * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
    3793      * </pre>
    3794      *
    3795      * @param text  text to search and replace in, may be null
    3796      * @param searchString  the String to search for, may be null
    3797      * @param replacement  the String to replace it with, may be null
    3798      * @param max  maximum number of values to replace, or <code>-1</code> if no maximum
    3799      * @return the text with any replacements processed,
    3800      *  <code>null</code> if null String input
    3801      */
    3802     public static String replace(String text, String searchString, String replacement, int max) {
    3803         if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
    3804             return text;
    3805         }
    3806         int start = 0;
    3807         int end = text.indexOf(searchString, start);
    3808         if (end == INDEX_NOT_FOUND) {
    3809             return text;
    3810         }
    3811         int replLength = searchString.length();
    3812         int increase = replacement.length() - replLength;
    3813         increase = (increase < 0 ? 0 : increase);
    3814         increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
    3815         StrBuilder buf = new StrBuilder(text.length() + increase);
    3816         while (end != INDEX_NOT_FOUND) {
    3817             buf.append(text.substring(start, end)).append(replacement);
    3818             start = end + replLength;
    3819             if (--max == 0) {
    3820                 break;
    3821             }
    3822             end = text.indexOf(searchString, start);
    3823         }
    3824         buf.append(text.substring(start));
    3825         return buf.toString();
    3826     }
    3827 
    3828     /**
    3829      * <p>
    3830      * Replaces all occurrences of Strings within another String.
    3831      * </p>
    3832      * 
    3833      * <p>
    3834      * A <code>null</code> reference passed to this method is a no-op, or if
    3835      * any "search string" or "string to replace" is null, that replace will be
    3836      * ignored. This will not repeat. For repeating replaces, call the
    3837      * overloaded method.
    3838      * </p>
    3839      * 
    3840      * <pre>
    3841      *  StringUtils.replaceEach(null, *, *)        = null
    3842      *  StringUtils.replaceEach("", *, *)          = ""
    3843      *  StringUtils.replaceEach("aba", null, null) = "aba"
    3844      *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
    3845      *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
    3846      *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
    3847      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
    3848      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
    3849      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
    3850      *  (example of how it does not repeat)
    3851      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
    3852      * </pre>
    3853      * 
    3854      * @param text
    3855      *            text to search and replace in, no-op if null
    3856      * @param searchList
    3857      *            the Strings to search for, no-op if null
    3858      * @param replacementList
    3859      *            the Strings to replace them with, no-op if null
    3860      * @return the text with any replacements processed, <code>null</code> if
    3861      *         null String input
    3862      * @throws IndexOutOfBoundsException
    3863      *             if the lengths of the arrays are not the same (null is ok,
    3864      *             and/or size 0)
    3865      * @since 2.4
    3866      */
    3867     public static String replaceEach(String text, String[] searchList, String[] replacementList) {
    3868         return replaceEach(text, searchList, replacementList, false, 0);
    3869     }
    3870 
    3871     /**
    3872      * <p>
    3873      * Replaces all occurrences of Strings within another String.
    3874      * </p>
    3875      * 
    3876      * <p>
    3877      * A <code>null</code> reference passed to this method is a no-op, or if
    3878      * any "search string" or "string to replace" is null, that replace will be
    3879      * ignored. This will not repeat. For repeating replaces, call the
    3880      * overloaded method.
    3881      * </p>
    3882      * 
    3883      * <pre>
    3884      *  StringUtils.replaceEach(null, *, *, *) = null
    3885      *  StringUtils.replaceEach("", *, *, *) = ""
    3886      *  StringUtils.replaceEach("aba", null, null, *) = "aba"
    3887      *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
    3888      *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
    3889      *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
    3890      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
    3891      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
    3892      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
    3893      *  (example of how it repeats)
    3894      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
    3895      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
    3896      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalArgumentException
    3897      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe"
    3898      * </pre>
    3899      * 
    3900      * @param text
    3901      *            text to search and replace in, no-op if null
    3902      * @param searchList
    3903      *            the Strings to search for, no-op if null
    3904      * @param replacementList
    3905      *            the Strings to replace them with, no-op if null
    3906      * @return the text with any replacements processed, <code>null</code> if
    3907      *         null String input
    3908      * @throws IllegalArgumentException
    3909      *             if the search is repeating and there is an endless loop due
    3910      *             to outputs of one being inputs to another
    3911      * @throws IndexOutOfBoundsException
    3912      *             if the lengths of the arrays are not the same (null is ok,
    3913      *             and/or size 0)
    3914      * @since 2.4
    3915      */
    3916     public static String replaceEachRepeatedly(String text, String[] searchList, String[] replacementList) {
    3917         // timeToLive should be 0 if not used or nothing to replace, else it's
    3918         // the length of the replace array
    3919         int timeToLive = searchList == null ? 0 : searchList.length;
    3920         return replaceEach(text, searchList, replacementList, true, timeToLive);
    3921     }
    3922 
    3923     /**
    3924      * <p>
    3925      * Replaces all occurrences of Strings within another String.
    3926      * </p>
    3927      * 
    3928      * <p>
    3929      * A <code>null</code> reference passed to this method is a no-op, or if
    3930      * any "search string" or "string to replace" is null, that replace will be
    3931      * ignored. 
    3932      * </p>
    3933      * 
    3934      * <pre>
    3935      *  StringUtils.replaceEach(null, *, *, *) = null
    3936      *  StringUtils.replaceEach("", *, *, *) = ""
    3937      *  StringUtils.replaceEach("aba", null, null, *) = "aba"
    3938      *  StringUtils.replaceEach("aba", new String[0], null, *) = "aba"
    3939      *  StringUtils.replaceEach("aba", null, new String[0], *) = "aba"
    3940      *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba"
    3941      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b"
    3942      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba"
    3943      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte"
    3944      *  (example of how it repeats)
    3945      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte"
    3946      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte"
    3947      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalArgumentException
    3948      * </pre>
    3949      * 
    3950      * @param text
    3951      *            text to search and replace in, no-op if null
    3952      * @param searchList
    3953      *            the Strings to search for, no-op if null
    3954      * @param replacementList
    3955      *            the Strings to replace them with, no-op if null
    3956      * @param repeat if true, then replace repeatedly 
    3957      *       until there are no more possible replacements or timeToLive < 0
    3958      * @param timeToLive
    3959      *            if less than 0 then there is a circular reference and endless
    3960      *            loop
    3961      * @return the text with any replacements processed, <code>null</code> if
    3962      *         null String input
    3963      * @throws IllegalArgumentException
    3964      *             if the search is repeating and there is an endless loop due
    3965      *             to outputs of one being inputs to another
    3966      * @throws IndexOutOfBoundsException
    3967      *             if the lengths of the arrays are not the same (null is ok,
    3968      *             and/or size 0)
    3969      * @since 2.4
    3970      */
    3971     private static String replaceEach(String text, String[] searchList, String[] replacementList, 
    3972                                       boolean repeat, int timeToLive) 
    3973     {
    3974 
    3975         // mchyzer Performance note: This creates very few new objects (one major goal)
    3976         // let me know if there are performance requests, we can create a harness to measure
    3977 
    3978         if (text == null || text.length() == 0 || searchList == null || 
    3979             searchList.length == 0 || replacementList == null || replacementList.length == 0) 
    3980         {
    3981             return text;
    3982         }
    3983 
    3984         // if recursing, this shouldnt be less than 0
    3985         if (timeToLive < 0) {
    3986             throw new IllegalStateException("TimeToLive of " + timeToLive + " is less than 0: " + text);
    3987         }
    3988 
    3989         int searchLength = searchList.length;
    3990         int replacementLength = replacementList.length;
    3991 
    3992         // make sure lengths are ok, these need to be equal
    3993         if (searchLength != replacementLength) {
    3994             throw new IllegalArgumentException("Search and Replace array lengths don't match: "
    3995                 + searchLength
    3996                 + " vs "
    3997                 + replacementLength);
    3998         }
    3999 
    4000         // keep track of which still have matches
    4001         boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
    4002 
    4003         // index on index that the match was found
    4004         int textIndex = -1;
    4005         int replaceIndex = -1;
    4006         int tempIndex = -1;
    4007 
    4008         // index of replace array that will replace the search string found
    4009         // NOTE: logic duplicated below START
    4010         for (int i = 0; i < searchLength; i++) {
    4011             if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 
    4012                 searchList[i].length() == 0 || replacementList[i] == null) 
    4013             {
    4014                 continue;
    4015             }
    4016             tempIndex = text.indexOf(searchList[i]);
    4017 
    4018             // see if we need to keep searching for this
    4019             if (tempIndex == -1) {
    4020                 noMoreMatchesForReplIndex[i] = true;
    4021             } else {
    4022                 if (textIndex == -1 || tempIndex < textIndex) {
    4023                     textIndex = tempIndex;
    4024                     replaceIndex = i;
    4025                 }
    4026             }
    4027         }
    4028         // NOTE: logic mostly below END
    4029 
    4030         // no search strings found, we are done
    4031         if (textIndex == -1) {
    4032             return text;
    4033         }
    4034 
    4035         int start = 0;
    4036 
    4037         // get a good guess on the size of the result buffer so it doesnt have to double if it goes over a bit
    4038         int increase = 0;
    4039 
    4040         // count the replacement text elements that are larger than their corresponding text being replaced
    4041         for (int i = 0; i < searchList.length; i++) {
    4042             if (searchList[i] == null || replacementList[i] == null) {
    4043                 continue;
    4044             }
    4045             int greater = replacementList[i].length() - searchList[i].length();
    4046             if (greater > 0) {
    4047                 increase += 3 * greater; // assume 3 matches
    4048             }
    4049         }
    4050         // have upper-bound at 20% increase, then let Java take over
    4051         increase = Math.min(increase, text.length() / 5);
    4052 
    4053         StrBuilder buf = new StrBuilder(text.length() + increase);
    4054 
    4055         while (textIndex != -1) {
    4056 
    4057             for (int i = start; i < textIndex; i++) {
    4058                 buf.append(text.charAt(i));
    4059             }
    4060             buf.append(replacementList[replaceIndex]);
    4061 
    4062             start = textIndex + searchList[replaceIndex].length();
    4063 
    4064             textIndex = -1;
    4065             replaceIndex = -1;
    4066             tempIndex = -1;
    4067             // find the next earliest match
    4068             // NOTE: logic mostly duplicated above START
    4069             for (int i = 0; i < searchLength; i++) {
    4070                 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 
    4071                     searchList[i].length() == 0 || replacementList[i] == null) 
    4072                 {
    4073                     continue;
    4074                 }
    4075                 tempIndex = text.indexOf(searchList[i], start);
    4076 
    4077                 // see if we need to keep searching for this
    4078                 if (tempIndex == -1) {
    4079                     noMoreMatchesForReplIndex[i] = true;
    4080                 } else {
    4081                     if (textIndex == -1 || tempIndex < textIndex) {
    4082                         textIndex = tempIndex;
    4083                         replaceIndex = i;
    4084                     }
    4085                 }
    4086             }
    4087             // NOTE: logic duplicated above END
    4088 
    4089         }
    4090         int textLength = text.length();
    4091         for (int i = start; i < textLength; i++) {
    4092             buf.append(text.charAt(i));
    4093         }
    4094         String result = buf.toString();
    4095         if (!repeat) {
    4096             return result;
    4097         }
    4098 
    4099         return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
    4100     }
    4101 
    4102     // Replace, character based
    4103     //-----------------------------------------------------------------------
    4104     /**
    4105      * <p>Replaces all occurrences of a character in a String with another.
    4106      * This is a null-safe version of {@link String#replace(char, char)}.</p>
    4107      *
    4108      * <p>A <code>null</code> string input returns <code>null</code>.
    4109      * An empty ("") string input returns an empty string.</p>
    4110      *
    4111      * <pre>
    4112      * StringUtils.replaceChars(null, *, *)        = null
    4113      * StringUtils.replaceChars("", *, *)          = ""
    4114      * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
    4115      * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
    4116      * </pre>
    4117      *
    4118      * @param str  String to replace characters in, may be null
    4119      * @param searchChar  the character to search for, may be null
    4120      * @param replaceChar  the character to replace, may be null
    4121      * @return modified String, <code>null</code> if null string input
    4122      * @since 2.0
    4123      */
    4124     public static String replaceChars(String str, char searchChar, char replaceChar) {
    4125         if (str == null) {
    4126             return null;
    4127         }
    4128         return str.replace(searchChar, replaceChar);
    4129     }
    4130 
    4131     /**
    4132      * <p>Replaces multiple characters in a String in one go.
    4133      * This method can also be used to delete characters.</p>
    4134      *
    4135      * <p>For example:<br />
    4136      * <code>replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly</code>.</p>
    4137      *
    4138      * <p>A <code>null</code> string input returns <code>null</code>.
    4139      * An empty ("") string input returns an empty string.
    4140      * A null or empty set of search characters returns the input string.</p>
    4141      *
    4142      * <p>The length of the search characters should normally equal the length
    4143      * of the replace characters.
    4144      * If the search characters is longer, then the extra search characters
    4145      * are deleted.
    4146      * If the search characters is shorter, then the extra replace characters
    4147      * are ignored.</p>
    4148      *
    4149      * <pre>
    4150      * StringUtils.replaceChars(null, *, *)           = null
    4151      * StringUtils.replaceChars("", *, *)             = ""
    4152      * StringUtils.replaceChars("abc", null, *)       = "abc"
    4153      * StringUtils.replaceChars("abc", "", *)         = "abc"
    4154      * StringUtils.replaceChars("abc", "b", null)     = "ac"
    4155      * StringUtils.replaceChars("abc", "b", "")       = "ac"
    4156      * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
    4157      * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
    4158      * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
    4159      * </pre>
    4160      *
    4161      * @param str  String to replace characters in, may be null
    4162      * @param searchChars  a set of characters to search for, may be null
    4163      * @param replaceChars  a set of characters to replace, may be null
    4164      * @return modified String, <code>null</code> if null string input
    4165      * @since 2.0
    4166      */
    4167     public static String replaceChars(String str, String searchChars, String replaceChars) {
    4168         if (isEmpty(str) || isEmpty(searchChars)) {
    4169             return str;
    4170         }
    4171         if (replaceChars == null) {
    4172             replaceChars = EMPTY;
    4173         }
    4174         boolean modified = false;
    4175         int replaceCharsLength = replaceChars.length();
    4176         int strLength = str.length();
    4177         StrBuilder buf = new StrBuilder(strLength);
    4178         for (int i = 0; i < strLength; i++) {
    4179             char ch = str.charAt(i);
    4180             int index = searchChars.indexOf(ch);
    4181             if (index >= 0) {
    4182                 modified = true;
    4183                 if (index < replaceCharsLength) {
    4184                     buf.append(replaceChars.charAt(index));
    4185                 }
    4186             } else {
    4187                 buf.append(ch);
    4188             }
    4189         }
    4190         if (modified) {
    4191             return buf.toString();
    4192         }
    4193         return str;
    4194     }
    4195 
    4196     // Overlay
    4197     //-----------------------------------------------------------------------
    4198     /**
    4199      * <p>Overlays part of a String with another String.</p>
    4200      *
    4201      * <pre>
    4202      * StringUtils.overlayString(null, *, *, *)           = NullPointerException
    4203      * StringUtils.overlayString(*, null, *, *)           = NullPointerException
    4204      * StringUtils.overlayString("", "abc", 0, 0)         = "abc"
    4205      * StringUtils.overlayString("abcdef", null, 2, 4)    = "abef"
    4206      * StringUtils.overlayString("abcdef", "", 2, 4)      = "abef"
    4207      * StringUtils.overlayString("abcdef", "zzzz", 2, 4)  = "abzzzzef"
    4208      * StringUtils.overlayString("abcdef", "zzzz", 4, 2)  = "abcdzzzzcdef"
    4209      * StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
    4210      * StringUtils.overlayString("abcdef", "zzzz", 2, 8)  = IndexOutOfBoundsException
    4211      * </pre>
    4212      *
    4213      * @param text  the String to do overlaying in, may be null
    4214      * @param overlay  the String to overlay, may be null
    4215      * @param start  the position to start overlaying at, must be valid
    4216      * @param end  the position to stop overlaying before, must be valid
    4217      * @return overlayed String, <code>null</code> if null String input
    4218      * @throws NullPointerException if text or overlay is null
    4219      * @throws IndexOutOfBoundsException if either position is invalid
    4220      * @deprecated Use better named {@link #overlay(String, String, int, int)} instead.
    4221      *             Method will be removed in Commons Lang 3.0.
    4222      */
    4223     public static String overlayString(String text, String overlay, int start, int end) {
    4224         return new StrBuilder(start + overlay.length() + text.length() - end + 1)
    4225             .append(text.substring(0, start))
    4226             .append(overlay)
    4227             .append(text.substring(end))
    4228             .toString();
    4229     }
    4230 
    4231     /**
    4232      * <p>Overlays part of a String with another String.</p>
    4233      *
    4234      * <p>A <code>null</code> string input returns <code>null</code>.
    4235      * A negative index is treated as zero.
    4236      * An index greater than the string length is treated as the string length.
    4237      * The start index is always the smaller of the two indices.</p>
    4238      *
    4239      * <pre>
    4240      * StringUtils.overlay(null, *, *, *)            = null
    4241      * StringUtils.overlay("", "abc", 0, 0)          = "abc"
    4242      * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
    4243      * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
    4244      * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
    4245      * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
    4246      * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
    4247      * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
    4248      * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
    4249      * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
    4250      * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
    4251      * </pre>
    4252      *
    4253      * @param str  the String to do overlaying in, may be null
    4254      * @param overlay  the String to overlay, may be null
    4255      * @param start  the position to start overlaying at
    4256      * @param end  the position to stop overlaying before
    4257      * @return overlayed String, <code>null</code> if null String input
    4258      * @since 2.0
    4259      */
    4260     public static String overlay(String str, String overlay, int start, int end) {
    4261         if (str == null) {
    4262             return null;
    4263         }
    4264         if (overlay == null) {
    4265             overlay = EMPTY;
    4266         }
    4267         int len = str.length();
    4268         if (start < 0) {
    4269             start = 0;
    4270         }
    4271         if (start > len) {
    4272             start = len;
    4273         }
    4274         if (end < 0) {
    4275             end = 0;
    4276         }
    4277         if (end > len) {
    4278             end = len;
    4279         }
    4280         if (start > end) {
    4281             int temp = start;
    4282             start = end;
    4283             end = temp;
    4284         }
    4285         return new StrBuilder(len + start - end + overlay.length() + 1)
    4286             .append(str.substring(0, start))
    4287             .append(overlay)
    4288             .append(str.substring(end))
    4289             .toString();
    4290     }
    4291 
    4292     // Chomping
    4293     //-----------------------------------------------------------------------
    4294     /**
    4295      * <p>Removes one newline from end of a String if it's there,
    4296      * otherwise leave it alone.  A newline is &quot;<code>\n</code>&quot;,
    4297      * &quot;<code>\r</code>&quot;, or &quot;<code>\r\n</code>&quot;.</p>
    4298      *
    4299      * <p>NOTE: This method changed in 2.0.
    4300      * It now more closely matches Perl chomp.</p>
    4301      *
    4302      * <pre>
    4303      * StringUtils.chomp(null)          = null
    4304      * StringUtils.chomp("")            = ""
    4305      * StringUtils.chomp("abc \r")      = "abc "
    4306      * StringUtils.chomp("abc\n")       = "abc"
    4307      * StringUtils.chomp("abc\r\n")     = "abc"
    4308      * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
    4309      * StringUtils.chomp("abc\n\r")     = "abc\n"
    4310      * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
    4311      * StringUtils.chomp("\r")          = ""
    4312      * StringUtils.chomp("\n")          = ""
    4313      * StringUtils.chomp("\r\n")        = ""
    4314      * </pre>
    4315      *
    4316      * @param str  the String to chomp a newline from, may be null
    4317      * @return String without newline, <code>null</code> if null String input
    4318      */
    4319     public static String chomp(String str) {
    4320         if (isEmpty(str)) {
    4321             return str;
    4322         }
    4323 
    4324         if (str.length() == 1) {
    4325             char ch = str.charAt(0);
    4326             if (ch == CharUtils.CR || ch == CharUtils.LF) {
    4327                 return EMPTY;
    4328             }
    4329             return str;
    4330         }
    4331 
    4332         int lastIdx = str.length() - 1;
    4333         char last = str.charAt(lastIdx);
    4334 
    4335         if (last == CharUtils.LF) {
    4336             if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    4337                 lastIdx--;
    4338             }
    4339         } else if (last != CharUtils.CR) {
    4340             lastIdx++;
    4341         }
    4342         return str.substring(0, lastIdx);
    4343     }
    4344 
    4345     /**
    4346      * <p>Removes <code>separator</code> from the end of
    4347      * <code>str</code> if it's there, otherwise leave it alone.</p>
    4348      *
    4349      * <p>NOTE: This method changed in version 2.0.
    4350      * It now more closely matches Perl chomp.
    4351      * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
    4352      * This method uses {@link String#endsWith(String)}.</p>
    4353      *
    4354      * <pre>
    4355      * StringUtils.chomp(null, *)         = null
    4356      * StringUtils.chomp("", *)           = ""
    4357      * StringUtils.chomp("foobar", "bar") = "foo"
    4358      * StringUtils.chomp("foobar", "baz") = "foobar"
    4359      * StringUtils.chomp("foo", "foo")    = ""
    4360      * StringUtils.chomp("foo ", "foo")   = "foo "
    4361      * StringUtils.chomp(" foo", "foo")   = " "
    4362      * StringUtils.chomp("foo", "foooo")  = "foo"
    4363      * StringUtils.chomp("foo", "")       = "foo"
    4364      * StringUtils.chomp("foo", null)     = "foo"
    4365      * </pre>
    4366      *
    4367      * @param str  the String to chomp from, may be null
    4368      * @param separator  separator String, may be null
    4369      * @return String without trailing separator, <code>null</code> if null String input
    4370      */
    4371     public static String chomp(String str, String separator) {
    4372         if (isEmpty(str) || separator == null) {
    4373             return str;
    4374         }
    4375         if (str.endsWith(separator)) {
    4376             return str.substring(0, str.length() - separator.length());
    4377         }
    4378         return str;
    4379     }
    4380 
    4381     /**
    4382      * <p>Remove any &quot;\n&quot; if and only if it is at the end
    4383      * of the supplied String.</p>
    4384      *
    4385      * @param str  the String to chomp from, must not be null
    4386      * @return String without chomped ending
    4387      * @throws NullPointerException if str is <code>null</code>
    4388      * @deprecated Use {@link #chomp(String)} instead.
    4389      *             Method will be removed in Commons Lang 3.0.
    4390      */
    4391     public static String chompLast(String str) {
    4392         return chompLast(str, "\n");
    4393     }
    4394 
    4395     /**
    4396      * <p>Remove a value if and only if the String ends with that value.</p>
    4397      *
    4398      * @param str  the String to chomp from, must not be null
    4399      * @param sep  the String to chomp, must not be null
    4400      * @return String without chomped ending
    4401      * @throws NullPointerException if str or sep is <code>null</code>
    4402      * @deprecated Use {@link #chomp(String,String)} instead.
    4403      *             Method will be removed in Commons Lang 3.0.
    4404      */
    4405     public static String chompLast(String str, String sep) {
    4406         if (str.length() == 0) {
    4407             return str;
    4408         }
    4409         String sub = str.substring(str.length() - sep.length());
    4410         if (sep.equals(sub)) {
    4411             return str.substring(0, str.length() - sep.length());
    4412         }
    4413         return str;
    4414     }
    4415 
    4416     /**
    4417      * <p>Remove everything and return the last value of a supplied String, and
    4418      * everything after it from a String.</p>
    4419      *
    4420      * @param str  the String to chomp from, must not be null
    4421      * @param sep  the String to chomp, must not be null
    4422      * @return String chomped
    4423      * @throws NullPointerException if str or sep is <code>null</code>
    4424      * @deprecated Use {@link #substringAfterLast(String, String)} instead
    4425      *             (although this doesn't include the separator)
    4426      *             Method will be removed in Commons Lang 3.0.
    4427      */
    4428     public static String getChomp(String str, String sep) {
    4429         int idx = str.lastIndexOf(sep);
    4430         if (idx == str.length() - sep.length()) {
    4431             return sep;
    4432         } else if (idx != -1) {
    4433             return str.substring(idx);
    4434         } else {
    4435             return EMPTY;
    4436         }
    4437     }
    4438 
    4439     /**
    4440      * <p>Remove the first value of a supplied String, and everything before it
    4441      * from a String.</p>
    4442      *
    4443      * @param str  the String to chomp from, must not be null
    4444      * @param sep  the String to chomp, must not be null
    4445      * @return String without chomped beginning
    4446      * @throws NullPointerException if str or sep is <code>null</code>
    4447      * @deprecated Use {@link #substringAfter(String,String)} instead.
    4448      *             Method will be removed in Commons Lang 3.0.
    4449      */
    4450     public static String prechomp(String str, String sep) {
    4451         int idx = str.indexOf(sep);
    4452         if (idx == -1) {
    4453             return str;
    4454         }             
    4455         return str.substring(idx + sep.length());
    4456     }
    4457 
    4458     /**
    4459      * <p>Remove and return everything before the first value of a
    4460      * supplied String from another String.</p>
    4461      *
    4462      * @param str  the String to chomp from, must not be null
    4463      * @param sep  the String to chomp, must not be null
    4464      * @return String prechomped
    4465      * @throws NullPointerException if str or sep is <code>null</code>
    4466      * @deprecated Use {@link #substringBefore(String,String)} instead
    4467      *             (although this doesn't include the separator).
    4468      *             Method will be removed in Commons Lang 3.0.
    4469      */
    4470     public static String getPrechomp(String str, String sep) {
    4471         int idx = str.indexOf(sep);
    4472         if (idx == -1) {
    4473             return EMPTY;
    4474         } 
    4475         return str.substring(0, idx + sep.length());
    4476     }
    4477 
    4478     // Chopping
    4479     //-----------------------------------------------------------------------
    4480     /**
    4481      * <p>Remove the last character from a String.</p>
    4482      *
    4483      * <p>If the String ends in <code>\r\n</code>, then remove both
    4484      * of them.</p>
    4485      *
    4486      * <pre>
    4487      * StringUtils.chop(null)          = null
    4488      * StringUtils.chop("")            = ""
    4489      * StringUtils.chop("abc \r")      = "abc "
    4490      * StringUtils.chop("abc\n")       = "abc"
    4491      * StringUtils.chop("abc\r\n")     = "abc"
    4492      * StringUtils.chop("abc")         = "ab"
    4493      * StringUtils.chop("abc\nabc")    = "abc\nab"
    4494      * StringUtils.chop("a")           = ""
    4495      * StringUtils.chop("\r")          = ""
    4496      * StringUtils.chop("\n")          = ""
    4497      * StringUtils.chop("\r\n")        = ""
    4498      * </pre>
    4499      *
    4500      * @param str  the String to chop last character from, may be null
    4501      * @return String without last character, <code>null</code> if null String input
    4502      */
    4503     public static String chop(String str) {
    4504         if (str == null) {
    4505             return null;
    4506         }
    4507         int strLen = str.length();
    4508         if (strLen < 2) {
    4509             return EMPTY;
    4510         }
    4511         int lastIdx = strLen - 1;
    4512         String ret = str.substring(0, lastIdx);
    4513         char last = str.charAt(lastIdx);
    4514         if (last == CharUtils.LF) {
    4515             if (ret.charAt(lastIdx - 1) == CharUtils.CR) {
    4516                 return ret.substring(0, lastIdx - 1);
    4517             }
    4518         }
    4519         return ret;
    4520     }
    4521 
    4522     /**
    4523      * <p>Removes <code>\n</code> from end of a String if it's there.
    4524      * If a <code>\r</code> precedes it, then remove that too.</p>
    4525      *
    4526      * @param str  the String to chop a newline from, must not be null
    4527      * @return String without newline
    4528      * @throws NullPointerException if str is <code>null</code>
    4529      * @deprecated Use {@link #chomp(String)} instead.
    4530      *             Method will be removed in Commons Lang 3.0.
    4531      */
    4532     public static String chopNewline(String str) {
    4533         int lastIdx = str.length() - 1;
    4534         if (lastIdx <= 0) {
    4535             return EMPTY;
    4536         }
    4537         char last = str.charAt(lastIdx);
    4538         if (last == CharUtils.LF) {
    4539             if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    4540                 lastIdx--;
    4541             }
    4542         } else {
    4543             lastIdx++;
    4544         }
    4545         return str.substring(0, lastIdx);
    4546     }
    4547 
    4548     // Conversion
    4549     //-----------------------------------------------------------------------
    4550     /**
    4551      * <p>Escapes any values it finds into their String form.</p>
    4552      *
    4553      * <p>So a tab becomes the characters <code>'\\'</code> and
    4554      * <code>'t'</code>.</p>
    4555      *
    4556      * <p>As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(String)}
    4557      * behind the scenes.
    4558      * </p>
    4559      * @see StringEscapeUtils#escapeJava(java.lang.String)
    4560      * @param str String to escape values in
    4561      * @return String with escaped values
    4562      * @throws NullPointerException if str is <code>null</code>
    4563      * @deprecated Use {@link StringEscapeUtils#escapeJava(String)}
    4564      *             This method will be removed in Commons Lang 3.0
    4565      */
    4566     public static String escape(String str) {
    4567         return StringEscapeUtils.escapeJava(str);
    4568     }
    4569 
    4570     // Padding
    4571     //-----------------------------------------------------------------------
    4572     /**
    4573      * <p>Repeat a String <code>repeat</code> times to form a
    4574      * new String.</p>
    4575      *
    4576      * <pre>
    4577      * StringUtils.repeat(null, 2) = null
    4578      * StringUtils.repeat("", 0)   = ""
    4579      * StringUtils.repeat("", 2)   = ""
    4580      * StringUtils.repeat("a", 3)  = "aaa"
    4581      * StringUtils.repeat("ab", 2) = "abab"
    4582      * StringUtils.repeat("a", -2) = ""
    4583      * </pre>
    4584      *
    4585      * @param str  the String to repeat, may be null
    4586      * @param repeat  number of times to repeat str, negative treated as zero
    4587      * @return a new String consisting of the original String repeated,
    4588      *  <code>null</code> if null String input
    4589      */
    4590     public static String repeat(String str, int repeat) {
    4591         // Performance tuned for 2.0 (JDK1.4)
    4592 
    4593         if (str == null) {
    4594             return null;
    4595         }
    4596         if (repeat <= 0) {
    4597             return EMPTY;
    4598         }
    4599         int inputLength = str.length();
    4600         if (repeat == 1 || inputLength == 0) {
    4601             return str;
    4602         }
    4603         if (inputLength == 1 && repeat <= PAD_LIMIT) {
    4604             return padding(repeat, str.charAt(0));
    4605         }
    4606 
    4607         int outputLength = inputLength * repeat;
    4608         switch (inputLength) {
    4609             case 1 :
    4610                 char ch = str.charAt(0);
    4611                 char[] output1 = new char[outputLength];
    4612                 for (int i = repeat - 1; i >= 0; i--) {
    4613                     output1[i] = ch;
    4614                 }
    4615                 return new String(output1);
    4616             case 2 :
    4617                 char ch0 = str.charAt(0);
    4618                 char ch1 = str.charAt(1);
    4619                 char[] output2 = new char[outputLength];
    4620                 for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
    4621                     output2[i] = ch0;
    4622                     output2[i + 1] = ch1;
    4623                 }
    4624                 return new String(output2);
    4625             default :
    4626                 StrBuilder buf = new StrBuilder(outputLength);
    4627                 for (int i = 0; i < repeat; i++) {
    4628                     buf.append(str);
    4629                 }
    4630                 return buf.toString();
    4631         }
    4632     }
    4633 
    4634     /**
    4635      * <p>Repeat a String <code>repeat</code> times to form a
    4636      * new String, with a String separator injected each time. </p>
    4637      *
    4638      * <pre>
    4639      * StringUtils.repeat(null, null, 2) = null
    4640      * StringUtils.repeat(null, "x", 2)  = null
    4641      * StringUtils.repeat("", null, 0)   = ""
    4642      * StringUtils.repeat("", "", 2)     = ""
    4643      * StringUtils.repeat("", "x", 3)    = "xxx"
    4644      * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
    4645      * </pre>
    4646      *
    4647      * @param str        the String to repeat, may be null
    4648      * @param separator  the String to inject, may be null
    4649      * @param repeat     number of times to repeat str, negative treated as zero
    4650      * @return a new String consisting of the original String repeated,
    4651      *  <code>null</code> if null String input
    4652      * @since 2.5
    4653      */
    4654     public static String repeat(String str, String separator, int repeat) {
    4655         if(str == null || separator == null) {
    4656             return repeat(str, repeat);
    4657         } else {
    4658             // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
    4659             String result = repeat(str + separator, repeat);
    4660             return removeEnd(result, separator);
    4661         }
    4662     }
    4663 
    4664     /**
    4665      * <p>Returns padding using the specified delimiter repeated
    4666      * to a given length.</p>
    4667      *
    4668      * <pre>
    4669      * StringUtils.padding(0, 'e')  = ""
    4670      * StringUtils.padding(3, 'e')  = "eee"
    4671      * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
    4672      * </pre>
    4673      *
    4674      * <p>Note: this method doesn't not support padding with
    4675      * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
    4676      * as they require a pair of <code>char</code>s to be represented.
    4677      * If you are needing to support full I18N of your applications
    4678      * consider using {@link #repeat(String, int)} instead. 
    4679      * </p>
    4680      *
    4681      * @param repeat  number of times to repeat delim
    4682      * @param padChar  character to repeat
    4683      * @return String with repeated character
    4684      * @throws IndexOutOfBoundsException if <code>repeat &lt; 0</code>
    4685      * @see #repeat(String, int)
    4686      */
    4687     private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
    4688         if (repeat < 0) {
    4689             throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
    4690         }
    4691         final char[] buf = new char[repeat];
    4692         for (int i = 0; i < buf.length; i++) {
    4693             buf[i] = padChar;
    4694         }
    4695         return new String(buf);
    4696     }
    4697 
    4698     /**
    4699      * <p>Right pad a String with spaces (' ').</p>
    4700      *
    4701      * <p>The String is padded to the size of <code>size</code>.</p>
    4702      *
    4703      * <pre>
    4704      * StringUtils.rightPad(null, *)   = null
    4705      * StringUtils.rightPad("", 3)     = "   "
    4706      * StringUtils.rightPad("bat", 3)  = "bat"
    4707      * StringUtils.rightPad("bat", 5)  = "bat  "
    4708      * StringUtils.rightPad("bat", 1)  = "bat"
    4709      * StringUtils.rightPad("bat", -1) = "bat"
    4710      * </pre>
    4711      *
    4712      * @param str  the String to pad out, may be null
    4713      * @param size  the size to pad to
    4714      * @return right padded String or original String if no padding is necessary,
    4715      *  <code>null</code> if null String input
    4716      */
    4717     public static String rightPad(String str, int size) {
    4718         return rightPad(str, size, ' ');
    4719     }
    4720 
    4721     /**
    4722      * <p>Right pad a String with a specified character.</p>
    4723      *
    4724      * <p>The String is padded to the size of <code>size</code>.</p>
    4725      *
    4726      * <pre>
    4727      * StringUtils.rightPad(null, *, *)     = null
    4728      * StringUtils.rightPad("", 3, 'z')     = "zzz"
    4729      * StringUtils.rightPad("bat", 3, 'z')  = "bat"
    4730      * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
    4731      * StringUtils.rightPad("bat", 1, 'z')  = "bat"
    4732      * StringUtils.rightPad("bat", -1, 'z') = "bat"
    4733      * </pre>
    4734      *
    4735      * @param str  the String to pad out, may be null
    4736      * @param size  the size to pad to
    4737      * @param padChar  the character to pad with
    4738      * @return right padded String or original String if no padding is necessary,
    4739      *  <code>null</code> if null String input
    4740      * @since 2.0
    4741      */
    4742     public static String rightPad(String str, int size, char padChar) {
    4743         if (str == null) {
    4744             return null;
    4745         }
    4746         int pads = size - str.length();
    4747         if (pads <= 0) {
    4748             return str; // returns original String when possible
    4749         }
    4750         if (pads > PAD_LIMIT) {
    4751             return rightPad(str, size, String.valueOf(padChar));
    4752         }
    4753         return str.concat(padding(pads, padChar));
    4754     }
    4755 
    4756     /**
    4757      * <p>Right pad a String with a specified String.</p>
    4758      *
    4759      * <p>The String is padded to the size of <code>size</code>.</p>
    4760      *
    4761      * <pre>
    4762      * StringUtils.rightPad(null, *, *)      = null
    4763      * StringUtils.rightPad("", 3, "z")      = "zzz"
    4764      * StringUtils.rightPad("bat", 3, "yz")  = "bat"
    4765      * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
    4766      * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
    4767      * StringUtils.rightPad("bat", 1, "yz")  = "bat"
    4768      * StringUtils.rightPad("bat", -1, "yz") = "bat"
    4769      * StringUtils.rightPad("bat", 5, null)  = "bat  "
    4770      * StringUtils.rightPad("bat", 5, "")    = "bat  "
    4771      * </pre>
    4772      *
    4773      * @param str  the String to pad out, may be null
    4774      * @param size  the size to pad to
    4775      * @param padStr  the String to pad with, null or empty treated as single space
    4776      * @return right padded String or original String if no padding is necessary,
    4777      *  <code>null</code> if null String input
    4778      */
    4779     public static String rightPad(String str, int size, String padStr) {
    4780         if (str == null) {
    4781             return null;
    4782         }
    4783         if (isEmpty(padStr)) {
    4784             padStr = " ";
    4785         }
    4786         int padLen = padStr.length();
    4787         int strLen = str.length();
    4788         int pads = size - strLen;
    4789         if (pads <= 0) {
    4790             return str; // returns original String when possible
    4791         }
    4792         if (padLen == 1 && pads <= PAD_LIMIT) {
    4793             return rightPad(str, size, padStr.charAt(0));
    4794         }
    4795 
    4796         if (pads == padLen) {
    4797             return str.concat(padStr);
    4798         } else if (pads < padLen) {
    4799             return str.concat(padStr.substring(0, pads));
    4800         } else {
    4801             char[] padding = new char[pads];
    4802             char[] padChars = padStr.toCharArray();
    4803             for (int i = 0; i < pads; i++) {
    4804                 padding[i] = padChars[i % padLen];
    4805             }
    4806             return str.concat(new String(padding));
    4807         }
    4808     }
    4809 
    4810     /**
    4811      * <p>Left pad a String with spaces (' ').</p>
    4812      *
    4813      * <p>The String is padded to the size of <code>size</code>.</p>
    4814      *
    4815      * <pre>
    4816      * StringUtils.leftPad(null, *)   = null
    4817      * StringUtils.leftPad("", 3)     = "   "
    4818      * StringUtils.leftPad("bat", 3)  = "bat"
    4819      * StringUtils.leftPad("bat", 5)  = "  bat"
    4820      * StringUtils.leftPad("bat", 1)  = "bat"
    4821      * StringUtils.leftPad("bat", -1) = "bat"
    4822      * </pre>
    4823      *
    4824      * @param str  the String to pad out, may be null
    4825      * @param size  the size to pad to
    4826      * @return left padded String or original String if no padding is necessary,
    4827      *  <code>null</code> if null String input
    4828      */
    4829     public static String leftPad(String str, int size) {
    4830         return leftPad(str, size, ' ');
    4831     }
    4832 
    4833     /**
    4834      * <p>Left pad a String with a specified character.</p>
    4835      *
    4836      * <p>Pad to a size of <code>size</code>.</p>
    4837      *
    4838      * <pre>
    4839      * StringUtils.leftPad(null, *, *)     = null
    4840      * StringUtils.leftPad("", 3, 'z')     = "zzz"
    4841      * StringUtils.leftPad("bat", 3, 'z')  = "bat"
    4842      * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
    4843      * StringUtils.leftPad("bat", 1, 'z')  = "bat"
    4844      * StringUtils.leftPad("bat", -1, 'z') = "bat"
    4845      * </pre>
    4846      *
    4847      * @param str  the String to pad out, may be null
    4848      * @param size  the size to pad to
    4849      * @param padChar  the character to pad with
    4850      * @return left padded String or original String if no padding is necessary,
    4851      *  <code>null</code> if null String input
    4852      * @since 2.0
    4853      */
    4854     public static String leftPad(String str, int size, char padChar) {
    4855         if (str == null) {
    4856             return null;
    4857         }
    4858         int pads = size - str.length();
    4859         if (pads <= 0) {
    4860             return str; // returns original String when possible
    4861         }
    4862         if (pads > PAD_LIMIT) {
    4863             return leftPad(str, size, String.valueOf(padChar));
    4864         }
    4865         return padding(pads, padChar).concat(str);
    4866     }
    4867 
    4868     /**
    4869      * <p>Left pad a String with a specified String.</p>
    4870      *
    4871      * <p>Pad to a size of <code>size</code>.</p>
    4872      *
    4873      * <pre>
    4874      * StringUtils.leftPad(null, *, *)      = null
    4875      * StringUtils.leftPad("", 3, "z")      = "zzz"
    4876      * StringUtils.leftPad("bat", 3, "yz")  = "bat"
    4877      * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
    4878      * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
    4879      * StringUtils.leftPad("bat", 1, "yz")  = "bat"
    4880      * StringUtils.leftPad("bat", -1, "yz") = "bat"
    4881      * StringUtils.leftPad("bat", 5, null)  = "  bat"
    4882      * StringUtils.leftPad("bat", 5, "")    = "  bat"
    4883      * </pre>
    4884      *
    4885      * @param str  the String to pad out, may be null
    4886      * @param size  the size to pad to
    4887      * @param padStr  the String to pad with, null or empty treated as single space
    4888      * @return left padded String or original String if no padding is necessary,
    4889      *  <code>null</code> if null String input
    4890      */
    4891     public static String leftPad(String str, int size, String padStr) {
    4892         if (str == null) {
    4893             return null;
    4894         }
    4895         if (isEmpty(padStr)) {
    4896             padStr = " ";
    4897         }
    4898         int padLen = padStr.length();
    4899         int strLen = str.length();
    4900         int pads = size - strLen;
    4901         if (pads <= 0) {
    4902             return str; // returns original String when possible
    4903         }
    4904         if (padLen == 1 && pads <= PAD_LIMIT) {
    4905             return leftPad(str, size, padStr.charAt(0));
    4906         }
    4907 
    4908         if (pads == padLen) {
    4909             return padStr.concat(str);
    4910         } else if (pads < padLen) {
    4911             return padStr.substring(0, pads).concat(str);
    4912         } else {
    4913             char[] padding = new char[pads];
    4914             char[] padChars = padStr.toCharArray();
    4915             for (int i = 0; i < pads; i++) {
    4916                 padding[i] = padChars[i % padLen];
    4917             }
    4918             return new String(padding).concat(str);
    4919         }
    4920     }
    4921 
    4922     /**
    4923      * Gets a String's length or <code>0</code> if the String is <code>null</code>.
    4924      * 
    4925      * @param str
    4926      *            a String or <code>null</code>
    4927      * @return String length or <code>0</code> if the String is <code>null</code>.
    4928      * @since 2.4
    4929      */
    4930     public static int length(String str) {
    4931         return str == null ? 0 : str.length();
    4932     }
    4933     
    4934     // Centering
    4935     //-----------------------------------------------------------------------
    4936     /**
    4937      * <p>Centers a String in a larger String of size <code>size</code>
    4938      * using the space character (' ').<p>
    4939      *
    4940      * <p>If the size is less than the String length, the String is returned.
    4941      * A <code>null</code> String returns <code>null</code>.
    4942      * A negative size is treated as zero.</p>
    4943      *
    4944      * <p>Equivalent to <code>center(str, size, " ")</code>.</p>
    4945      *
    4946      * <pre>
    4947      * StringUtils.center(null, *)   = null
    4948      * StringUtils.center("", 4)     = "    "
    4949      * StringUtils.center("ab", -1)  = "ab"
    4950      * StringUtils.center("ab", 4)   = " ab "
    4951      * StringUtils.center("abcd", 2) = "abcd"
    4952      * StringUtils.center("a", 4)    = " a  "
    4953      * </pre>
    4954      *
    4955      * @param str  the String to center, may be null
    4956      * @param size  the int size of new String, negative treated as zero
    4957      * @return centered String, <code>null</code> if null String input
    4958      */
    4959     public static String center(String str, int size) {
    4960         return center(str, size, ' ');
    4961     }
    4962 
    4963     /**
    4964      * <p>Centers a String in a larger String of size <code>size</code>.
    4965      * Uses a supplied character as the value to pad the String with.</p>
    4966      *
    4967      * <p>If the size is less than the String length, the String is returned.
    4968      * A <code>null</code> String returns <code>null</code>.
    4969      * A negative size is treated as zero.</p>
    4970      *
    4971      * <pre>
    4972      * StringUtils.center(null, *, *)     = null
    4973      * StringUtils.center("", 4, ' ')     = "    "
    4974      * StringUtils.center("ab", -1, ' ')  = "ab"
    4975      * StringUtils.center("ab", 4, ' ')   = " ab"
    4976      * StringUtils.center("abcd", 2, ' ') = "abcd"
    4977      * StringUtils.center("a", 4, ' ')    = " a  "
    4978      * StringUtils.center("a", 4, 'y')    = "yayy"
    4979      * </pre>
    4980      *
    4981      * @param str  the String to center, may be null
    4982      * @param size  the int size of new String, negative treated as zero
    4983      * @param padChar  the character to pad the new String with
    4984      * @return centered String, <code>null</code> if null String input
    4985      * @since 2.0
    4986      */
    4987     public static String center(String str, int size, char padChar) {
    4988         if (str == null || size <= 0) {
    4989             return str;
    4990         }
    4991         int strLen = str.length();
    4992         int pads = size - strLen;
    4993         if (pads <= 0) {
    4994             return str;
    4995         }
    4996         str = leftPad(str, strLen + pads / 2, padChar);
    4997         str = rightPad(str, size, padChar);
    4998         return str;
    4999     }
    5000 
    5001     /**
    5002      * <p>Centers a String in a larger String of size <code>size</code>.
    5003      * Uses a supplied String as the value to pad the String with.</p>
    5004      *
    5005      * <p>If the size is less than the String length, the String is returned.
    5006      * A <code>null</code> String returns <code>null</code>.
    5007      * A negative size is treated as zero.</p>
    5008      *
    5009      * <pre>
    5010      * StringUtils.center(null, *, *)     = null
    5011      * StringUtils.center("", 4, " ")     = "    "
    5012      * StringUtils.center("ab", -1, " ")  = "ab"
    5013      * StringUtils.center("ab", 4, " ")   = " ab"
    5014      * StringUtils.center("abcd", 2, " ") = "abcd"
    5015      * StringUtils.center("a", 4, " ")    = " a  "
    5016      * StringUtils.center("a", 4, "yz")   = "yayz"
    5017      * StringUtils.center("abc", 7, null) = "  abc  "
    5018      * StringUtils.center("abc", 7, "")   = "  abc  "
    5019      * </pre>
    5020      *
    5021      * @param str  the String to center, may be null
    5022      * @param size  the int size of new String, negative treated as zero
    5023      * @param padStr  the String to pad the new String with, must not be null or empty
    5024      * @return centered String, <code>null</code> if null String input
    5025      * @throws IllegalArgumentException if padStr is <code>null</code> or empty
    5026      */
    5027     public static String center(String str, int size, String padStr) {
    5028         if (str == null || size <= 0) {
    5029             return str;
    5030         }
    5031         if (isEmpty(padStr)) {
    5032             padStr = " ";
    5033         }
    5034         int strLen = str.length();
    5035         int pads = size - strLen;
    5036         if (pads <= 0) {
    5037             return str;
    5038         }
    5039         str = leftPad(str, strLen + pads / 2, padStr);
    5040         str = rightPad(str, size, padStr);
    5041         return str;
    5042     }
    5043 
    5044     // Case conversion
    5045     //-----------------------------------------------------------------------
    5046     /**
    5047      * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
    5048      *
    5049      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5050      *
    5051      * <pre>
    5052      * StringUtils.upperCase(null)  = null
    5053      * StringUtils.upperCase("")    = ""
    5054      * StringUtils.upperCase("aBc") = "ABC"
    5055      * </pre>
    5056      *
    5057      * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
    5058      * the result of this method is affected by the current locale.
    5059      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5060      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5061      *
    5062      * @param str  the String to upper case, may be null
    5063      * @return the upper cased String, <code>null</code> if null String input
    5064      */
    5065     public static String upperCase(String str) {
    5066         if (str == null) {
    5067             return null;
    5068         }
    5069         return str.toUpperCase();
    5070     }
    5071 
    5072     /**
    5073      * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
    5074      *
    5075      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5076      *
    5077      * <pre>
    5078      * StringUtils.upperCase(null, Locale.ENGLISH)  = null
    5079      * StringUtils.upperCase("", Locale.ENGLISH)    = ""
    5080      * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
    5081      * </pre>
    5082      *
    5083      * @param str  the String to upper case, may be null
    5084      * @param locale  the locale that defines the case transformation rules, must not be null
    5085      * @return the upper cased String, <code>null</code> if null String input
    5086      * @since 2.5
    5087      */
    5088     public static String upperCase(String str, Locale locale) {
    5089         if (str == null) {
    5090             return null;
    5091         }
    5092         return str.toUpperCase(locale);
    5093     }
    5094 
    5095     /**
    5096      * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
    5097      *
    5098      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5099      *
    5100      * <pre>
    5101      * StringUtils.lowerCase(null)  = null
    5102      * StringUtils.lowerCase("")    = ""
    5103      * StringUtils.lowerCase("aBc") = "abc"
    5104      * </pre>
    5105      *
    5106      * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
    5107      * the result of this method is affected by the current locale.
    5108      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5109      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5110      *
    5111      * @param str  the String to lower case, may be null
    5112      * @return the lower cased String, <code>null</code> if null String input
    5113      */
    5114     public static String lowerCase(String str) {
    5115         if (str == null) {
    5116             return null;
    5117         }
    5118         return str.toLowerCase();
    5119     }
    5120 
    5121     /**
    5122      * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
    5123      *
    5124      * <p>A <code>null</code> input String returns <code>null</code>.</p>
    5125      *
    5126      * <pre>
    5127      * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
    5128      * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
    5129      * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
    5130      * </pre>
    5131      *
    5132      * @param str  the String to lower case, may be null
    5133      * @param locale  the locale that defines the case transformation rules, must not be null
    5134      * @return the lower cased String, <code>null</code> if null String input
    5135      * @since 2.5
    5136      */
    5137     public static String lowerCase(String str, Locale locale) {
    5138         if (str == null) {
    5139             return null;
    5140         }
    5141         return str.toLowerCase(locale);
    5142     }
    5143 
    5144     /**
    5145      * <p>Capitalizes a String changing the first letter to title case as
    5146      * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
    5147      *
    5148      * <p>For a word based algorithm, see {@link WordUtils#capitalize(String)}.
    5149      * A <code>null</code> input String returns <code>null</code>.</p>
    5150      *
    5151      * <pre>
    5152      * StringUtils.capitalize(null)  = null
    5153      * StringUtils.capitalize("")    = ""
    5154      * StringUtils.capitalize("cat") = "Cat"
    5155      * StringUtils.capitalize("cAt") = "CAt"
    5156      * </pre>
    5157      *
    5158      * @param str  the String to capitalize, may be null
    5159      * @return the capitalized String, <code>null</code> if null String input
    5160      * @see WordUtils#capitalize(String)
    5161      * @see #uncapitalize(String)
    5162      * @since 2.0
    5163      */
    5164     public static String capitalize(String str) {
    5165         int strLen;
    5166         if (str == null || (strLen = str.length()) == 0) {
    5167             return str;
    5168         }
    5169         return new StrBuilder(strLen)
    5170             .append(Character.toTitleCase(str.charAt(0)))
    5171             .append(str.substring(1))
    5172             .toString();
    5173     }
    5174 
    5175     /**
    5176      * <p>Capitalizes a String changing the first letter to title case as
    5177      * per {@link Character#toTitleCase(char)}. No other letters are changed.</p>
    5178      *
    5179      * @param str  the String to capitalize, may be null
    5180      * @return the capitalized String, <code>null</code> if null String input
    5181      * @deprecated Use the standardly named {@link #capitalize(String)}.
    5182      *             Method will be removed in Commons Lang 3.0.
    5183      */
    5184     public static String capitalise(String str) {
    5185         return capitalize(str);
    5186     }
    5187 
    5188     /**
    5189      * <p>Uncapitalizes a String changing the first letter to title case as
    5190      * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
    5191      *
    5192      * <p>For a word based algorithm, see {@link WordUtils#uncapitalize(String)}.
    5193      * A <code>null</code> input String returns <code>null</code>.</p>
    5194      *
    5195      * <pre>
    5196      * StringUtils.uncapitalize(null)  = null
    5197      * StringUtils.uncapitalize("")    = ""
    5198      * StringUtils.uncapitalize("Cat") = "cat"
    5199      * StringUtils.uncapitalize("CAT") = "cAT"
    5200      * </pre>
    5201      *
    5202      * @param str  the String to uncapitalize, may be null
    5203      * @return the uncapitalized String, <code>null</code> if null String input
    5204      * @see WordUtils#uncapitalize(String)
    5205      * @see #capitalize(String)
    5206      * @since 2.0
    5207      */
    5208     public static String uncapitalize(String str) {
    5209         int strLen;
    5210         if (str == null || (strLen = str.length()) == 0) {
    5211             return str;
    5212         }
    5213         return new StrBuilder(strLen)
    5214             .append(Character.toLowerCase(str.charAt(0)))
    5215             .append(str.substring(1))
    5216             .toString();
    5217     }
    5218 
    5219     /**
    5220      * <p>Uncapitalizes a String changing the first letter to title case as
    5221      * per {@link Character#toLowerCase(char)}. No other letters are changed.</p>
    5222      *
    5223      * @param str  the String to uncapitalize, may be null
    5224      * @return the uncapitalized String, <code>null</code> if null String input
    5225      * @deprecated Use the standardly named {@link #uncapitalize(String)}.
    5226      *             Method will be removed in Commons Lang 3.0.
    5227      */
    5228     public static String uncapitalise(String str) {
    5229         return uncapitalize(str);
    5230     }
    5231 
    5232     /**
    5233      * <p>Swaps the case of a String changing upper and title case to
    5234      * lower case, and lower case to upper case.</p>
    5235      *
    5236      * <ul>
    5237      *  <li>Upper case character converts to Lower case</li>
    5238      *  <li>Title case character converts to Lower case</li>
    5239      *  <li>Lower case character converts to Upper case</li>
    5240      * </ul>
    5241      *
    5242      * <p>For a word based algorithm, see {@link WordUtils#swapCase(String)}.
    5243      * A <code>null</code> input String returns <code>null</code>.</p>
    5244      *
    5245      * <pre>
    5246      * StringUtils.swapCase(null)                 = null
    5247      * StringUtils.swapCase("")                   = ""
    5248      * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
    5249      * </pre>
    5250      *
    5251      * <p>NOTE: This method changed in Lang version 2.0.
    5252      * It no longer performs a word based algorithm.
    5253      * If you only use ASCII, you will notice no change.
    5254      * That functionality is available in WordUtils.</p>
    5255      *
    5256      * @param str  the String to swap case, may be null
    5257      * @return the changed String, <code>null</code> if null String input
    5258      */
    5259     public static String swapCase(String str) {
    5260         int strLen;
    5261         if (str == null || (strLen = str.length()) == 0) {
    5262             return str;
    5263         }
    5264         StrBuilder buffer = new StrBuilder(strLen);
    5265 
    5266         char ch = 0;
    5267         for (int i = 0; i < strLen; i++) {
    5268             ch = str.charAt(i);
    5269             if (Character.isUpperCase(ch)) {
    5270                 ch = Character.toLowerCase(ch);
    5271             } else if (Character.isTitleCase(ch)) {
    5272                 ch = Character.toLowerCase(ch);
    5273             } else if (Character.isLowerCase(ch)) {
    5274                 ch = Character.toUpperCase(ch);
    5275             }
    5276             buffer.append(ch);
    5277         }
    5278         return buffer.toString();
    5279     }
    5280 
    5281     /**
    5282      * <p>Capitalizes all the whitespace separated words in a String.
    5283      * Only the first letter of each word is changed.</p>
    5284      *
    5285      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
    5286      * A <code>null</code> input String returns <code>null</code>.</p>
    5287      *
    5288      * @param str  the String to capitalize, may be null
    5289      * @return capitalized String, <code>null</code> if null String input
    5290      * @deprecated Use the relocated {@link WordUtils#capitalize(String)}.
    5291      *             Method will be removed in Commons Lang 3.0.
    5292      */
    5293     public static String capitaliseAllWords(String str) {
    5294         return WordUtils.capitalize(str);
    5295     }
    5296 
    5297     // Count matches
    5298     //-----------------------------------------------------------------------
    5299     /**
    5300      * <p>Counts how many times the substring appears in the larger String.</p>
    5301      *
    5302      * <p>A <code>null</code> or empty ("") String input returns <code>0</code>.</p>
    5303      *
    5304      * <pre>
    5305      * StringUtils.countMatches(null, *)       = 0
    5306      * StringUtils.countMatches("", *)         = 0
    5307      * StringUtils.countMatches("abba", null)  = 0
    5308      * StringUtils.countMatches("abba", "")    = 0
    5309      * StringUtils.countMatches("abba", "a")   = 2
    5310      * StringUtils.countMatches("abba", "ab")  = 1
    5311      * StringUtils.countMatches("abba", "xxx") = 0
    5312      * </pre>
    5313      *
    5314      * @param str  the String to check, may be null
    5315      * @param sub  the substring to count, may be null
    5316      * @return the number of occurrences, 0 if either String is <code>null</code>
    5317      */
    5318     public static int countMatches(String str, String sub) {
    5319         if (isEmpty(str) || isEmpty(sub)) {
    5320             return 0;
    5321         }
    5322         int count = 0;
    5323         int idx = 0;
    5324         while ((idx = str.indexOf(sub, idx)) != INDEX_NOT_FOUND) {
    5325             count++;
    5326             idx += sub.length();
    5327         }
    5328         return count;
    5329     }
    5330 
    5331     // Character Tests
    5332     //-----------------------------------------------------------------------
    5333     /**
    5334      * <p>Checks if the String contains only unicode letters.</p>
    5335      *
    5336      * <p><code>null</code> will return <code>false</code>.
    5337      * An empty String (length()=0) will return <code>true</code>.</p>
    5338      *
    5339      * <pre>
    5340      * StringUtils.isAlpha(null)   = false
    5341      * StringUtils.isAlpha("")     = true
    5342      * StringUtils.isAlpha("  ")   = false
    5343      * StringUtils.isAlpha("abc")  = true
    5344      * StringUtils.isAlpha("ab2c") = false
    5345      * StringUtils.isAlpha("ab-c") = false
    5346      * </pre>
    5347      *
    5348      * @param str  the String to check, may be null
    5349      * @return <code>true</code> if only contains letters, and is non-null
    5350      */
    5351     public static boolean isAlpha(String str) {
    5352         if (str == null) {
    5353             return false;
    5354         }
    5355         int sz = str.length();
    5356         for (int i = 0; i < sz; i++) {
    5357             if (Character.isLetter(str.charAt(i)) == false) {
    5358                 return false;
    5359             }
    5360         }
    5361         return true;
    5362     }
    5363 
    5364     /**
    5365      * <p>Checks if the String contains only unicode letters and
    5366      * space (' ').</p>
    5367      *
    5368      * <p><code>null</code> will return <code>false</code>
    5369      * An empty String (length()=0) will return <code>true</code>.</p>
    5370      *
    5371      * <pre>
    5372      * StringUtils.isAlphaSpace(null)   = false
    5373      * StringUtils.isAlphaSpace("")     = true
    5374      * StringUtils.isAlphaSpace("  ")   = true
    5375      * StringUtils.isAlphaSpace("abc")  = true
    5376      * StringUtils.isAlphaSpace("ab c") = true
    5377      * StringUtils.isAlphaSpace("ab2c") = false
    5378      * StringUtils.isAlphaSpace("ab-c") = false
    5379      * </pre>
    5380      *
    5381      * @param str  the String to check, may be null
    5382      * @return <code>true</code> if only contains letters and space,
    5383      *  and is non-null
    5384      */
    5385     public static boolean isAlphaSpace(String str) {
    5386         if (str == null) {
    5387             return false;
    5388         }
    5389         int sz = str.length();
    5390         for (int i = 0; i < sz; i++) {
    5391             if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5392                 return false;
    5393             }
    5394         }
    5395         return true;
    5396     }
    5397 
    5398     /**
    5399      * <p>Checks if the String contains only unicode letters or digits.</p>
    5400      *
    5401      * <p><code>null</code> will return <code>false</code>.
    5402      * An empty String (length()=0) will return <code>true</code>.</p>
    5403      *
    5404      * <pre>
    5405      * StringUtils.isAlphanumeric(null)   = false
    5406      * StringUtils.isAlphanumeric("")     = true
    5407      * StringUtils.isAlphanumeric("  ")   = false
    5408      * StringUtils.isAlphanumeric("abc")  = true
    5409      * StringUtils.isAlphanumeric("ab c") = false
    5410      * StringUtils.isAlphanumeric("ab2c") = true
    5411      * StringUtils.isAlphanumeric("ab-c") = false
    5412      * </pre>
    5413      *
    5414      * @param str  the String to check, may be null
    5415      * @return <code>true</code> if only contains letters or digits,
    5416      *  and is non-null
    5417      */
    5418     public static boolean isAlphanumeric(String str) {
    5419         if (str == null) {
    5420             return false;
    5421         }
    5422         int sz = str.length();
    5423         for (int i = 0; i < sz; i++) {
    5424             if (Character.isLetterOrDigit(str.charAt(i)) == false) {
    5425                 return false;
    5426             }
    5427         }
    5428         return true;
    5429     }
    5430 
    5431     /**
    5432      * <p>Checks if the String contains only unicode letters, digits
    5433      * or space (<code>' '</code>).</p>
    5434      *
    5435      * <p><code>null</code> will return <code>false</code>.
    5436      * An empty String (length()=0) will return <code>true</code>.</p>
    5437      *
    5438      * <pre>
    5439      * StringUtils.isAlphanumeric(null)   = false
    5440      * StringUtils.isAlphanumeric("")     = true
    5441      * StringUtils.isAlphanumeric("  ")   = true
    5442      * StringUtils.isAlphanumeric("abc")  = true
    5443      * StringUtils.isAlphanumeric("ab c") = true
    5444      * StringUtils.isAlphanumeric("ab2c") = true
    5445      * StringUtils.isAlphanumeric("ab-c") = false
    5446      * </pre>
    5447      *
    5448      * @param str  the String to check, may be null
    5449      * @return <code>true</code> if only contains letters, digits or space,
    5450      *  and is non-null
    5451      */
    5452     public static boolean isAlphanumericSpace(String str) {
    5453         if (str == null) {
    5454             return false;
    5455         }
    5456         int sz = str.length();
    5457         for (int i = 0; i < sz; i++) {
    5458             if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5459                 return false;
    5460             }
    5461         }
    5462         return true;
    5463     }
    5464 
    5465     /**
    5466      * <p>Checks if the string contains only ASCII printable characters.</p>
    5467      * 
    5468      * <p><code>null</code> will return <code>false</code>.
    5469      * An empty String (length()=0) will return <code>true</code>.</p>
    5470      * 
    5471      * <pre>
    5472      * StringUtils.isAsciiPrintable(null)     = false
    5473      * StringUtils.isAsciiPrintable("")       = true
    5474      * StringUtils.isAsciiPrintable(" ")      = true
    5475      * StringUtils.isAsciiPrintable("Ceki")   = true
    5476      * StringUtils.isAsciiPrintable("ab2c")   = true
    5477      * StringUtils.isAsciiPrintable("!ab-c~") = true
    5478      * StringUtils.isAsciiPrintable("\u0020") = true
    5479      * StringUtils.isAsciiPrintable("\u0021") = true
    5480      * StringUtils.isAsciiPrintable("\u007e") = true
    5481      * StringUtils.isAsciiPrintable("\u007f") = false
    5482      * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
    5483      * </pre>
    5484      *
    5485      * @param str the string to check, may be null
    5486      * @return <code>true</code> if every character is in the range
    5487      *  32 thru 126
    5488      * @since 2.1
    5489      */
    5490     public static boolean isAsciiPrintable(String str) {
    5491         if (str == null) {
    5492             return false;
    5493         }
    5494         int sz = str.length();
    5495         for (int i = 0; i < sz; i++) {
    5496             if (CharUtils.isAsciiPrintable(str.charAt(i)) == false) {
    5497                 return false;
    5498             }
    5499         }
    5500         return true;
    5501     }
    5502 
    5503     /**
    5504      * <p>Checks if the String contains only unicode digits.
    5505      * A decimal point is not a unicode digit and returns false.</p>
    5506      *
    5507      * <p><code>null</code> will return <code>false</code>.
    5508      * An empty String (length()=0) will return <code>true</code>.</p>
    5509      *
    5510      * <pre>
    5511      * StringUtils.isNumeric(null)   = false
    5512      * StringUtils.isNumeric("")     = true
    5513      * StringUtils.isNumeric("  ")   = false
    5514      * StringUtils.isNumeric("123")  = true
    5515      * StringUtils.isNumeric("12 3") = false
    5516      * StringUtils.isNumeric("ab2c") = false
    5517      * StringUtils.isNumeric("12-3") = false
    5518      * StringUtils.isNumeric("12.3") = false
    5519      * </pre>
    5520      *
    5521      * @param str  the String to check, may be null
    5522      * @return <code>true</code> if only contains digits, and is non-null
    5523      */
    5524     public static boolean isNumeric(String str) {
    5525         if (str == null) {
    5526             return false;
    5527         }
    5528         int sz = str.length();
    5529         for (int i = 0; i < sz; i++) {
    5530             if (Character.isDigit(str.charAt(i)) == false) {
    5531                 return false;
    5532             }
    5533         }
    5534         return true;
    5535     }
    5536 
    5537     /**
    5538      * <p>Checks if the String contains only unicode digits or space
    5539      * (<code>' '</code>).
    5540      * A decimal point is not a unicode digit and returns false.</p>
    5541      *
    5542      * <p><code>null</code> will return <code>false</code>.
    5543      * An empty String (length()=0) will return <code>true</code>.</p>
    5544      *
    5545      * <pre>
    5546      * StringUtils.isNumeric(null)   = false
    5547      * StringUtils.isNumeric("")     = true
    5548      * StringUtils.isNumeric("  ")   = true
    5549      * StringUtils.isNumeric("123")  = true
    5550      * StringUtils.isNumeric("12 3") = true
    5551      * StringUtils.isNumeric("ab2c") = false
    5552      * StringUtils.isNumeric("12-3") = false
    5553      * StringUtils.isNumeric("12.3") = false
    5554      * </pre>
    5555      *
    5556      * @param str  the String to check, may be null
    5557      * @return <code>true</code> if only contains digits or space,
    5558      *  and is non-null
    5559      */
    5560     public static boolean isNumericSpace(String str) {
    5561         if (str == null) {
    5562             return false;
    5563         }
    5564         int sz = str.length();
    5565         for (int i = 0; i < sz; i++) {
    5566             if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
    5567                 return false;
    5568             }
    5569         }
    5570         return true;
    5571     }
    5572 
    5573     /**
    5574      * <p>Checks if the String contains only whitespace.</p>
    5575      *
    5576      * <p><code>null</code> will return <code>false</code>.
    5577      * An empty String (length()=0) will return <code>true</code>.</p>
    5578      *
    5579      * <pre>
    5580      * StringUtils.isWhitespace(null)   = false
    5581      * StringUtils.isWhitespace("")     = true
    5582      * StringUtils.isWhitespace("  ")   = true
    5583      * StringUtils.isWhitespace("abc")  = false
    5584      * StringUtils.isWhitespace("ab2c") = false
    5585      * StringUtils.isWhitespace("ab-c") = false
    5586      * </pre>
    5587      *
    5588      * @param str  the String to check, may be null
    5589      * @return <code>true</code> if only contains whitespace, and is non-null
    5590      * @since 2.0
    5591      */
    5592     public static boolean isWhitespace(String str) {
    5593         if (str == null) {
    5594             return false;
    5595         }
    5596         int sz = str.length();
    5597         for (int i = 0; i < sz; i++) {
    5598             if ((Character.isWhitespace(str.charAt(i)) == false)) {
    5599                 return false;
    5600             }
    5601         }
    5602         return true;
    5603     }
    5604 
    5605     /**
    5606      * <p>Checks if the String contains only lowercase characters.</p>
    5607      *
    5608      * <p><code>null</code> will return <code>false</code>.
    5609      * An empty String (length()=0) will return <code>false</code>.</p>
    5610      *
    5611      * <pre>
    5612      * StringUtils.isAllLowerCase(null)   = false
    5613      * StringUtils.isAllLowerCase("")     = false
    5614      * StringUtils.isAllLowerCase("  ")   = false
    5615      * StringUtils.isAllLowerCase("abc")  = true
    5616      * StringUtils.isAllLowerCase("abC") = false
    5617      * </pre>
    5618      *
    5619      * @param str  the String to check, may be null
    5620      * @return <code>true</code> if only contains lowercase characters, and is non-null
    5621      * @since 2.5
    5622      */
    5623     public static boolean isAllLowerCase(String str) {
    5624         if (str == null || isEmpty(str)) {
    5625             return false;
    5626         }
    5627         int sz = str.length();
    5628         for (int i = 0; i < sz; i++) {
    5629             if (Character.isLowerCase(str.charAt(i)) == false) {
    5630                 return false;
    5631             }
    5632         }
    5633         return true;
    5634     }
    5635 
    5636     /**
    5637      * <p>Checks if the String contains only uppercase characters.</p>
    5638      *
    5639      * <p><code>null</code> will return <code>false</code>.
    5640      * An empty String (length()=0) will return <code>false</code>.</p>
    5641      *
    5642      * <pre>
    5643      * StringUtils.isAllUpperCase(null)   = false
    5644      * StringUtils.isAllUpperCase("")     = false
    5645      * StringUtils.isAllUpperCase("  ")   = false
    5646      * StringUtils.isAllUpperCase("ABC")  = true
    5647      * StringUtils.isAllUpperCase("aBC") = false
    5648      * </pre>
    5649      *
    5650      * @param str  the String to check, may be null
    5651      * @return <code>true</code> if only contains uppercase characters, and is non-null
    5652      * @since 2.5
    5653      */
    5654     public static boolean isAllUpperCase(String str) {
    5655         if (str == null || isEmpty(str)) {
    5656             return false;
    5657         }
    5658         int sz = str.length();
    5659         for (int i = 0; i < sz; i++) {
    5660             if (Character.isUpperCase(str.charAt(i)) == false) {
    5661                 return false;
    5662             }
    5663         }
    5664         return true;
    5665     }
    5666 
    5667     // Defaults
    5668     //-----------------------------------------------------------------------
    5669     /**
    5670      * <p>Returns either the passed in String,
    5671      * or if the String is <code>null</code>, an empty String ("").</p>
    5672      *
    5673      * <pre>
    5674      * StringUtils.defaultString(null)  = ""
    5675      * StringUtils.defaultString("")    = ""
    5676      * StringUtils.defaultString("bat") = "bat"
    5677      * </pre>
    5678      *
    5679      * @see ObjectUtils#toString(Object)
    5680      * @see String#valueOf(Object)
    5681      * @param str  the String to check, may be null
    5682      * @return the passed in String, or the empty String if it
    5683      *  was <code>null</code>
    5684      */
    5685     public static String defaultString(String str) {
    5686         return str == null ? EMPTY : str;
    5687     }
    5688 
    5689     /**
    5690      * <p>Returns either the passed in String, or if the String is
    5691      * <code>null</code>, the value of <code>defaultStr</code>.</p>
    5692      *
    5693      * <pre>
    5694      * StringUtils.defaultString(null, "NULL")  = "NULL"
    5695      * StringUtils.defaultString("", "NULL")    = ""
    5696      * StringUtils.defaultString("bat", "NULL") = "bat"
    5697      * </pre>
    5698      *
    5699      * @see ObjectUtils#toString(Object,String)
    5700      * @see String#valueOf(Object)
    5701      * @param str  the String to check, may be null
    5702      * @param defaultStr  the default String to return
    5703      *  if the input is <code>null</code>, may be null
    5704      * @return the passed in String, or the default if it was <code>null</code>
    5705      */
    5706     public static String defaultString(String str, String defaultStr) {
    5707         return str == null ? defaultStr : str;
    5708     }
    5709 
    5710     /**
    5711      * <p>Returns either the passed in String, or if the String is
    5712      * whitespace, empty ("") or <code>null</code>, the value of <code>defaultStr</code>.</p>
    5713      *
    5714      * <pre>
    5715      * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
    5716      * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
    5717      * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
    5718      * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
    5719      * StringUtils.defaultIfBlank("", null)      = null
    5720      * </pre>
    5721      * @param str the String to check, may be null
    5722      * @param defaultStr  the default String to return
    5723      *  if the input is whitespace, empty ("") or <code>null</code>, may be null
    5724      * @return the passed in String, or the default
    5725      * @see StringUtils#defaultString(String, String)
    5726      * @since 2.6
    5727      */
    5728     public static String defaultIfBlank(String str, String defaultStr) {
    5729         return StringUtils.isBlank(str) ? defaultStr : str;
    5730     }
    5731 
    5732     /**
    5733      * <p>Returns either the passed in String, or if the String is
    5734      * empty or <code>null</code>, the value of <code>defaultStr</code>.</p>
    5735      *
    5736      * <pre>
    5737      * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
    5738      * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
    5739      * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
    5740      * StringUtils.defaultIfEmpty("", null)      = null
    5741      * </pre>
    5742      *
    5743      * @param str  the String to check, may be null
    5744      * @param defaultStr  the default String to return
    5745      *  if the input is empty ("") or <code>null</code>, may be null
    5746      * @return the passed in String, or the default
    5747      * @see StringUtils#defaultString(String, String)
    5748      */
    5749     public static String defaultIfEmpty(String str, String defaultStr) {
    5750         return StringUtils.isEmpty(str) ? defaultStr : str;
    5751     }
    5752 
    5753     // Reversing
    5754     //-----------------------------------------------------------------------
    5755     /**
    5756      * <p>Reverses a String as per {@link StrBuilder#reverse()}.</p>
    5757      *
    5758      * <p>A <code>null</code> String returns <code>null</code>.</p>
    5759      *
    5760      * <pre>
    5761      * StringUtils.reverse(null)  = null
    5762      * StringUtils.reverse("")    = ""
    5763      * StringUtils.reverse("bat") = "tab"
    5764      * </pre>
    5765      *
    5766      * @param str  the String to reverse, may be null
    5767      * @return the reversed String, <code>null</code> if null String input
    5768      */
    5769     public static String reverse(String str) {
    5770         if (str == null) {
    5771             return null;
    5772         }
    5773         return new StrBuilder(str).reverse().toString();
    5774     }
    5775 
    5776     /**
    5777      * <p>Reverses a String that is delimited by a specific character.</p>
    5778      *
    5779      * <p>The Strings between the delimiters are not reversed.
    5780      * Thus java.lang.String becomes String.lang.java (if the delimiter
    5781      * is <code>'.'</code>).</p>
    5782      *
    5783      * <pre>
    5784      * StringUtils.reverseDelimited(null, *)      = null
    5785      * StringUtils.reverseDelimited("", *)        = ""
    5786      * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
    5787      * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
    5788      * </pre>
    5789      *
    5790      * @param str  the String to reverse, may be null
    5791      * @param separatorChar  the separator character to use
    5792      * @return the reversed String, <code>null</code> if null String input
    5793      * @since 2.0
    5794      */
    5795     public static String reverseDelimited(String str, char separatorChar) {
    5796         if (str == null) {
    5797             return null;
    5798         }
    5799         // could implement manually, but simple way is to reuse other,
    5800         // probably slower, methods.
    5801         String[] strs = split(str, separatorChar);
    5802         ArrayUtils.reverse(strs);
    5803         return join(strs, separatorChar);
    5804     }
    5805 
    5806     /**
    5807      * <p>Reverses a String that is delimited by a specific character.</p>
    5808      *
    5809      * <p>The Strings between the delimiters are not reversed.
    5810      * Thus java.lang.String becomes String.lang.java (if the delimiter
    5811      * is <code>"."</code>).</p>
    5812      *
    5813      * <pre>
    5814      * StringUtils.reverseDelimitedString(null, *)       = null
    5815      * StringUtils.reverseDelimitedString("",*)          = ""
    5816      * StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
    5817      * StringUtils.reverseDelimitedString("a.b.c", ".")  = "c.b.a"
    5818      * </pre>
    5819      *
    5820      * @param str  the String to reverse, may be null
    5821      * @param separatorChars  the separator characters to use, null treated as whitespace
    5822      * @return the reversed String, <code>null</code> if null String input
    5823      * @deprecated Use {@link #reverseDelimited(String, char)} instead.
    5824      *      This method is broken as the join doesn't know which char to use.
    5825      *      Method will be removed in Commons Lang 3.0.
    5826      *
    5827      */
    5828     public static String reverseDelimitedString(String str, String separatorChars) {
    5829         if (str == null) {
    5830             return null;
    5831         }
    5832         // could implement manually, but simple way is to reuse other,
    5833         // probably slower, methods.
    5834         String[] strs = split(str, separatorChars);
    5835         ArrayUtils.reverse(strs);
    5836         if (separatorChars == null) {
    5837             return join(strs, ' ');
    5838         }
    5839         return join(strs, separatorChars);
    5840     }
    5841 
    5842     // Abbreviating
    5843     //-----------------------------------------------------------------------
    5844     /**
    5845      * <p>Abbreviates a String using ellipses. This will turn
    5846      * "Now is the time for all good men" into "Now is the time for..."</p>
    5847      *
    5848      * <p>Specifically:
    5849      * <ul>
    5850      *   <li>If <code>str</code> is less than <code>maxWidth</code> characters
    5851      *       long, return it.</li>
    5852      *   <li>Else abbreviate it to <code>(substring(str, 0, max-3) + "...")</code>.</li>
    5853      *   <li>If <code>maxWidth</code> is less than <code>4</code>, throw an
    5854      *       <code>IllegalArgumentException</code>.</li>
    5855      *   <li>In no case will it return a String of length greater than
    5856      *       <code>maxWidth</code>.</li>
    5857      * </ul>
    5858      * </p>
    5859      *
    5860      * <pre>
    5861      * StringUtils.abbreviate(null, *)      = null
    5862      * StringUtils.abbreviate("", 4)        = ""
    5863      * StringUtils.abbreviate("abcdefg", 6) = "abc..."
    5864      * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
    5865      * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
    5866      * StringUtils.abbreviate("abcdefg", 4) = "a..."
    5867      * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
    5868      * </pre>
    5869      *
    5870      * @param str  the String to check, may be null
    5871      * @param maxWidth  maximum length of result String, must be at least 4
    5872      * @return abbreviated String, <code>null</code> if null String input
    5873      * @throws IllegalArgumentException if the width is too small
    5874      * @since 2.0
    5875      */
    5876     public static String abbreviate(String str, int maxWidth) {
    5877         return abbreviate(str, 0, maxWidth);
    5878     }
    5879 
    5880     /**
    5881      * <p>Abbreviates a String using ellipses. This will turn
    5882      * "Now is the time for all good men" into "...is the time for..."</p>
    5883      *
    5884      * <p>Works like <code>abbreviate(String, int)</code>, but allows you to specify
    5885      * a "left edge" offset.  Note that this left edge is not necessarily going to
    5886      * be the leftmost character in the result, or the first character following the
    5887      * ellipses, but it will appear somewhere in the result.
    5888      *
    5889      * <p>In no case will it return a String of length greater than
    5890      * <code>maxWidth</code>.</p>
    5891      *
    5892      * <pre>
    5893      * StringUtils.abbreviate(null, *, *)                = null
    5894      * StringUtils.abbreviate("", 0, 4)                  = ""
    5895      * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
    5896      * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
    5897      * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
    5898      * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
    5899      * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
    5900      * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
    5901      * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
    5902      * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
    5903      * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
    5904      * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
    5905      * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
    5906      * </pre>
    5907      *
    5908      * @param str  the String to check, may be null
    5909      * @param offset  left edge of source String
    5910      * @param maxWidth  maximum length of result String, must be at least 4
    5911      * @return abbreviated String, <code>null</code> if null String input
    5912      * @throws IllegalArgumentException if the width is too small
    5913      * @since 2.0
    5914      */
    5915     public static String abbreviate(String str, int offset, int maxWidth) {
    5916         if (str == null) {
    5917             return null;
    5918         }
    5919         if (maxWidth < 4) {
    5920             throw new IllegalArgumentException("Minimum abbreviation width is 4");
    5921         }
    5922         if (str.length() <= maxWidth) {
    5923             return str;
    5924         }
    5925         if (offset > str.length()) {
    5926             offset = str.length();
    5927         }
    5928         if ((str.length() - offset) < (maxWidth - 3)) {
    5929             offset = str.length() - (maxWidth - 3);
    5930         }
    5931         if (offset <= 4) {
    5932             return str.substring(0, maxWidth - 3) + "...";
    5933         }
    5934         if (maxWidth < 7) {
    5935             throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
    5936         }
    5937         if ((offset + (maxWidth - 3)) < str.length()) {
    5938             return "..." + abbreviate(str.substring(offset), maxWidth - 3);
    5939         }
    5940         return "..." + str.substring(str.length() - (maxWidth - 3));
    5941     }
    5942     
    5943     /**
    5944      * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
    5945      * replacement String.</p>
    5946      *
    5947      * <p>This abbreviation only occurs if the following criteria is met:
    5948      * <ul>
    5949      * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
    5950      * <li>The length to truncate to is less than the length of the supplied String</li>
    5951      * <li>The length to truncate to is greater than 0</li>
    5952      * <li>The abbreviated String will have enough room for the length supplied replacement String
    5953      * and the first and last characters of the supplied String for abbreviation</li>
    5954      * </ul>
    5955      * Otherwise, the returned String will be the same as the supplied String for abbreviation.
    5956      * </p>
    5957      *
    5958      * <pre>
    5959      * StringUtils.abbreviateMiddle(null, null, 0)      = null
    5960      * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
    5961      * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
    5962      * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
    5963      * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
    5964      * </pre>
    5965      *
    5966      * @param str  the String to abbreviate, may be null
    5967      * @param middle the String to replace the middle characters with, may be null
    5968      * @param length the length to abbreviate <code>str</code> to.
    5969      * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
    5970      * @since 2.5
    5971      */
    5972     public static String abbreviateMiddle(String str, String middle, int length) {
    5973         if (isEmpty(str) || isEmpty(middle)) {
    5974             return str;
    5975         }
    5976       
    5977         if (length >= str.length() || length < (middle.length()+2)) {
    5978             return str;
    5979         }
    5980 
    5981         int targetSting = length-middle.length();
    5982         int startOffset = targetSting/2+targetSting%2;
    5983         int endOffset = str.length()-targetSting/2;
    5984         
    5985         StrBuilder builder = new StrBuilder(length);
    5986         builder.append(str.substring(0,startOffset));
    5987         builder.append(middle);
    5988         builder.append(str.substring(endOffset));
    5989         
    5990         return builder.toString();
    5991     }
    5992 
    5993     // Difference
    5994     //-----------------------------------------------------------------------
    5995     /**
    5996      * <p>Compares two Strings, and returns the portion where they differ.
    5997      * (More precisely, return the remainder of the second String,
    5998      * starting from where it's different from the first.)</p>
    5999      *
    6000      * <p>For example,
    6001      * <code>difference("i am a machine", "i am a robot") -> "robot"</code>.</p>
    6002      *
    6003      * <pre>
    6004      * StringUtils.difference(null, null) = null
    6005      * StringUtils.difference("", "") = ""
    6006      * StringUtils.difference("", "abc") = "abc"
    6007      * StringUtils.difference("abc", "") = ""
    6008      * StringUtils.difference("abc", "abc") = ""
    6009      * StringUtils.difference("ab", "abxyz") = "xyz"
    6010      * StringUtils.difference("abcde", "abxyz") = "xyz"
    6011      * StringUtils.difference("abcde", "xyz") = "xyz"
    6012      * </pre>
    6013      *
    6014      * @param str1  the first String, may be null
    6015      * @param str2  the second String, may be null
    6016      * @return the portion of str2 where it differs from str1; returns the
    6017      * empty String if they are equal
    6018      * @since 2.0
    6019      */
    6020     public static String difference(String str1, String str2) {
    6021         if (str1 == null) {
    6022             return str2;
    6023         }
    6024         if (str2 == null) {
    6025             return str1;
    6026         }
    6027         int at = indexOfDifference(str1, str2);
    6028         if (at == INDEX_NOT_FOUND) {
    6029             return EMPTY;
    6030         }
    6031         return str2.substring(at);
    6032     }
    6033 
    6034     /**
    6035      * <p>Compares two Strings, and returns the index at which the
    6036      * Strings begin to differ.</p>
    6037      *
    6038      * <p>For example,
    6039      * <code>indexOfDifference("i am a machine", "i am a robot") -> 7</code></p>
    6040      *
    6041      * <pre>
    6042      * StringUtils.indexOfDifference(null, null) = -1
    6043      * StringUtils.indexOfDifference("", "") = -1
    6044      * StringUtils.indexOfDifference("", "abc") = 0
    6045      * StringUtils.indexOfDifference("abc", "") = 0
    6046      * StringUtils.indexOfDifference("abc", "abc") = -1
    6047      * StringUtils.indexOfDifference("ab", "abxyz") = 2
    6048      * StringUtils.indexOfDifference("abcde", "abxyz") = 2
    6049      * StringUtils.indexOfDifference("abcde", "xyz") = 0
    6050      * </pre>
    6051      *
    6052      * @param str1  the first String, may be null
    6053      * @param str2  the second String, may be null
    6054      * @return the index where str2 and str1 begin to differ; -1 if they are equal
    6055      * @since 2.0
    6056      */
    6057     public static int indexOfDifference(String str1, String str2) {
    6058         if (str1 == str2) {
    6059             return INDEX_NOT_FOUND;
    6060         }
    6061         if (str1 == null || str2 == null) {
    6062             return 0;
    6063         }
    6064         int i;
    6065         for (i = 0; i < str1.length() && i < str2.length(); ++i) {
    6066             if (str1.charAt(i) != str2.charAt(i)) {
    6067                 break;
    6068             }
    6069         }
    6070         if (i < str2.length() || i < str1.length()) {
    6071             return i;
    6072         }
    6073         return INDEX_NOT_FOUND;
    6074     }
    6075 
    6076     /**
    6077      * <p>Compares all Strings in an array and returns the index at which the
    6078      * Strings begin to differ.</p>
    6079      *
    6080      * <p>For example,
    6081      * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7</code></p>
    6082      *
    6083      * <pre>
    6084      * StringUtils.indexOfDifference(null) = -1
    6085      * StringUtils.indexOfDifference(new String[] {}) = -1
    6086      * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
    6087      * StringUtils.indexOfDifference(new String[] {null, null}) = -1
    6088      * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
    6089      * StringUtils.indexOfDifference(new String[] {"", null}) = 0
    6090      * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
    6091      * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
    6092      * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
    6093      * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
    6094      * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
    6095      * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
    6096      * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
    6097      * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
    6098      * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
    6099      * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
    6100      * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
    6101      * </pre>
    6102      *
    6103      * @param strs  array of strings, entries may be null
    6104      * @return the index where the strings begin to differ; -1 if they are all equal
    6105      * @since 2.4
    6106      */
    6107     public static int indexOfDifference(String[] strs) {
    6108         if (strs == null || strs.length <= 1) {
    6109             return INDEX_NOT_FOUND;
    6110         }
    6111         boolean anyStringNull = false;
    6112         boolean allStringsNull = true;
    6113         int arrayLen = strs.length;
    6114         int shortestStrLen = Integer.MAX_VALUE;
    6115         int longestStrLen = 0;
    6116 
    6117         // find the min and max string lengths; this avoids checking to make
    6118         // sure we are not exceeding the length of the string each time through
    6119         // the bottom loop.
    6120         for (int i = 0; i < arrayLen; i++) {
    6121             if (strs[i] == null) {
    6122                 anyStringNull = true;
    6123                 shortestStrLen = 0;
    6124             } else {
    6125                 allStringsNull = false;
    6126                 shortestStrLen = Math.min(strs[i].length(), shortestStrLen);
    6127                 longestStrLen = Math.max(strs[i].length(), longestStrLen);
    6128             }
    6129         }
    6130 
    6131         // handle lists containing all nulls or all empty strings
    6132         if (allStringsNull || (longestStrLen == 0 && !anyStringNull)) {
    6133             return INDEX_NOT_FOUND;
    6134         }
    6135 
    6136         // handle lists containing some nulls or some empty strings
    6137         if (shortestStrLen == 0) {
    6138             return 0;
    6139         }
    6140 
    6141         // find the position with the first difference across all strings
    6142         int firstDiff = -1;
    6143         for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
    6144             char comparisonChar = strs[0].charAt(stringPos);
    6145             for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
    6146                 if (strs[arrayPos].charAt(stringPos) != comparisonChar) {
    6147                     firstDiff = stringPos;
    6148                     break;
    6149                 }
    6150             }
    6151             if (firstDiff != -1) {
    6152                 break;
    6153             }
    6154         }
    6155 
    6156         if (firstDiff == -1 && shortestStrLen != longestStrLen) {
    6157             // we compared all of the characters up to the length of the
    6158             // shortest string and didn't find a match, but the string lengths
    6159             // vary, so return the length of the shortest string.
    6160             return shortestStrLen;
    6161         }
    6162         return firstDiff;
    6163     }
    6164     
    6165     /**
    6166      * <p>Compares all Strings in an array and returns the initial sequence of 
    6167      * characters that is common to all of them.</p>
    6168      *
    6169      * <p>For example,
    6170      * <code>getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "</code></p>
    6171      *
    6172      * <pre>
    6173      * StringUtils.getCommonPrefix(null) = ""
    6174      * StringUtils.getCommonPrefix(new String[] {}) = ""
    6175      * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
    6176      * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
    6177      * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
    6178      * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
    6179      * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
    6180      * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
    6181      * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
    6182      * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
    6183      * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
    6184      * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
    6185      * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
    6186      * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
    6187      * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
    6188      * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
    6189      * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
    6190      * </pre>
    6191      *
    6192      * @param strs  array of String objects, entries may be null
    6193      * @return the initial sequence of characters that are common to all Strings
    6194      * in the array; empty String if the array is null, the elements are all null 
    6195      * or if there is no common prefix. 
    6196      * @since 2.4
    6197      */
    6198     public static String getCommonPrefix(String[] strs) {
    6199         if (strs == null || strs.length == 0) {
    6200             return EMPTY;
    6201         }
    6202         int smallestIndexOfDiff = indexOfDifference(strs);
    6203         if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
    6204             // all strings were identical
    6205             if (strs[0] == null) {
    6206                 return EMPTY;
    6207             }
    6208             return strs[0];
    6209         } else if (smallestIndexOfDiff == 0) {
    6210             // there were no common initial characters
    6211             return EMPTY;
    6212         } else {
    6213             // we found a common initial character sequence
    6214             return strs[0].substring(0, smallestIndexOfDiff);
    6215         }
    6216     }  
    6217     
    6218     // Misc
    6219     //-----------------------------------------------------------------------
    6220     /**
    6221      * <p>Find the Levenshtein distance between two Strings.</p>
    6222      *
    6223      * <p>This is the number of changes needed to change one String into
    6224      * another, where each change is a single character modification (deletion,
    6225      * insertion or substitution).</p>
    6226      *
    6227      * <p>The previous implementation of the Levenshtein distance algorithm
    6228      * was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
    6229      *
    6230      * <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
    6231      * which can occur when my Java implementation is used with very large strings.<br>
    6232      * This implementation of the Levenshtein distance algorithm
    6233      * is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p>
    6234      *
    6235      * <pre>
    6236      * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
    6237      * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
    6238      * StringUtils.getLevenshteinDistance("","")               = 0
    6239      * StringUtils.getLevenshteinDistance("","a")              = 1
    6240      * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
    6241      * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
    6242      * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
    6243      * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
    6244      * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
    6245      * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
    6246      * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
    6247      * </pre>
    6248      *
    6249      * @param s  the first String, must not be null
    6250      * @param t  the second String, must not be null
    6251      * @return result distance
    6252      * @throws IllegalArgumentException if either String input <code>null</code>
    6253      */
    6254     public static int getLevenshteinDistance(String s, String t) {
    6255         if (s == null || t == null) {
    6256             throw new IllegalArgumentException("Strings must not be null");
    6257         }
    6258 
    6259         /*
    6260            The difference between this impl. and the previous is that, rather 
    6261            than creating and retaining a matrix of size s.length()+1 by t.length()+1, 
    6262            we maintain two single-dimensional arrays of length s.length()+1.  The first, d,
    6263            is the 'current working' distance array that maintains the newest distance cost
    6264            counts as we iterate through the characters of String s.  Each time we increment
    6265            the index of String t we are comparing, d is copied to p, the second int[].  Doing so
    6266            allows us to retain the previous cost counts as required by the algorithm (taking 
    6267            the minimum of the cost count to the left, up one, and diagonally up and to the left
    6268            of the current cost count being calculated).  (Note that the arrays aren't really 
    6269            copied anymore, just switched...this is clearly much better than cloning an array 
    6270            or doing a System.arraycopy() each time  through the outer loop.)
    6271 
    6272            Effectively, the difference between the two implementations is this one does not 
    6273            cause an out of memory condition when calculating the LD over two very large strings.
    6274          */
    6275 
    6276         int n = s.length(); // length of s
    6277         int m = t.length(); // length of t
    6278 
    6279         if (n == 0) {
    6280             return m;
    6281         } else if (m == 0) {
    6282             return n;
    6283         }
    6284 
    6285         if (n > m) {
    6286             // swap the input strings to consume less memory
    6287             String tmp = s;
    6288             s = t;
    6289             t = tmp;
    6290             n = m;
    6291             m = t.length();
    6292         }
    6293 
    6294         int p[] = new int[n+1]; //'previous' cost array, horizontally
    6295         int d[] = new int[n+1]; // cost array, horizontally
    6296         int _d[]; //placeholder to assist in swapping p and d
    6297 
    6298         // indexes into strings s and t
    6299         int i; // iterates through s
    6300         int j; // iterates through t
    6301 
    6302         char t_j; // jth character of t
    6303 
    6304         int cost; // cost
    6305 
    6306         for (i = 0; i<=n; i++) {
    6307             p[i] = i;
    6308         }
    6309 
    6310         for (j = 1; j<=m; j++) {
    6311             t_j = t.charAt(j-1);
    6312             d[0] = j;
    6313 
    6314             for (i=1; i<=n; i++) {
    6315                 cost = s.charAt(i-1)==t_j ? 0 : 1;
    6316                 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
    6317                 d[i] = Math.min(Math.min(d[i-1]+1, p[i]+1),  p[i-1]+cost);
    6318             }
    6319 
    6320             // copy current distance counts to 'previous row' distance counts
    6321             _d = p;
    6322             p = d;
    6323             d = _d;
    6324         }
    6325 
    6326         // our last action in the above loop was to switch d and p, so p now 
    6327         // actually has the most recent cost counts
    6328         return p[n];
    6329     }
    6330 
    6331     // startsWith
    6332     //-----------------------------------------------------------------------
    6333 
    6334     /**
    6335      * <p>Check if a String starts with a specified prefix.</p>
    6336      *
    6337      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6338      * references are considered to be equal. The comparison is case sensitive.</p>
    6339      *
    6340      * <pre>
    6341      * StringUtils.startsWith(null, null)      = true
    6342      * StringUtils.startsWith(null, "abc")     = false
    6343      * StringUtils.startsWith("abcdef", null)  = false
    6344      * StringUtils.startsWith("abcdef", "abc") = true
    6345      * StringUtils.startsWith("ABCDEF", "abc") = false
    6346      * </pre>
    6347      *
    6348      * @see java.lang.String#startsWith(String)
    6349      * @param str  the String to check, may be null
    6350      * @param prefix the prefix to find, may be null
    6351      * @return <code>true</code> if the String starts with the prefix, case sensitive, or
    6352      *  both <code>null</code>
    6353      * @since 2.4
    6354      */
    6355     public static boolean startsWith(String str, String prefix) {
    6356         return startsWith(str, prefix, false);
    6357     }
    6358 
    6359     /**
    6360      * <p>Case insensitive check if a String starts with a specified prefix.</p>
    6361      *
    6362      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6363      * references are considered to be equal. The comparison is case insensitive.</p>
    6364      *
    6365      * <pre>
    6366      * StringUtils.startsWithIgnoreCase(null, null)      = true
    6367      * StringUtils.startsWithIgnoreCase(null, "abc")     = false
    6368      * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
    6369      * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
    6370      * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
    6371      * </pre>
    6372      *
    6373      * @see java.lang.String#startsWith(String)
    6374      * @param str  the String to check, may be null
    6375      * @param prefix the prefix to find, may be null
    6376      * @return <code>true</code> if the String starts with the prefix, case insensitive, or
    6377      *  both <code>null</code>
    6378      * @since 2.4
    6379      */
    6380     public static boolean startsWithIgnoreCase(String str, String prefix) {
    6381         return startsWith(str, prefix, true);
    6382     }
    6383 
    6384     /**
    6385      * <p>Check if a String starts with a specified prefix (optionally case insensitive).</p>
    6386      *
    6387      * @see java.lang.String#startsWith(String)
    6388      * @param str  the String to check, may be null
    6389      * @param prefix the prefix to find, may be null
    6390      * @param ignoreCase inidicates whether the compare should ignore case
    6391      *  (case insensitive) or not.
    6392      * @return <code>true</code> if the String starts with the prefix or
    6393      *  both <code>null</code>
    6394      */
    6395     private static boolean startsWith(String str, String prefix, boolean ignoreCase) {
    6396         if (str == null || prefix == null) {
    6397             return (str == null && prefix == null);
    6398         }
    6399         if (prefix.length() > str.length()) {
    6400             return false;
    6401         }
    6402         return str.regionMatches(ignoreCase, 0, prefix, 0, prefix.length());
    6403     }
    6404     
    6405     /**
    6406      * <p>Check if a String starts with any of an array of specified strings.</p>
    6407      * 
    6408      * <pre>
    6409      * StringUtils.startsWithAny(null, null)      = false
    6410      * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
    6411      * StringUtils.startsWithAny("abcxyz", null)     = false
    6412      * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false
    6413      * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
    6414      * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    6415      * </pre>
    6416      *
    6417      * @see #startsWith(String, String)
    6418      * @param string  the String to check, may be null
    6419      * @param searchStrings the Strings to find, may be null or empty
    6420      * @return <code>true</code> if the String starts with any of the the prefixes, case insensitive, or
    6421      *  both <code>null</code>
    6422      * @since 2.5
    6423      */
    6424     public static boolean startsWithAny(String string, String[] searchStrings) {
    6425         if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
    6426             return false;
    6427         }
    6428         for (int i = 0; i < searchStrings.length; i++) {
    6429             String searchString = searchStrings[i];
    6430             if (StringUtils.startsWith(string, searchString)) {
    6431                 return true;
    6432             }
    6433         }
    6434         return false;
    6435     }
    6436 
    6437     // endsWith
    6438     //-----------------------------------------------------------------------
    6439 
    6440     /**
    6441      * <p>Check if a String ends with a specified suffix.</p>
    6442      *
    6443      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6444      * references are considered to be equal. The comparison is case sensitive.</p>
    6445      *
    6446      * <pre>
    6447      * StringUtils.endsWith(null, null)      = true
    6448      * StringUtils.endsWith(null, "def")     = false
    6449      * StringUtils.endsWith("abcdef", null)  = false
    6450      * StringUtils.endsWith("abcdef", "def") = true
    6451      * StringUtils.endsWith("ABCDEF", "def") = false
    6452      * StringUtils.endsWith("ABCDEF", "cde") = false
    6453      * </pre>
    6454      *
    6455      * @see java.lang.String#endsWith(String)
    6456      * @param str  the String to check, may be null
    6457      * @param suffix the suffix to find, may be null
    6458      * @return <code>true</code> if the String ends with the suffix, case sensitive, or
    6459      *  both <code>null</code>
    6460      * @since 2.4
    6461      */
    6462     public static boolean endsWith(String str, String suffix) {
    6463         return endsWith(str, suffix, false);
    6464     }
    6465 
    6466     /**
    6467      * <p>Case insensitive check if a String ends with a specified suffix.</p>
    6468      *
    6469      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
    6470      * references are considered to be equal. The comparison is case insensitive.</p>
    6471      *
    6472      * <pre>
    6473      * StringUtils.endsWithIgnoreCase(null, null)      = true
    6474      * StringUtils.endsWithIgnoreCase(null, "def")     = false
    6475      * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
    6476      * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
    6477      * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
    6478      * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
    6479      * </pre>
    6480      *
    6481      * @see java.lang.String#endsWith(String)
    6482      * @param str  the String to check, may be null
    6483      * @param suffix the suffix to find, may be null
    6484      * @return <code>true</code> if the String ends with the suffix, case insensitive, or
    6485      *  both <code>null</code>
    6486      * @since 2.4
    6487      */
    6488     public static boolean endsWithIgnoreCase(String str, String suffix) {
    6489         return endsWith(str, suffix, true);
    6490     }
    6491 
    6492     /**
    6493      * <p>Check if a String ends with a specified suffix (optionally case insensitive).</p>
    6494      *
    6495      * @see java.lang.String#endsWith(String)
    6496      * @param str  the String to check, may be null
    6497      * @param suffix the suffix to find, may be null
    6498      * @param ignoreCase inidicates whether the compare should ignore case
    6499      *  (case insensitive) or not.
    6500      * @return <code>true</code> if the String starts with the prefix or
    6501      *  both <code>null</code>
    6502      */
    6503     private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
    6504         if (str == null || suffix == null) {
    6505             return (str == null && suffix == null);
    6506         }
    6507         if (suffix.length() > str.length()) {
    6508             return false;
    6509         }
    6510         int strOffset = str.length() - suffix.length();
    6511         return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
    6512     }
    6513 
    6514     /**
    6515      * <p>
    6516      * Similar to <a
    6517      * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize
    6518      * -space</a>
    6519      * </p>
    6520      * <p>
    6521      * The function returns the argument string with whitespace normalized by using
    6522      * <code>{@link #trim(String)}</code> to remove leading and trailing whitespace
    6523      * and then replacing sequences of whitespace characters by a single space.
    6524      * </p>
    6525      * In XML Whitespace characters are the same as those allowed by the <a
    6526      * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
    6527      * <p>
    6528      * See Java's {@link Character#isWhitespace(char)} for which characters are considered whitespace.
    6529      * <p>
    6530      * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
    6531      * normalize. Additonally <code>{@link #trim(String)}</code> removes control characters (char &lt;= 32) from both
    6532      * ends of this String.
    6533      * </p>
    6534      *
    6535      * @see Character#isWhitespace(char)
    6536      * @see #trim(String)
    6537      * @see <ahref="http://www.w3.org/TR/xpath/#function-normalize-space">
    6538      *              http://www.w3.org/TR/xpath/#function-normalize-space</a>
    6539      * @param str the source String to normalize whitespaces from, may be null
    6540      * @return the modified string with whitespace normalized, <code>null</code> if null String input
    6541      * 
    6542      * @since 2.6
    6543      */
    6544     public static String normalizeSpace(String str) {
    6545         str = strip(str);
    6546         if(str == null || str.length() <= 2) {
    6547             return str;
    6548         }
    6549         StrBuilder b = new StrBuilder(str.length());
    6550         for (int i = 0; i < str.length(); i++) {
    6551             char c = str.charAt(i);
    6552             if (Character.isWhitespace(c)) {
    6553                 if (i > 0 && !Character.isWhitespace(str.charAt(i - 1))) {
    6554                     b.append(' ');
    6555                 }
    6556             } else {
    6557                 b.append(c);
    6558             }
    6559         }
    6560         return b.toString();
    6561     }
    6562 
    6563     /**
    6564      * <p>Check if a String ends with any of an array of specified strings.</p>
    6565      *
    6566      * <pre>
    6567      * StringUtils.endsWithAny(null, null)      = false
    6568      * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
    6569      * StringUtils.endsWithAny("abcxyz", null)     = false
    6570      * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
    6571      * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
    6572      * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    6573      * </pre>
    6574      *
    6575      * @param string  the String to check, may be null
    6576      * @param searchStrings the Strings to find, may be null or empty
    6577      * @return <code>true</code> if the String ends with any of the the prefixes, case insensitive, or
    6578      *  both <code>null</code>
    6579      * @since 2.6
    6580      */
    6581     public static boolean endsWithAny(String string, String[] searchStrings) {
    6582         if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) {
    6583             return false;
    6584         }
    6585         for (int i = 0; i < searchStrings.length; i++) {
    6586             String searchString = searchStrings[i];
    6587             if (StringUtils.endsWith(string, searchString)) {
    6588                 return true;
    6589             }
    6590         }
    6591         return false;
    6592     }
    6593 
    6594 }

    这里提供:

    commons-lang-2.6-src.zip
  • 相关阅读:
    进程与线程
    前端教程大全
    vuex的五大属性和使用方法
    vue中以this.$xx的属性详解
    VUE-element-admin项目地址
    从零开始学 Web 之 Vue.js(三)Vue实例的生命周期
    从零开始学 Web 之 Vue.js(四)Vue的Ajax请求和跨域
    vue使用promise.all异步实现多个请求完成之后在执行某些操作
    react受控组件与非受控组件
    react生命周期
  • 原文地址:https://www.cnblogs.com/hongten/p/java_commons_lang_stringutils.html
Copyright © 2020-2023  润新知