欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Java开发中的Apache Commons Lang库:StringUtils工具类详解与源代码解析

最编程 2024-08-01 20:33:37
...

在之前写了一篇关于""和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") =					

推荐阅读