    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.lang3;
    018
    019import java.io.UnsupportedEncodingException;
    020import java.nio.charset.Charset;
    021import java.text.Normalizer;
    022import java.util.ArrayList;
    023import java.util.Arrays;
    024import java.util.Iterator;
    025import java.util.List;
    026import java.util.Locale;
    027import java.util.Objects;
    028import java.util.function.Supplier;
    029import java.util.regex.Pattern;
    030
    031/**
    032 * <p>Operations on {@link java.lang.String} that are
    033 * {@code null} safe.</p>
    034 *
    035 * <ul>
    036 *  <li><b>IsEmpty/IsBlank</b>
    037 *      - checks if a String contains text</li>
    038 *  <li><b>Trim/Strip</b>
    039 *      - removes leading and trailing whitespace</li>
    040 *  <li><b>Equals/Compare</b>
    041 *      - compares two strings null-safe</li>
    042 *  <li><b>startsWith</b>
    043 *      - check if a String starts with a prefix null-safe</li>
    044 *  <li><b>endsWith</b>
    045 *      - check if a String ends with a suffix null-safe</li>
    046 *  <li><b>IndexOf/LastIndexOf/Contains</b>
    047 *      - null-safe index-of checks
    048 *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
    049 *      - index-of any of a set of Strings</li>
    050 *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
    051 *      - does String contains only/none/any of these characters</li>
    052 *  <li><b>Substring/Left/Right/Mid</b>
    053 *      - null-safe substring extractions</li>
    054 *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
    055 *      - substring extraction relative to other strings</li>
    056 *  <li><b>Split/Join</b>
    057 *      - splits a String into an array of substrings and vice versa</li>
    058 *  <li><b>Remove/Delete</b>
    059 *      - removes part of a String</li>
    060 *  <li><b>Replace/Overlay</b>
    061 *      - Searches a String and replaces one String with another</li>
    062 *  <li><b>Chomp/Chop</b>
    063 *      - removes the last part of a String</li>
    064 *  <li><b>AppendIfMissing</b>
    065 *      - appends a suffix to the end of the String if not present</li>
    066 *  <li><b>PrependIfMissing</b>
    067 *      - prepends a prefix to the start of the String if not present</li>
    068 *  <li><b>LeftPad/RightPad/Center/Repeat</b>
    069 *      - pads a String</li>
    070 *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
    071 *      - changes the case of a String</li>
    072 *  <li><b>CountMatches</b>
    073 *      - counts the number of occurrences of one String in another</li>
    074 *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
    075 *      - checks the characters in a String</li>
    076 *  <li><b>DefaultString</b>
    077 *      - protects against a null input String</li>
    078 *  <li><b>Rotate</b>
    079 *      - rotate (circular shift) a String</li>
    080 *  <li><b>Reverse/ReverseDelimited</b>
    081 *      - reverses a String</li>
    082 *  <li><b>Abbreviate</b>
    083 *      - abbreviates a string using ellipsis or another given String</li>
    084 *  <li><b>Difference</b>
    085 *      - compares Strings and reports on their differences</li>
    086 *  <li><b>LevenshteinDistance</b>
    087 *      - the number of changes needed to change one String into another</li>
    088 * </ul>
    089 *
    090 * <p>The {@code StringUtils} class defines certain words related to
    091 * String handling.</p>
    092 *
    093 * <ul>
    094 *  <li>null - {@code null}</li>
    095 *  <li>empty - a zero-length string ({@code ""})</li>
    096 *  <li>space - the space character ({@code ' '}, char 32)</li>
    097 *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
    098 *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
    099 * </ul>
    100 *
    101 * <p>{@code StringUtils} handles {@code null} input Strings quietly.
    102 * That is to say that a {@code null} input will return {@code null}.
    103 * Where a {@code boolean} or {@code int} is being returned
    104 * details vary by method.</p>
    105 *
    106 * <p>A side effect of the {@code null} handling is that a
    107 * {@code NullPointerException} should be considered a bug in
    108 * {@code StringUtils}.</p>
    109 *
    110 * <p>Methods in this class give sample code to explain their operation.
    111 * The symbol {@code *} is used to indicate any input including {@code null}.</p>
    112 *
    113 * <p>#ThreadSafe#</p>
    114 * @see java.lang.String
    115 * @since 1.0
    116 */
    117//@Immutable
    118public class StringUtils {
    119
    120    private static final int STRING_BUILDER_SIZE = 256;
    121
    122    // Performance testing notes (JDK 1.4, Jul03, scolebourne)
    123    // Whitespace:
    124    // Character.isWhitespace() is faster than WHITESPACE.indexOf()
    125    // where WHITESPACE is a string of all whitespace characters
    126    //
    127    // Character access:
    128    // String.charAt(n) versus toCharArray(), then array[n]
    129    // String.charAt(n) is about 15% worse for a 10K string
    130    // They are about equal for a length 50 string
    131    // String.charAt(n) is about 4 times better for a length 3 string
    132    // String.charAt(n) is best bet overall
    133    //
    134    // Append:
    135    // String.concat about twice as fast as StringBuffer.append
    136    // (not sure who tested this)
    137
    138    /**
    139     * A String for a space character.
    140     *
    141     * @since 3.2
    142     */
    143    public static final String SPACE = " ";
    144
    145    /**
    146     * The empty String {@code ""}.
    147     * @since 2.0
    148     */
    149    public static final String EMPTY = "";
    150
    151    /**
    152     * A String for linefeed LF ("\n").
    153     *
    154     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    155     *      for Character and String Literals</a>
    156     * @since 3.2
    157     */
    158    public static final String LF = "\n";
    159
    160    /**
    161     * A String for carriage return CR ("\r").
    162     *
    163     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    164     *      for Character and String Literals</a>
    165     * @since 3.2
    166     */
    167    public static final String CR = "\r";
    168
    169    /**
    170     * Represents a failed index search.
    171     * @since 2.1
    172     */
    173    public static final int INDEX_NOT_FOUND = -1;
    174
    175    /**
    176     * <p>The maximum size to which the padding constant(s) can expand.</p>
    177     */
    178    private static final int PAD_LIMIT = 8192;
    179
    180    // Abbreviating
    181    //-----------------------------------------------------------------------
    182    /**
    183     * <p>Abbreviates a String using ellipses. This will turn
    184     * "Now is the time for all good men" into "Now is the time for..."</p>
    185     *
    186     * <p>Specifically:</p>
    187     * <ul>
    188     *   <li>If the number of characters in {@code str} is less than or equal to
    189     *       {@code maxWidth}, return {@code str}.</li>
    190     *   <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li>
    191     *   <li>If {@code maxWidth} is less than {@code 4}, throw an
    192     *       {@code IllegalArgumentException}.</li>
    193     *   <li>In no case will it return a String of length greater than
    194     *       {@code maxWidth}.</li>
    195     * </ul>
    196     *
    197     * <pre>
    198     * StringUtils.abbreviate(null, *)      = null
    199     * StringUtils.abbreviate("", 4)        = ""
    200     * StringUtils.abbreviate("abcdefg", 6) = "abc..."
    201     * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
    202     * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
    203     * StringUtils.abbreviate("abcdefg", 4) = "a..."
    204     * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
    205     * </pre>
    206     *
    207     * @param str  the String to check, may be null
    208     * @param maxWidth  maximum length of result String, must be at least 4
    209     * @return abbreviated String, {@code null} if null String input
    210     * @throws IllegalArgumentException if the width is too small
    211     * @since 2.0
    212     */
    213    public static String abbreviate(final String str, final int maxWidth) {
    214        return abbreviate(str, "...", 0, maxWidth);
    215    }
    216
    217    /**
    218     * <p>Abbreviates a String using ellipses. This will turn
    219     * "Now is the time for all good men" into "...is the time for..."</p>
    220     *
    221     * <p>Works like {@code abbreviate(String, int)}, but allows you to specify
    222     * a "left edge" offset.  Note that this left edge is not necessarily going to
    223     * be the leftmost character in the result, or the first character following the
    224     * ellipses, but it will appear somewhere in the result.
    225     *
    226     * <p>In no case will it return a String of length greater than
    227     * {@code maxWidth}.</p>
    228     *
    229     * <pre>
    230     * StringUtils.abbreviate(null, *, *)                = null
    231     * StringUtils.abbreviate("", 0, 4)                  = ""
    232     * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
    233     * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
    234     * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
    235     * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
    236     * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
    237     * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
    238     * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
    239     * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
    240     * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
    241     * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
    242     * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
    243     * </pre>
    244     *
    245     * @param str  the String to check, may be null
    246     * @param offset  left edge of source String
    247     * @param maxWidth  maximum length of result String, must be at least 4
    248     * @return abbreviated String, {@code null} if null String input
    249     * @throws IllegalArgumentException if the width is too small
    250     * @since 2.0
    251     */
    252    public static String abbreviate(final String str, final int offset, final int maxWidth) {
    253        return abbreviate(str, "...", offset, maxWidth);
    254    }
    255
    256    /**
    257     * <p>Abbreviates a String using another given String as replacement marker. This will turn
    258     * "Now is the time for all good men" into "Now is the time for..." if "..." was defined
    259     * as the replacement marker.</p>
    260     *
    261     * <p>Specifically:</p>
    262     * <ul>
    263     *   <li>If the number of characters in {@code str} is less than or equal to
    264     *       {@code maxWidth}, return {@code str}.</li>
    265     *   <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li>
    266     *   <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an
    267     *       {@code IllegalArgumentException}.</li>
    268     *   <li>In no case will it return a String of length greater than
    269     *       {@code maxWidth}.</li>
    270     * </ul>
    271     *
    272     * <pre>
    273     * StringUtils.abbreviate(null, "...", *)      = null
    274     * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"
    275     * StringUtils.abbreviate("", "...", 4)        = ""
    276     * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."
    277     * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"
    278     * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"
    279     * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."
    280     * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."
    281     * StringUtils.abbreviate("abcdefg", "..", 2)  = IllegalArgumentException
    282     * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException
    283     * </pre>
    284     *
    285     * @param str  the String to check, may be null
    286     * @param abbrevMarker  the String used as replacement marker
    287     * @param maxWidth  maximum length of result String, must be at least {@code abbrevMarker.length + 1}
    288     * @return abbreviated String, {@code null} if null String input
    289     * @throws IllegalArgumentException if the width is too small
    290     * @since 3.6
    291     */
    292    public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
    293        return abbreviate(str, abbrevMarker, 0, maxWidth);
    294    }
    295    /**
    296     * <p>Abbreviates a String using a given replacement marker. This will turn
    297     * "Now is the time for all good men" into "...is the time for..." if "..." was defined
    298     * as the replacement marker.</p>
    299     *
    300     * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify
    301     * a "left edge" offset.  Note that this left edge is not necessarily going to
    302     * be the leftmost character in the result, or the first character following the
    303     * replacement marker, but it will appear somewhere in the result.
    304     *
    305     * <p>In no case will it return a String of length greater than {@code maxWidth}.</p>
    306     *
    307     * <pre>
    308     * StringUtils.abbreviate(null, null, *, *)                 = null
    309     * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"
    310     * StringUtils.abbreviate("", "...", 0, 4)                  = ""
    311     * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
    312     * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10)    = "abcdefghi,"
    313     * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10)    = "abcdefghi,"
    314     * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10)    = "abcdefghi,"
    315     * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10)   = "::efghij::"
    316     * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10)  = "...ghij..."
    317     * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10)    = "*ghijklmno"
    318     * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10)   = "'ghijklmno"
    319     * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10)   = "!ghijklmno"
    320     * StringUtils.abbreviate("abcdefghij", "abra", 0, 4)       = IllegalArgumentException
    321     * StringUtils.abbreviate("abcdefghij", "...", 5, 6)        = IllegalArgumentException
    322     * </pre>
    323     *
    324     * @param str  the String to check, may be null
    325     * @param abbrevMarker  the String used as replacement marker
    326     * @param offset  left edge of source String
    327     * @param maxWidth  maximum length of result String, must be at least 4
    328     * @return abbreviated String, {@code null} if null String input
    329     * @throws IllegalArgumentException if the width is too small
    330     * @since 3.6
    331     */
    332    public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) {
    333        if (isEmpty(str) && isEmpty(abbrevMarker)) {
    334            return str;
    335        } else if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) {
    336            return str.substring(0, maxWidth);
    337        } else if (isEmpty(str) || isEmpty(abbrevMarker)) {
    338            return str;
    339        }
    340        final int abbrevMarkerLength = abbrevMarker.length();
    341        final int minAbbrevWidth = abbrevMarkerLength + 1;
    342        final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;
    343
    344        if (maxWidth < minAbbrevWidth) {
    345            throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
    346        }
    347        if (str.length() <= maxWidth) {
    348            return str;
    349        }
    350        if (offset > str.length()) {
    351            offset = str.length();
    352        }
    353        if (str.length() - offset < maxWidth - abbrevMarkerLength) {
    354            offset = str.length() - (maxWidth - abbrevMarkerLength);
    355        }
    356        if (offset <= abbrevMarkerLength+1) {
    357            return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
    358        }
    359        if (maxWidth < minAbbrevWidthOffset) {
    360            throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
    361        }
    362        if (offset + maxWidth - abbrevMarkerLength < str.length()) {
    363            return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
    364        }
    365        return abbrevMarker + str.substring(str.length() - (maxWidth - abbrevMarkerLength));
    366    }
    367
    368    /**
    369     * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
    370     * replacement String.</p>
    371     *
    372     * <p>This abbreviation only occurs if the following criteria is met:</p>
    373     * <ul>
    374     * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
    375     * <li>The length to truncate to is less than the length of the supplied String</li>
    376     * <li>The length to truncate to is greater than 0</li>
    377     * <li>The abbreviated String will have enough room for the length supplied replacement String
    378     * and the first and last characters of the supplied String for abbreviation</li>
    379     * </ul>
    380     * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation.
    381     * </p>
    382     *
    383     * <pre>
    384     * StringUtils.abbreviateMiddle(null, null, 0)      = null
    385     * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
    386     * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
    387     * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
    388     * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
    389     * </pre>
    390     *
    391     * @param str  the String to abbreviate, may be null
    392     * @param middle the String to replace the middle characters with, may be null
    393     * @param length the length to abbreviate {@code str} to.
    394     * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
    395     * @since 2.5
    396     */
    397    public static String abbreviateMiddle(final String str, final String middle, final int length) {
    398        if (isEmpty(str) || isEmpty(middle)) {
    399            return str;
    400        }
    401
    402        if (length >= str.length() || length < middle.length()+2) {
    403            return str;
    404        }
    405
    406        final int targetSting = length-middle.length();
    407        final int startOffset = targetSting/2+targetSting%2;
    408        final int endOffset = str.length()-targetSting/2;
    409
    410        return str.substring(0, startOffset) +
    411            middle +
    412            str.substring(endOffset);
    413    }
    414
    415    /**
    416     * Appends the suffix to the end of the string if the string does not
    417     * already end with the suffix.
    418     *
    419     * @param str The string.
    420     * @param suffix The suffix to append to the end of the string.
    421     * @param ignoreCase Indicates whether the compare should ignore case.
    422     * @param suffixes Additional suffixes that are valid terminators (optional).
    423     *
    424     * @return A new String if suffix was appended, the same string otherwise.
    425     */
    426    private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
    427        if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) {
    428            return str;
    429        }
    430        if (ArrayUtils.isNotEmpty(suffixes)) {
    431            for (final CharSequence s : suffixes) {
    432                if (endsWith(str, s, ignoreCase)) {
    433                    return str;
    434                }
    435            }
    436        }
    437        return str + suffix.toString();
    438    }
    439
    440    /**
    441     * Appends the suffix to the end of the string if the string does not
    442     * already end with any of the suffixes.
    443     *
    444     * <pre>
    445     * StringUtils.appendIfMissing(null, null) = null
    446     * StringUtils.appendIfMissing("abc", null) = "abc"
    447     * StringUtils.appendIfMissing("", "xyz") = "xyz"
    448     * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz"
    449     * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
    450     * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
    451     * </pre>
    452     * <p>With additional suffixes,</p>
    453     * <pre>
    454     * StringUtils.appendIfMissing(null, null, null) = null
    455     * StringUtils.appendIfMissing("abc", null, null) = "abc"
    456     * StringUtils.appendIfMissing("", "xyz", null) = "xyz"
    457     * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
    458     * StringUtils.appendIfMissing("abc", "xyz", "") = "abc"
    459     * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz"
    460     * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
    461     * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
    462     * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
    463     * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
    464     * </pre>
    465     *
    466     * @param str The string.
    467     * @param suffix The suffix to append to the end of the string.
    468     * @param suffixes Additional suffixes that are valid terminators.
    469     *
    470     * @return A new String if suffix was appended, the same string otherwise.
    471     *
    472     * @since 3.2
    473     */
    474    public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
    475        return appendIfMissing(str, suffix, false, suffixes);
    476    }
    477
    478    /**
    479     * Appends the suffix to the end of the string if the string does not
    480     * already end, case insensitive, with any of the suffixes.
    481     *
    482     * <pre>
    483     * StringUtils.appendIfMissingIgnoreCase(null, null) = null
    484     * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc"
    485     * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz"
    486     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz"
    487     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
    488     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
    489     * </pre>
    490     * <p>With additional suffixes,</p>
    491     * <pre>
    492     * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null
    493     * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc"
    494     * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz"
    495     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
    496     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc"
    497     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "axyz"
    498     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
    499     * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
    500     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
    501     * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
    502     * </pre>
    503     *
    504     * @param str The string.
    505     * @param suffix The suffix to append to the end of the string.
    506     * @param suffixes Additional suffixes that are valid terminators.
    507     *
    508     * @return A new String if suffix was appended, the same string otherwise.
    509     *
    510     * @since 3.2
    511     */
    512    public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
    513        return appendIfMissing(str, suffix, true, suffixes);
    514    }
    515
    516    /**
    517     * <p>Capitalizes a String changing the first character to title case as
    518     * per {@link Character#toTitleCase(int)}. No other characters are changed.</p>
    519     *
    520     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}.
    521     * A {@code null} input String returns {@code null}.</p>
    522     *
    523     * <pre>
    524     * StringUtils.capitalize(null)  = null
    525     * StringUtils.capitalize("")    = ""
    526     * StringUtils.capitalize("cat") = "Cat"
    527     * StringUtils.capitalize("cAt") = "CAt"
    528     * StringUtils.capitalize("'cat'") = "'cat'"
    529     * </pre>
    530     *
    531     * @param str the String to capitalize, may be null
    532     * @return the capitalized String, {@code null} if null String input
    533     * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)
    534     * @see #uncapitalize(String)
    535     * @since 2.0
    536     */
    537    public static String capitalize(final String str) {
    538        final int strLen = length(str);
    539        if (strLen == 0) {
    540            return str;
    541        }
    542
    543        final int firstCodepoint = str.codePointAt(0);
    544        final int newCodePoint = Character.toTitleCase(firstCodepoint);
    545        if (firstCodepoint == newCodePoint) {
    546            // already capitalized
    547            return str;
    548        }
    549
    550        final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
    551        int outOffset = 0;
    552        newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
    553        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
    554            final int codepoint = str.codePointAt(inOffset);
    555            newCodePoints[outOffset++] = codepoint; // copy the remaining ones
    556            inOffset += Character.charCount(codepoint);
    557         }
    558        return new String(newCodePoints, 0, outOffset);
    559    }
    560
    561    // Centering
    562    //-----------------------------------------------------------------------
    563    /**
    564     * <p>Centers a String in a larger String of size {@code size}
    565     * using the space character (' ').</p>
    566     *
    567     * <p>If the size is less than the String length, the String is returned.
    568     * A {@code null} String returns {@code null}.
    569     * A negative size is treated as zero.</p>
    570     *
    571     * <p>Equivalent to {@code center(str, size, " ")}.</p>
    572     *
    573     * <pre>
    574     * StringUtils.center(null, *)   = null
    575     * StringUtils.center("", 4)     = "    "
    576     * StringUtils.center("ab", -1)  = "ab"
    577     * StringUtils.center("ab", 4)   = " ab "
    578     * StringUtils.center("abcd", 2) = "abcd"
    579     * StringUtils.center("a", 4)    = " a  "
    580     * </pre>
    581     *
    582     * @param str  the String to center, may be null
    583     * @param size  the int size of new String, negative treated as zero
    584     * @return centered String, {@code null} if null String input
    585     */
    586    public static String center(final String str, final int size) {
    587        return center(str, size, ' ');
    588    }
    589
    590    /**
    591     * <p>Centers a String in a larger String of size {@code size}.
    592     * Uses a supplied character as the value to pad the String with.</p>
    593     *
    594     * <p>If the size is less than the String length, the String is returned.
    595     * A {@code null} String returns {@code null}.
    596     * A negative size is treated as zero.</p>
    597     *
    598     * <pre>
    599     * StringUtils.center(null, *, *)     = null
    600     * StringUtils.center("", 4, ' ')     = "    "
    601     * StringUtils.center("ab", -1, ' ')  = "ab"
    602     * StringUtils.center("ab", 4, ' ')   = " ab "
    603     * StringUtils.center("abcd", 2, ' ') = "abcd"
    604     * StringUtils.center("a", 4, ' ')    = " a  "
    605     * StringUtils.center("a", 4, 'y')    = "yayy"
    606     * </pre>
    607     *
    608     * @param str  the String to center, may be null
    609     * @param size  the int size of new String, negative treated as zero
    610     * @param padChar  the character to pad the new String with
    611     * @return centered String, {@code null} if null String input
    612     * @since 2.0
    613     */
    614    public static String center(String str, final int size, final char padChar) {
    615        if (str == null || size <= 0) {
    616            return str;
    617        }
    618        final int strLen = str.length();
    619        final int pads = size - strLen;
    620        if (pads <= 0) {
    621            return str;
    622        }
    623        str = leftPad(str, strLen + pads / 2, padChar);
    624        str = rightPad(str, size, padChar);
    625        return str;
    626    }
    627
    628    /**
    629     * <p>Centers a String in a larger String of size {@code size}.
    630     * Uses a supplied String as the value to pad the String with.</p>
    631     *
    632     * <p>If the size is less than the String length, the String is returned.
    633     * A {@code null} String returns {@code null}.
    634     * A negative size is treated as zero.</p>
    635     *
    636     * <pre>
    637     * StringUtils.center(null, *, *)     = null
    638     * StringUtils.center("", 4, " ")     = "    "
    639     * StringUtils.center("ab", -1, " ")  = "ab"
    640     * StringUtils.center("ab", 4, " ")   = " ab "
    641     * StringUtils.center("abcd", 2, " ") = "abcd"
    642     * StringUtils.center("a", 4, " ")    = " a  "
    643     * StringUtils.center("a", 4, "yz")   = "yayz"
    644     * StringUtils.center("abc", 7, null) = "  abc  "
    645     * StringUtils.center("abc", 7, "")   = "  abc  "
    646     * </pre>
    647     *
    648     * @param str  the String to center, may be null
    649     * @param size  the int size of new String, negative treated as zero
    650     * @param padStr  the String to pad the new String with, must not be null or empty
    651     * @return centered String, {@code null} if null String input
    652     * @throws IllegalArgumentException if padStr is {@code null} or empty
    653     */
    654    public static String center(String str, final int size, String padStr) {
    655        if (str == null || size <= 0) {
    656            return str;
    657        }
    658        if (isEmpty(padStr)) {
    659            padStr = SPACE;
    660        }
    661        final int strLen = str.length();
    662        final int pads = size - strLen;
    663        if (pads <= 0) {
    664            return str;
    665        }
    666        str = leftPad(str, strLen + pads / 2, padStr);
    667        str = rightPad(str, size, padStr);
    668        return str;
    669    }
    670
    671    // Chomping
    672    //-----------------------------------------------------------------------
    673    /**
    674     * <p>Removes one newline from end of a String if it's there,
    675     * otherwise leave it alone.  A newline is &quot;{@code \n}&quot;,
    676     * &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.</p>
    677     *
    678     * <p>NOTE: This method changed in 2.0.
    679     * It now more closely matches Perl chomp.</p>
    680     *
    681     * <pre>
    682     * StringUtils.chomp(null)          = null
    683     * StringUtils.chomp("")            = ""
    684     * StringUtils.chomp("abc \r")      = "abc "
    685     * StringUtils.chomp("abc\n")       = "abc"
    686     * StringUtils.chomp("abc\r\n")     = "abc"
    687     * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
    688     * StringUtils.chomp("abc\n\r")     = "abc\n"
    689     * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
    690     * StringUtils.chomp("\r")          = ""
    691     * StringUtils.chomp("\n")          = ""
    692     * StringUtils.chomp("\r\n")        = ""
    693     * </pre>
    694     *
    695     * @param str  the String to chomp a newline from, may be null
    696     * @return String without newline, {@code null} if null String input
    697     */
    698    public static String chomp(final String str) {
    699        if (isEmpty(str)) {
    700            return str;
    701        }
    702
    703        if (str.length() == 1) {
    704            final char ch = str.charAt(0);
    705            if (ch == CharUtils.CR || ch == CharUtils.LF) {
    706                return EMPTY;
    707            }
    708            return str;
    709        }
    710
    711        int lastIdx = str.length() - 1;
    712        final char last = str.charAt(lastIdx);
    713
    714        if (last == CharUtils.LF) {
    715            if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    716                lastIdx--;
    717            }
    718        } else if (last != CharUtils.CR) {
    719            lastIdx++;
    720        }
    721        return str.substring(0, lastIdx);
    722    }
    723
    724    /**
    725     * <p>Removes {@code separator} from the end of
    726     * {@code str} if it's there, otherwise leave it alone.</p>
    727     *
    728     * <p>NOTE: This method changed in version 2.0.
    729     * It now more closely matches Perl chomp.
    730     * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
    731     * This method uses {@link String#endsWith(String)}.</p>
    732     *
    733     * <pre>
    734     * StringUtils.chomp(null, *)         = null
    735     * StringUtils.chomp("", *)           = ""
    736     * StringUtils.chomp("foobar", "bar") = "foo"
    737     * StringUtils.chomp("foobar", "baz") = "foobar"
    738     * StringUtils.chomp("foo", "foo")    = ""
    739     * StringUtils.chomp("foo ", "foo")   = "foo "
    740     * StringUtils.chomp(" foo", "foo")   = " "
    741     * StringUtils.chomp("foo", "foooo")  = "foo"
    742     * StringUtils.chomp("foo", "")       = "foo"
    743     * StringUtils.chomp("foo", null)     = "foo"
    744     * </pre>
    745     *
    746     * @param str  the String to chomp from, may be null
    747     * @param separator  separator String, may be null
    748     * @return String without trailing separator, {@code null} if null String input
    749     * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead
    750     */
    751    @Deprecated
    752    public static String chomp(final String str, final String separator) {
    753        return removeEnd(str, separator);
    754    }
    755
    756    // Chopping
    757    //-----------------------------------------------------------------------
    758    /**
    759     * <p>Remove the last character from a String.</p>
    760     *
    761     * <p>If the String ends in {@code \r\n}, then remove both
    762     * of them.</p>
    763     *
    764     * <pre>
    765     * StringUtils.chop(null)          = null
    766     * StringUtils.chop("")            = ""
    767     * StringUtils.chop("abc \r")      = "abc "
    768     * StringUtils.chop("abc\n")       = "abc"
    769     * StringUtils.chop("abc\r\n")     = "abc"
    770     * StringUtils.chop("abc")         = "ab"
    771     * StringUtils.chop("abc\nabc")    = "abc\nab"
    772     * StringUtils.chop("a")           = ""
    773     * StringUtils.chop("\r")          = ""
    774     * StringUtils.chop("\n")          = ""
    775     * StringUtils.chop("\r\n")        = ""
    776     * </pre>
    777     *
    778     * @param str  the String to chop last character from, may be null
    779     * @return String without last character, {@code null} if null String input
    780     */
    781    public static String chop(final String str) {
    782        if (str == null) {
    783            return null;
    784        }
    785        final int strLen = str.length();
    786        if (strLen < 2) {
    787            return EMPTY;
    788        }
    789        final int lastIdx = strLen - 1;
    790        final String ret = str.substring(0, lastIdx);
    791        final char last = str.charAt(lastIdx);
    792        if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
    793            return ret.substring(0, lastIdx - 1);
    794        }
    795        return ret;
    796    }
    797
    798    // Compare
    799    //-----------------------------------------------------------------------
    800    /**
    801     * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p>
    802     * <ul>
    803     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    804     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    805     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    806     * </ul>
    807     *
    808     * <p>This is a {@code null} safe version of :</p>
    809     * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
    810     *
    811     * <p>{@code null} value is considered less than non-{@code null} value.
    812     * Two {@code null} references are considered equal.</p>
    813     *
    814     * <pre>
    815     * StringUtils.compare(null, null)   = 0
    816     * StringUtils.compare(null , "a")   &lt; 0
    817     * StringUtils.compare("a", null)    &gt; 0
    818     * StringUtils.compare("abc", "abc") = 0
    819     * StringUtils.compare("a", "b")     &lt; 0
    820     * StringUtils.compare("b", "a")     &gt; 0
    821     * StringUtils.compare("a", "B")     &gt; 0
    822     * StringUtils.compare("ab", "abc")  &lt; 0
    823     * </pre>
    824     *
    825     * @see #compare(String, String, boolean)
    826     * @see String#compareTo(String)
    827     * @param str1  the String to compare from
    828     * @param str2  the String to compare to
    829     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal or greater than {@code str2}
    830     * @since 3.5
    831     */
    832    public static int compare(final String str1, final String str2) {
    833        return compare(str1, str2, true);
    834    }
    835
    836    /**
    837     * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p>
    838     * <ul>
    839     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    840     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    841     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    842     * </ul>
    843     *
    844     * <p>This is a {@code null} safe version of :</p>
    845     * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
    846     *
    847     * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
    848     * Two {@code null} references are considered equal.</p>
    849     *
    850     * <pre>
    851     * StringUtils.compare(null, null, *)     = 0
    852     * StringUtils.compare(null , "a", true)  &lt; 0
    853     * StringUtils.compare(null , "a", false) &gt; 0
    854     * StringUtils.compare("a", null, true)   &gt; 0
    855     * StringUtils.compare("a", null, false)  &lt; 0
    856     * StringUtils.compare("abc", "abc", *)   = 0
    857     * StringUtils.compare("a", "b", *)       &lt; 0
    858     * StringUtils.compare("b", "a", *)       &gt; 0
    859     * StringUtils.compare("a", "B", *)       &gt; 0
    860     * StringUtils.compare("ab", "abc", *)    &lt; 0
    861     * </pre>
    862     *
    863     * @see String#compareTo(String)
    864     * @param str1  the String to compare from
    865     * @param str2  the String to compare to
    866     * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
    867     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
    868     * @since 3.5
    869     */
    870    public static int compare(final String str1, final String str2, final boolean nullIsLess) {
    871        if (str1 == str2) {
    872            return 0;
    873        }
    874        if (str1 == null) {
    875            return nullIsLess ? -1 : 1;
    876        }
    877        if (str2 == null) {
    878            return nullIsLess ? 1 : - 1;
    879        }
    880        return str1.compareTo(str2);
    881    }
    882
    883    /**
    884     * <p>Compare two Strings lexicographically, ignoring case differences,
    885     * as per {@link String#compareToIgnoreCase(String)}, returning :</p>
    886     * <ul>
    887     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    888     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    889     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    890     * </ul>
    891     *
    892     * <p>This is a {@code null} safe version of :</p>
    893     * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
    894     *
    895     * <p>{@code null} value is considered less than non-{@code null} value.
    896     * Two {@code null} references are considered equal.
    897     * Comparison is case insensitive.</p>
    898     *
    899     * <pre>
    900     * StringUtils.compareIgnoreCase(null, null)   = 0
    901     * StringUtils.compareIgnoreCase(null , "a")   &lt; 0
    902     * StringUtils.compareIgnoreCase("a", null)    &gt; 0
    903     * StringUtils.compareIgnoreCase("abc", "abc") = 0
    904     * StringUtils.compareIgnoreCase("abc", "ABC") = 0
    905     * StringUtils.compareIgnoreCase("a", "b")     &lt; 0
    906     * StringUtils.compareIgnoreCase("b", "a")     &gt; 0
    907     * StringUtils.compareIgnoreCase("a", "B")     &lt; 0
    908     * StringUtils.compareIgnoreCase("A", "b")     &lt; 0
    909     * StringUtils.compareIgnoreCase("ab", "ABC")  &lt; 0
    910     * </pre>
    911     *
    912     * @see #compareIgnoreCase(String, String, boolean)
    913     * @see String#compareToIgnoreCase(String)
    914     * @param str1  the String to compare from
    915     * @param str2  the String to compare to
    916     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
    917     *          ignoring case differences.
    918     * @since 3.5
    919     */
    920    public static int compareIgnoreCase(final String str1, final String str2) {
    921        return compareIgnoreCase(str1, str2, true);
    922    }
    923
    924    /**
    925     * <p>Compare two Strings lexicographically, ignoring case differences,
    926     * as per {@link String#compareToIgnoreCase(String)}, returning :</p>
    927     * <ul>
    928     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    929     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    930     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    931     * </ul>
    932     *
    933     * <p>This is a {@code null} safe version of :</p>
    934     * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
    935     *
    936     * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
    937     * Two {@code null} references are considered equal.
    938     * Comparison is case insensitive.</p>
    939     *
    940     * <pre>
    941     * StringUtils.compareIgnoreCase(null, null, *)     = 0
    942     * StringUtils.compareIgnoreCase(null , "a", true)  &lt; 0
    943     * StringUtils.compareIgnoreCase(null , "a", false) &gt; 0
    944     * StringUtils.compareIgnoreCase("a", null, true)   &gt; 0
    945     * StringUtils.compareIgnoreCase("a", null, false)  &lt; 0
    946     * StringUtils.compareIgnoreCase("abc", "abc", *)   = 0
    947     * StringUtils.compareIgnoreCase("abc", "ABC", *)   = 0
    948     * StringUtils.compareIgnoreCase("a", "b", *)       &lt; 0
    949     * StringUtils.compareIgnoreCase("b", "a", *)       &gt; 0
    950     * StringUtils.compareIgnoreCase("a", "B", *)       &lt; 0
    951     * StringUtils.compareIgnoreCase("A", "b", *)       &lt; 0
    952     * StringUtils.compareIgnoreCase("ab", "abc", *)    &lt; 0
    953     * </pre>
    954     *
    955     * @see String#compareToIgnoreCase(String)
    956     * @param str1  the String to compare from
    957     * @param str2  the String to compare to
    958     * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
    959     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
    960     *          ignoring case differences.
    961     * @since 3.5
    962     */
    963    public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
    964        if (str1 == str2) {
    965            return 0;
    966        }
    967        if (str1 == null) {
    968            return nullIsLess ? -1 : 1;
    969        }
    970        if (str2 == null) {
    971            return nullIsLess ? 1 : - 1;
    972        }
    973        return str1.compareToIgnoreCase(str2);
    974    }
    975
    976    /**
    977     * <p>Checks if CharSequence contains a search CharSequence, handling {@code null}.
    978     * This method uses {@link String#indexOf(String)} if possible.</p>
    979     *
    980     * <p>A {@code null} CharSequence will return {@code false}.</p>
    981     *
    982     * <pre>
    983     * StringUtils.contains(null, *)     = false
    984     * StringUtils.contains(*, null)     = false
    985     * StringUtils.contains("", "")      = true
    986     * StringUtils.contains("abc", "")   = true
    987     * StringUtils.contains("abc", "a")  = true
    988     * StringUtils.contains("abc", "z")  = false
    989     * </pre>
    990     *
    991     * @param seq  the CharSequence to check, may be null
    992     * @param searchSeq  the CharSequence to find, may be null
    993     * @return true if the CharSequence contains the search CharSequence,
    994     *  false if not or {@code null} string input
    995     * @since 2.0
    996     * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
    997     */
    998    public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
    999        if (seq == null || searchSeq == null) {
    1000            return false;
    1001        }
    1002        return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;
    1003    }
    1004
    1005    // Contains
    1006    //-----------------------------------------------------------------------
    1007    /**
    1008     * <p>Checks if CharSequence contains a search character, handling {@code null}.
    1009     * This method uses {@link String#indexOf(int)} if possible.</p>
    1010     *
    1011     * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p>
    1012     *
    1013     * <pre>
    1014     * StringUtils.contains(null, *)    = false
    1015     * StringUtils.contains("", *)      = false
    1016     * StringUtils.contains("abc", 'a') = true
    1017     * StringUtils.contains("abc", 'z') = false
    1018     * </pre>
    1019     *
    1020     * @param seq  the CharSequence to check, may be null
    1021     * @param searchChar  the character to find
    1022     * @return true if the CharSequence contains the search character,
    1023     *  false if not or {@code null} string input
    1024     * @since 2.0
    1025     * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
    1026     */
    1027    public static boolean contains(final CharSequence seq, final int searchChar) {
    1028        if (isEmpty(seq)) {
    1029            return false;
    1030        }
    1031        return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
    1032    }
    1033
    1034    // ContainsAny
    1035    //-----------------------------------------------------------------------
    1036    /**
    1037     * <p>Checks if the CharSequence contains any character in the given
    1038     * set of characters.</p>
    1039     *
    1040     * <p>A {@code null} CharSequence will return {@code false}.
    1041     * A {@code null} or zero length search array will return {@code false}.</p>
    1042     *
    1043     * <pre>
    1044     * StringUtils.containsAny(null, *)                  = false
    1045     * StringUtils.containsAny("", *)                    = false
    1046     * StringUtils.containsAny(*, null)                  = false
    1047     * StringUtils.containsAny(*, [])                    = false
    1048     * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true
    1049     * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true
    1050     * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true
    1051     * StringUtils.containsAny("aba", ['z'])             = false
    1052     * </pre>
    1053     *
    1054     * @param cs  the CharSequence to check, may be null
    1055     * @param searchChars  the chars to search for, may be null
    1056     * @return the {@code true} if any of the chars are found,
    1057     * {@code false} if no match or null input
    1058     * @since 2.4
    1059     * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
    1060     */
    1061    public static boolean containsAny(final CharSequence cs, final char... searchChars) {
    1062        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    1063            return false;
    1064        }
    1065        final int csLength = cs.length();
    1066        final int searchLength = searchChars.length;
    1067        final int csLast = csLength - 1;
    1068        final int searchLast = searchLength - 1;
    1069        for (int i = 0; i < csLength; i++) {
    1070            final char ch = cs.charAt(i);
    1071            for (int j = 0; j < searchLength; j++) {
    1072                if (searchChars[j] == ch) {
    1073                    if (Character.isHighSurrogate(ch)) {
    1074                        if (j == searchLast) {
    1075                            // missing low surrogate, fine, like String.indexOf(String)
    1076                            return true;
    1077                        }
    1078                        if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
    1079                            return true;
    1080                        }
    1081                    } else {
    1082                        // ch is in the Basic Multilingual Plane
    1083                        return true;
    1084                    }
    1085                }
    1086            }
    1087        }
    1088        return false;
    1089    }
    1090
    1091    /**
    1092     * <p>
    1093     * Checks if the CharSequence contains any character in the given set of characters.
    1094     * </p>
    1095     *
    1096     * <p>
    1097     * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
    1098     * {@code false}.
    1099     * </p>
    1100     *
    1101     * <pre>
    1102     * StringUtils.containsAny(null, *)               = false
    1103     * StringUtils.containsAny("", *)                 = false
    1104     * StringUtils.containsAny(*, null)               = false
    1105     * StringUtils.containsAny(*, "")                 = false
    1106     * StringUtils.containsAny("zzabyycdxx", "za")    = true
    1107     * StringUtils.containsAny("zzabyycdxx", "by")    = true
    1108     * StringUtils.containsAny("zzabyycdxx", "zy")    = true
    1109     * StringUtils.containsAny("zzabyycdxx", "\tx")   = true
    1110     * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
    1111     * StringUtils.containsAny("aba", "z")            = false
    1112     * </pre>
    1113     *
    1114     * @param cs
    1115     *            the CharSequence to check, may be null
    1116     * @param searchChars
    1117     *            the chars to search for, may be null
    1118     * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
    1119     * @since 2.4
    1120     * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
    1121     */
    1122    public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
    1123        if (searchChars == null) {
    1124            return false;
    1125        }
    1126        return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
    1127    }
    1128
    1129    /**
    1130     * <p>Checks if the CharSequence contains any of the CharSequences in the given array.</p>
    1131     *
    1132     * <p>
    1133     * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero
    1134     * length search array will return {@code false}.
    1135     * </p>
    1136     *
    1137     * <pre>
    1138     * StringUtils.containsAny(null, *)            = false
    1139     * StringUtils.containsAny("", *)              = false
    1140     * StringUtils.containsAny(*, null)            = false
    1141     * StringUtils.containsAny(*, [])              = false
    1142     * StringUtils.containsAny("abcd", "ab", null) = true
    1143     * StringUtils.containsAny("abcd", "ab", "cd") = true
    1144     * StringUtils.containsAny("abc", "d", "abc")  = true
    1145     * </pre>
    1146     *
    1147     *
    1148     * @param cs The CharSequence to check, may be null
    1149     * @param searchCharSequences The array of CharSequences to search for, may be null.
    1150     * Individual CharSequences may be null as well.
    1151     * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
    1152     * @since 3.4
    1153     */
    1154    public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
    1155        if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {
    1156            return false;
    1157        }
    1158        for (final CharSequence searchCharSequence : searchCharSequences) {
    1159            if (contains(cs, searchCharSequence)) {
    1160                return true;
    1161            }
    1162        }
    1163        return false;
    1164    }
    1165
    1166    /**
    1167     * <p>Checks if CharSequence contains a search CharSequence irrespective of case,
    1168     * handling {@code null}. Case-insensitivity is defined as by
    1169     * {@link String#equalsIgnoreCase(String)}.
    1170     *
    1171     * <p>A {@code null} CharSequence will return {@code false}.</p>
    1172     *
    1173     * <pre>
    1174     * StringUtils.containsIgnoreCase(null, *) = false
    1175     * StringUtils.containsIgnoreCase(*, null) = false
    1176     * StringUtils.containsIgnoreCase("", "") = true
    1177     * StringUtils.containsIgnoreCase("abc", "") = true
    1178     * StringUtils.containsIgnoreCase("abc", "a") = true
    1179     * StringUtils.containsIgnoreCase("abc", "z") = false
    1180     * StringUtils.containsIgnoreCase("abc", "A") = true
    1181     * StringUtils.containsIgnoreCase("abc", "Z") = false
    1182     * </pre>
    1183     *
    1184     * @param str  the CharSequence to check, may be null
    1185     * @param searchStr  the CharSequence to find, may be null
    1186     * @return true if the CharSequence contains the search CharSequence irrespective of
    1187     * case or false if not or {@code null} string input
    1188     * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
    1189     */
    1190    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    1191        if (str == null || searchStr == null) {
    1192            return false;
    1193        }
    1194        final int len = searchStr.length();
    1195        final int max = str.length() - len;
    1196        for (int i = 0; i <= max; i++) {
    1197            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
    1198                return true;
    1199            }
    1200        }
    1201        return false;
    1202    }
    1203
    1204    // ContainsNone
    1205    //-----------------------------------------------------------------------
    1206    /**
    1207     * <p>Checks that the CharSequence does not contain certain characters.</p>
    1208     *
    1209     * <p>A {@code null} CharSequence will return {@code true}.
    1210     * A {@code null} invalid character array will return {@code true}.
    1211     * An empty CharSequence (length()=0) always returns true.</p>
    1212     *
    1213     * <pre>
    1214     * StringUtils.containsNone(null, *)       = true
    1215     * StringUtils.containsNone(*, null)       = true
    1216     * StringUtils.containsNone("", *)         = true
    1217     * StringUtils.containsNone("ab", '')      = true
    1218     * StringUtils.containsNone("abab", 'xyz') = true
    1219     * StringUtils.containsNone("ab1", 'xyz')  = true
    1220     * StringUtils.containsNone("abz", 'xyz')  = false
    1221     * </pre>
    1222     *
    1223     * @param cs  the CharSequence to check, may be null
    1224     * @param searchChars  an array of invalid chars, may be null
    1225     * @return true if it contains none of the invalid chars, or is null
    1226     * @since 2.0
    1227     * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
    1228     */
    1229    public static boolean containsNone(final CharSequence cs, final char... searchChars) {
    1230        if (cs == null || searchChars == null) {
    1231            return true;
    1232        }
    1233        final int csLen = cs.length();
    1234        final int csLast = csLen - 1;
    1235        final int searchLen = searchChars.length;
    1236        final int searchLast = searchLen - 1;
    1237        for (int i = 0; i < csLen; i++) {
    1238            final char ch = cs.charAt(i);
    1239            for (int j = 0; j < searchLen; j++) {
    1240                if (searchChars[j] == ch) {
    1241                    if (Character.isHighSurrogate(ch)) {
    1242                        if (j == searchLast) {
    1243                            // missing low surrogate, fine, like String.indexOf(String)
    1244                            return false;
    1245                        }
    1246                        if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
    1247                            return false;
    1248                        }
    1249                    } else {
    1250                        // ch is in the Basic Multilingual Plane
    1251                        return false;
    1252                    }
    1253                }
    1254            }
    1255        }
    1256        return true;
    1257    }
    1258
    1259    /**
    1260     * <p>Checks that the CharSequence does not contain certain characters.</p>
    1261     *
    1262     * <p>A {@code null} CharSequence will return {@code true}.
    1263     * A {@code null} invalid character array will return {@code true}.
    1264     * An empty String ("") always returns true.</p>
    1265     *
    1266     * <pre>
    1267     * StringUtils.containsNone(null, *)       = true
    1268     * StringUtils.containsNone(*, null)       = true
    1269     * StringUtils.containsNone("", *)         = true
    1270     * StringUtils.containsNone("ab", "")      = true
    1271     * StringUtils.containsNone("abab", "xyz") = true
    1272     * StringUtils.containsNone("ab1", "xyz")  = true
    1273     * StringUtils.containsNone("abz", "xyz")  = false
    1274     * </pre>
    1275     *
    1276     * @param cs  the CharSequence to check, may be null
    1277     * @param invalidChars  a String of invalid chars, may be null
    1278     * @return true if it contains none of the invalid chars, or is null
    1279     * @since 2.0
    1280     * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
    1281     */
    1282    public static boolean containsNone(final CharSequence cs, final String invalidChars) {
    1283        if (cs == null || invalidChars == null) {
    1284            return true;
    1285        }
    1286        return containsNone(cs, invalidChars.toCharArray());
    1287    }
    1288
    1289    // ContainsOnly
    1290    //-----------------------------------------------------------------------
    1291    /**
    1292     * <p>Checks if the CharSequence contains only certain characters.</p>
    1293     *
    1294     * <p>A {@code null} CharSequence will return {@code false}.
    1295     * A {@code null} valid character array will return {@code false}.
    1296     * An empty CharSequence (length()=0) always returns {@code true}.</p>
    1297     *
    1298     * <pre>
    1299     * StringUtils.containsOnly(null, *)       = false
    1300     * StringUtils.containsOnly(*, null)       = false
    1301     * StringUtils.containsOnly("", *)         = true
    1302     * StringUtils.containsOnly("ab", '')      = false
    1303     * StringUtils.containsOnly("abab", 'abc') = true
    1304     * StringUtils.containsOnly("ab1", 'abc')  = false
    1305     * StringUtils.containsOnly("abz", 'abc')  = false
    1306     * </pre>
    1307     *
    1308     * @param cs  the String to check, may be null
    1309     * @param valid  an array of valid chars, may be null
    1310     * @return true if it only contains valid chars and is non-null
    1311     * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
    1312     */
    1313    public static boolean containsOnly(final CharSequence cs, final char... valid) {
    1314        // All these pre-checks are to maintain API with an older version
    1315        if (valid == null || cs == null) {
    1316            return false;
    1317        }
    1318        if (cs.length() == 0) {
    1319            return true;
    1320        }
    1321        if (valid.length == 0) {
    1322            return false;
    1323        }
    1324        return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
    1325    }
    1326
    1327    /**
    1328     * <p>Checks if the CharSequence contains only certain characters.</p>
    1329     *
    1330     * <p>A {@code null} CharSequence will return {@code false}.
    1331     * A {@code null} valid character String will return {@code false}.
    1332     * An empty String (length()=0) always returns {@code true}.</p>
    1333     *
    1334     * <pre>
    1335     * StringUtils.containsOnly(null, *)       = false
    1336     * StringUtils.containsOnly(*, null)       = false
    1337     * StringUtils.containsOnly("", *)         = true
    1338     * StringUtils.containsOnly("ab", "")      = false
    1339     * StringUtils.containsOnly("abab", "abc") = true
    1340     * StringUtils.containsOnly("ab1", "abc")  = false
    1341     * StringUtils.containsOnly("abz", "abc")  = false
    1342     * </pre>
    1343     *
    1344     * @param cs  the CharSequence to check, may be null
    1345     * @param validChars  a String of valid chars, may be null
    1346     * @return true if it only contains valid chars and is non-null
    1347     * @since 2.0
    1348     * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
    1349     */
    1350    public static boolean containsOnly(final CharSequence cs, final String validChars) {
    1351        if (cs == null || validChars == null) {
    1352            return false;
    1353        }
    1354        return containsOnly(cs, validChars.toCharArray());
    1355    }
    1356
    1357    /**
    1358     * <p>Check whether the given CharSequence contains any whitespace characters.</p>
    1359     *
    1360     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1361     *
    1362     * @param seq the CharSequence to check (may be {@code null})
    1363     * @return {@code true} if the CharSequence is not empty and
    1364     * contains at least 1 (breaking) whitespace character
    1365     * @since 3.0
    1366     */
    1367    // From org.springframework.util.StringUtils, under Apache License 2.0
    1368    public static boolean containsWhitespace(final CharSequence seq) {
    1369        if (isEmpty(seq)) {
    1370            return false;
    1371        }
    1372        final int strLen = seq.length();
    1373        for (int i = 0; i < strLen; i++) {
    1374            if (Character.isWhitespace(seq.charAt(i))) {
    1375                return true;
    1376            }
    1377        }
    1378        return false;
    1379    }
    1380
    1381    private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
    1382        for (int i = 0; i < decomposed.length(); i++) {
    1383            if (decomposed.charAt(i) == '\u0141') {
    1384                decomposed.deleteCharAt(i);
    1385                decomposed.insert(i, 'L');
    1386            } else if (decomposed.charAt(i) == '\u0142') {
    1387                decomposed.deleteCharAt(i);
    1388                decomposed.insert(i, 'l');
    1389            }
    1390        }
    1391    }
    1392
    1393    /**
    1394     * <p>Counts how many times the char appears in the given string.</p>
    1395     *
    1396     * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
    1397     *
    1398     * <pre>
    1399     * StringUtils.countMatches(null, *)       = 0
    1400     * StringUtils.countMatches("", *)         = 0
    1401     * StringUtils.countMatches("abba", 0)  = 0
    1402     * StringUtils.countMatches("abba", 'a')   = 2
    1403     * StringUtils.countMatches("abba", 'b')  = 2
    1404     * StringUtils.countMatches("abba", 'x') = 0
    1405     * </pre>
    1406     *
    1407     * @param str  the CharSequence to check, may be null
    1408     * @param ch  the char to count
    1409     * @return the number of occurrences, 0 if the CharSequence is {@code null}
    1410     * @since 3.4
    1411     */
    1412    public static int countMatches(final CharSequence str, final char ch) {
    1413        if (isEmpty(str)) {
    1414            return 0;
    1415        }
    1416        int count = 0;
    1417        // We could also call str.toCharArray() for faster look ups but that would generate more garbage.
    1418        for (int i = 0; i < str.length(); i++) {
    1419            if (ch == str.charAt(i)) {
    1420                count++;
    1421            }
    1422        }
    1423        return count;
    1424    }
    1425
    1426    // Count matches
    1427    //-----------------------------------------------------------------------
    1428    /**
    1429     * <p>Counts how many times the substring appears in the larger string.</p>
    1430     *
    1431     * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
    1432     *
    1433     * <pre>
    1434     * StringUtils.countMatches(null, *)       = 0
    1435     * StringUtils.countMatches("", *)         = 0
    1436     * StringUtils.countMatches("abba", null)  = 0
    1437     * StringUtils.countMatches("abba", "")    = 0
    1438     * StringUtils.countMatches("abba", "a")   = 2
    1439     * StringUtils.countMatches("abba", "ab")  = 1
    1440     * StringUtils.countMatches("abba", "xxx") = 0
    1441     * </pre>
    1442     *
    1443     * @param str  the CharSequence to check, may be null
    1444     * @param sub  the substring to count, may be null
    1445     * @return the number of occurrences, 0 if either CharSequence is {@code null}
    1446     * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
    1447     */
    1448    public static int countMatches(final CharSequence str, final CharSequence sub) {
    1449        if (isEmpty(str) || isEmpty(sub)) {
    1450            return 0;
    1451        }
    1452        int count = 0;
    1453        int idx = 0;
    1454        while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
    1455            count++;
    1456            idx += sub.length();
    1457        }
    1458        return count;
    1459    }
    1460
    1461    /**
    1462     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    1463     * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p>
    1464     *
    1465     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1466     *
    1467     * <pre>
    1468     * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
    1469     * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
    1470     * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
    1471     * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
    1472     * StringUtils.defaultIfBlank("", null)      = null
    1473     * </pre>
    1474     * @param <T> the specific kind of CharSequence
    1475     * @param str the CharSequence to check, may be null
    1476     * @param defaultStr  the default CharSequence to return
    1477     *  if the input is whitespace, empty ("") or {@code null}, may be null
    1478     * @return the passed in CharSequence, or the default
    1479     * @see StringUtils#defaultString(String, String)
    1480     */
    1481    public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
    1482        return isBlank(str) ? defaultStr : str;
    1483    }
    1484
    1485    /**
    1486     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    1487     * empty or {@code null}, the value of {@code defaultStr}.</p>
    1488     *
    1489     * <pre>
    1490     * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
    1491     * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
    1492     * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
    1493     * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
    1494     * StringUtils.defaultIfEmpty("", null)      = null
    1495     * </pre>
    1496     * @param <T> the specific kind of CharSequence
    1497     * @param str  the CharSequence to check, may be null
    1498     * @param defaultStr  the default CharSequence to return
    1499     *  if the input is empty ("") or {@code null}, may be null
    1500     * @return the passed in CharSequence, or the default
    1501     * @see StringUtils#defaultString(String, String)
    1502     */
    1503    public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
    1504        return isEmpty(str) ? defaultStr : str;
    1505    }
    1506
    1507    /**
    1508     * <p>Returns either the passed in String,
    1509     * or if the String is {@code null}, an empty String ("").</p>
    1510     *
    1511     * <pre>
    1512     * StringUtils.defaultString(null)  = ""
    1513     * StringUtils.defaultString("")    = ""
    1514     * StringUtils.defaultString("bat") = "bat"
    1515     * </pre>
    1516     *
    1517     * @see ObjectUtils#toString(Object)
    1518     * @see String#valueOf(Object)
    1519     * @param str  the String to check, may be null
    1520     * @return the passed in String, or the empty String if it
    1521     *  was {@code null}
    1522     */
    1523    public static String defaultString(final String str) {
    1524        return defaultString(str, EMPTY);
    1525    }
    1526
    1527    /**
    1528     * <p>Returns either the passed in String, or if the String is
    1529     * {@code null}, the value of {@code defaultStr}.</p>
    1530     *
    1531     * <pre>
    1532     * StringUtils.defaultString(null, "NULL")  = "NULL"
    1533     * StringUtils.defaultString("", "NULL")    = ""
    1534     * StringUtils.defaultString("bat", "NULL") = "bat"
    1535     * </pre>
    1536     *
    1537     * @see ObjectUtils#toString(Object,String)
    1538     * @see String#valueOf(Object)
    1539     * @param str  the String to check, may be null
    1540     * @param defaultStr  the default String to return
    1541     *  if the input is {@code null}, may be null
    1542     * @return the passed in String, or the default if it was {@code null}
    1543     */
    1544    public static String defaultString(final String str, final String defaultStr) {
    1545        return str == null ? defaultStr : str;
    1546    }
    1547
    1548    // Delete
    1549    //-----------------------------------------------------------------------
    1550    /**
    1551     * <p>Deletes all whitespaces from a String as defined by
    1552     * {@link Character#isWhitespace(char)}.</p>
    1553     *
    1554     * <pre>
    1555     * StringUtils.deleteWhitespace(null)         = null
    1556     * StringUtils.deleteWhitespace("")           = ""
    1557     * StringUtils.deleteWhitespace("abc")        = "abc"
    1558     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
    1559     * </pre>
    1560     *
    1561     * @param str  the String to delete whitespace from, may be null
    1562     * @return the String without whitespaces, {@code null} if null String input
    1563     */
    1564    public static String deleteWhitespace(final String str) {
    1565        if (isEmpty(str)) {
    1566            return str;
    1567        }
    1568        final int sz = str.length();
    1569        final char[] chs = new char[sz];
    1570        int count = 0;
    1571        for (int i = 0; i < sz; i++) {
    1572            if (!Character.isWhitespace(str.charAt(i))) {
    1573                chs[count++] = str.charAt(i);
    1574            }
    1575        }
    1576        if (count == sz) {
    1577            return str;
    1578        }
    1579        return new String(chs, 0, count);
    1580    }
    1581
    1582    // Difference
    1583    //-----------------------------------------------------------------------
    1584    /**
    1585     * <p>Compares two Strings, and returns the portion where they differ.
    1586     * More precisely, return the remainder of the second String,
    1587     * starting from where it's different from the first. This means that
    1588     * the difference between "abc" and "ab" is the empty String and not "c". </p>
    1589     *
    1590     * <p>For example,
    1591     * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p>
    1592     *
    1593     * <pre>
    1594     * StringUtils.difference(null, null) = null
    1595     * StringUtils.difference("", "") = ""
    1596     * StringUtils.difference("", "abc") = "abc"
    1597     * StringUtils.difference("abc", "") = ""
    1598     * StringUtils.difference("abc", "abc") = ""
    1599     * StringUtils.difference("abc", "ab") = ""
    1600     * StringUtils.difference("ab", "abxyz") = "xyz"
    1601     * StringUtils.difference("abcde", "abxyz") = "xyz"
    1602     * StringUtils.difference("abcde", "xyz") = "xyz"
    1603     * </pre>
    1604     *
    1605     * @param str1  the first String, may be null
    1606     * @param str2  the second String, may be null
    1607     * @return the portion of str2 where it differs from str1; returns the
    1608     * empty String if they are equal
    1609     * @see #indexOfDifference(CharSequence,CharSequence)
    1610     * @since 2.0
    1611     */
    1612    public static String difference(final String str1, final String str2) {
    1613        if (str1 == null) {
    1614            return str2;
    1615        }
    1616        if (str2 == null) {
    1617            return str1;
    1618        }
    1619        final int at = indexOfDifference(str1, str2);
    1620        if (at == INDEX_NOT_FOUND) {
    1621            return EMPTY;
    1622        }
    1623        return str2.substring(at);
    1624    }
    1625
    1626    /**
    1627     * <p>Check if a CharSequence ends with a specified suffix.</p>
    1628     *
    1629     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1630     * references are considered to be equal. The comparison is case sensitive.</p>
    1631     *
    1632     * <pre>
    1633     * StringUtils.endsWith(null, null)      = true
    1634     * StringUtils.endsWith(null, "def")     = false
    1635     * StringUtils.endsWith("abcdef", null)  = false
    1636     * StringUtils.endsWith("abcdef", "def") = true
    1637     * StringUtils.endsWith("ABCDEF", "def") = false
    1638     * StringUtils.endsWith("ABCDEF", "cde") = false
    1639     * StringUtils.endsWith("ABCDEF", "")    = true
    1640     * </pre>
    1641     *
    1642     * @see java.lang.String#endsWith(String)
    1643     * @param str  the CharSequence to check, may be null
    1644     * @param suffix the suffix to find, may be null
    1645     * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or
    1646     *  both {@code null}
    1647     * @since 2.4
    1648     * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
    1649     */
    1650    public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
    1651        return endsWith(str, suffix, false);
    1652    }
    1653
    1654    /**
    1655     * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p>
    1656     *
    1657     * @see java.lang.String#endsWith(String)
    1658     * @param str  the CharSequence to check, may be null
    1659     * @param suffix the suffix to find, may be null
    1660     * @param ignoreCase indicates whether the compare should ignore case
    1661     *  (case insensitive) or not.
    1662     * @return {@code true} if the CharSequence starts with the prefix or
    1663     *  both {@code null}
    1664     */
    1665    private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
    1666        if (str == null || suffix == null) {
    1667            return str == suffix;
    1668        }
    1669        if (suffix.length() > str.length()) {
    1670            return false;
    1671        }
    1672        final int strOffset = str.length() - suffix.length();
    1673        return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length());
    1674    }
    1675
    1676    /**
    1677     * <p>Check if a CharSequence ends with any of the provided case-sensitive suffixes.</p>
    1678     *
    1679     * <pre>
    1680     * StringUtils.endsWithAny(null, null)      = false
    1681     * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
    1682     * StringUtils.endsWithAny("abcxyz", null)     = false
    1683     * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
    1684     * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
    1685     * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    1686     * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
    1687     * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
    1688     * </pre>
    1689     *
    1690     * @param sequence  the CharSequence to check, may be null
    1691     * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
    1692     * @see StringUtils#endsWith(CharSequence, CharSequence)
    1693     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
    1694     *   the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
    1695     * @since 3.0
    1696     */
    1697    public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
    1698        if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
    1699            return false;
    1700        }
    1701        for (final CharSequence searchString : searchStrings) {
    1702            if (endsWith(sequence, searchString)) {
    1703                return true;
    1704            }
    1705        }
    1706        return false;
    1707    }
    1708
    1709    /**
    1710     * <p>Case insensitive check if a CharSequence ends with a specified suffix.</p>
    1711     *
    1712     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1713     * references are considered to be equal. The comparison is case insensitive.</p>
    1714     *
    1715     * <pre>
    1716     * StringUtils.endsWithIgnoreCase(null, null)      = true
    1717     * StringUtils.endsWithIgnoreCase(null, "def")     = false
    1718     * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
    1719     * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
    1720     * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
    1721     * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
    1722     * </pre>
    1723     *
    1724     * @see java.lang.String#endsWith(String)
    1725     * @param str  the CharSequence to check, may be null
    1726     * @param suffix the suffix to find, may be null
    1727     * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or
    1728     *  both {@code null}
    1729     * @since 2.4
    1730     * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
    1731     */
    1732    public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
    1733        return endsWith(str, suffix, true);
    1734    }
    1735
    1736    // Equals
    1737    //-----------------------------------------------------------------------
    1738    /**
    1739     * <p>Compares two CharSequences, returning {@code true} if they represent
    1740     * equal sequences of characters.</p>
    1741     *
    1742     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1743     * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p>
    1744     *
    1745     * <pre>
    1746     * StringUtils.equals(null, null)   = true
    1747     * StringUtils.equals(null, "abc")  = false
    1748     * StringUtils.equals("abc", null)  = false
    1749     * StringUtils.equals("abc", "abc") = true
    1750     * StringUtils.equals("abc", "ABC") = false
    1751     * </pre>
    1752     *
    1753     * @param cs1  the first CharSequence, may be {@code null}
    1754     * @param cs2  the second CharSequence, may be {@code null}
    1755     * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
    1756     * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
    1757     * @see Object#equals(Object)
    1758     * @see #equalsIgnoreCase(CharSequence, CharSequence)
    1759     */
    1760    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
    1761        if (cs1 == cs2) {
    1762            return true;
    1763        }
    1764        if (cs1 == null || cs2 == null) {
    1765            return false;
    1766        }
    1767        if (cs1.length() != cs2.length()) {
    1768            return false;
    1769        }
    1770        if (cs1 instanceof String && cs2 instanceof String) {
    1771            return cs1.equals(cs2);
    1772        }
    1773        // Step-wise comparison
    1774        final int length = cs1.length();
    1775        for (int i = 0; i < length; i++) {
    1776            if (cs1.charAt(i) != cs2.charAt(i)) {
    1777                return false;
    1778            }
    1779        }
    1780        return true;
    1781    }
    1782
    1783    /**
    1784     * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
    1785     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.</p>
    1786     *
    1787     * <pre>
    1788     * StringUtils.equalsAny(null, (CharSequence[]) null) = false
    1789     * StringUtils.equalsAny(null, null, null)    = true
    1790     * StringUtils.equalsAny(null, "abc", "def")  = false
    1791     * StringUtils.equalsAny("abc", null, "def")  = false
    1792     * StringUtils.equalsAny("abc", "abc", "def") = true
    1793     * StringUtils.equalsAny("abc", "ABC", "DEF") = false
    1794     * </pre>
    1795     *
    1796     * @param string to compare, may be {@code null}.
    1797     * @param searchStrings a vararg of strings, may be {@code null}.
    1798     * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings};
    1799     * {@code false} if {@code searchStrings} is null or contains no matches.
    1800     * @since 3.5
    1801     */
    1802    public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
    1803        if (ArrayUtils.isNotEmpty(searchStrings)) {
    1804            for (final CharSequence next : searchStrings) {
    1805                if (equals(string, next)) {
    1806                    return true;
    1807                }
    1808            }
    1809        }
    1810        return false;
    1811    }
    1812
    1813    /**
    1814     * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
    1815     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.</p>
    1816     *
    1817     * <pre>
    1818     * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
    1819     * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
    1820     * StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
    1821     * StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
    1822     * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
    1823     * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
    1824     * </pre>
    1825     *
    1826     * @param string to compare, may be {@code null}.
    1827     * @param searchStrings a vararg of strings, may be {@code null}.
    1828     * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
    1829     * {@code false} if {@code searchStrings} is null or contains no matches.
    1830     * @since 3.5
    1831     */
    1832    public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) {
    1833        if (ArrayUtils.isNotEmpty(searchStrings)) {
    1834            for (final CharSequence next : searchStrings) {
    1835                if (equalsIgnoreCase(string, next)) {
    1836                    return true;
    1837                }
    1838            }
    1839        }
    1840        return false;
    1841    }
    1842
    1843    /**
    1844     * <p>Compares two CharSequences, returning {@code true} if they represent
    1845     * equal sequences of characters, ignoring case.</p>
    1846     *
    1847     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1848     * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
    1849     *
    1850     * <pre>
    1851     * StringUtils.equalsIgnoreCase(null, null)   = true
    1852     * StringUtils.equalsIgnoreCase(null, "abc")  = false
    1853     * StringUtils.equalsIgnoreCase("abc", null)  = false
    1854     * StringUtils.equalsIgnoreCase("abc", "abc") = true
    1855     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
    1856     * </pre>
    1857     *
    1858     * @param cs1  the first CharSequence, may be {@code null}
    1859     * @param cs2  the second CharSequence, may be {@code null}
    1860     * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
    1861     * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
    1862     * @see #equals(CharSequence, CharSequence)
    1863     */
    1864    public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
    1865        if (cs1 == cs2) {
    1866            return true;
    1867        }
    1868        if (cs1 == null || cs2 == null) {
    1869            return false;
    1870        }
    1871        if (cs1.length() != cs2.length()) {
    1872            return false;
    1873        }
    1874        return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length());
    1875    }
    1876
    1877    /**
    1878     * <p>Returns the first value in the array which is not empty (""),
    1879     * {@code null} or whitespace only.</p>
    1880     *
    1881     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1882     *
    1883     * <p>If all values are blank or the array is {@code null}
    1884     * or empty then {@code null} is returned.</p>
    1885     *
    1886     * <pre>
    1887     * StringUtils.firstNonBlank(null, null, null)     = null
    1888     * StringUtils.firstNonBlank(null, "", " ")        = null
    1889     * StringUtils.firstNonBlank("abc")                = "abc"
    1890     * StringUtils.firstNonBlank(null, "xyz")          = "xyz"
    1891     * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
    1892     * StringUtils.firstNonBlank(null, "xyz", "abc")   = "xyz"
    1893     * StringUtils.firstNonBlank()                     = null
    1894     * </pre>
    1895     *
    1896     * @param <T> the specific kind of CharSequence
    1897     * @param values  the values to test, may be {@code null} or empty
    1898     * @return the first value from {@code values} which is not blank,
    1899     *  or {@code null} if there are no non-blank values
    1900     * @since 3.8
    1901     */
    1902    @SafeVarargs
    1903    public static <T extends CharSequence> T firstNonBlank(final T... values) {
    1904        if (values != null) {
    1905            for (final T val : values) {
    1906                if (isNotBlank(val)) {
    1907                    return val;
    1908                }
    1909            }
    1910        }
    1911        return null;
    1912    }
    1913
    1914    /**
    1915     * <p>Returns the first value in the array which is not empty.</p>
    1916     *
    1917     * <p>If all values are empty or the array is {@code null}
    1918     * or empty then {@code null} is returned.</p>
    1919     *
    1920     * <pre>
    1921     * StringUtils.firstNonEmpty(null, null, null)   = null
    1922     * StringUtils.firstNonEmpty(null, null, "")     = null
    1923     * StringUtils.firstNonEmpty(null, "", " ")      = " "
    1924     * StringUtils.firstNonEmpty("abc")              = "abc"
    1925     * StringUtils.firstNonEmpty(null, "xyz")        = "xyz"
    1926     * StringUtils.firstNonEmpty("", "xyz")          = "xyz"
    1927     * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
    1928     * StringUtils.firstNonEmpty()                   = null
    1929     * </pre>
    1930     *
    1931     * @param <T> the specific kind of CharSequence
    1932     * @param values  the values to test, may be {@code null} or empty
    1933     * @return the first value from {@code values} which is not empty,
    1934     *  or {@code null} if there are no non-empty values
    1935     * @since 3.8
    1936     */
    1937    @SafeVarargs
    1938    public static <T extends CharSequence> T firstNonEmpty(final T... values) {
    1939        if (values != null) {
    1940            for (final T val : values) {
    1941                if (isNotEmpty(val)) {
    1942                    return val;
    1943                }
    1944            }
    1945        }
    1946        return null;
    1947    }
    1948
    1949    /**
    1950     * Calls {@link String#getBytes(Charset)} in a null-safe manner.
    1951     *
    1952     * @param string input string
    1953     * @param charset The {@link Charset} to encode the {@code String}. If null, then use the default Charset.
    1954     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
    1955     * @see String#getBytes(Charset)
    1956     * @since 3.10
    1957     */
    1958    public static byte[] getBytes(final String string, final Charset charset) {
    1959        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
    1960    }
    1961
    1962    /**
    1963     * Calls {@link String#getBytes(String)} in a null-safe manner.
    1964     *
    1965     * @param string input string
    1966     * @param charset The {@link Charset} name to encode the {@code String}. If null, then use the default Charset.
    1967     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
    1968     * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
    1969     * @see String#getBytes(String)
    1970     * @since 3.10
    1971     */
    1972    public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
    1973        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
    1974    }
    1975
    1976    /**
    1977     * <p>Compares all Strings in an array and returns the initial sequence of
    1978     * characters that is common to all of them.</p>
    1979     *
    1980     * <p>For example,
    1981     * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -&gt; "i am a "}</p>
    1982     *
    1983     * <pre>
    1984     * StringUtils.getCommonPrefix(null) = ""
    1985     * StringUtils.getCommonPrefix(new String[] {}) = ""
    1986     * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
    1987     * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
    1988     * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
    1989     * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
    1990     * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
    1991     * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
    1992     * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
    1993     * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
    1994     * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
    1995     * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
    1996     * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
    1997     * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
    1998     * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
    1999     * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
    2000     * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
    2001     * </pre>
    2002     *
    2003     * @param strs  array of String objects, entries may be null
    2004     * @return the initial sequence of characters that are common to all Strings
    2005     * in the array; empty String if the array is null, the elements are all null
    2006     * or if there is no common prefix.
    2007     * @since 2.4
    2008     */
    2009    public static String getCommonPrefix(final String... strs) {
    2010        if (ArrayUtils.isEmpty(strs)) {
    2011            return EMPTY;
    2012        }
    2013        final int smallestIndexOfDiff = indexOfDifference(strs);
    2014        if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
    2015            // all strings were identical
    2016            if (strs[0] == null) {
    2017                return EMPTY;
    2018            }
    2019            return strs[0];
    2020        } else if (smallestIndexOfDiff == 0) {
    2021            // there were no common initial characters
    2022            return EMPTY;
    2023        } else {
    2024            // we found a common initial character sequence
    2025            return strs[0].substring(0, smallestIndexOfDiff);
    2026        }
    2027    }
    2028
    2029    /**
    2030     * <p>Checks if a String {@code str} contains Unicode digits,
    2031     * if yes then concatenate all the digits in {@code str} and return it as a String.</p>
    2032     *
    2033     * <p>An empty ("") String will be returned if no digits found in {@code str}.</p>
    2034     *
    2035     * <pre>
    2036     * StringUtils.getDigits(null)  = null
    2037     * StringUtils.getDigits("")    = ""
    2038     * StringUtils.getDigits("abc") = ""
    2039     * StringUtils.getDigits("1000$") = "1000"
    2040     * StringUtils.getDigits("1123~45") = "112345"
    2041     * StringUtils.getDigits("(541) 754-3010") = "5417543010"
    2042     * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
    2043     * </pre>
    2044     *
    2045     * @param str the String to extract digits from, may be null
    2046     * @return String with only digits,
    2047     *           or an empty ("") String if no digits found,
    2048     *           or {@code null} String if {@code str} is null
    2049     * @since 3.6
    2050     */
    2051    public static String getDigits(final String str) {
    2052        if (isEmpty(str)) {
    2053            return str;
    2054        }
    2055        final int sz = str.length();
    2056        final StringBuilder strDigits = new StringBuilder(sz);
    2057        for (int i = 0; i < sz; i++) {
    2058            final char tempChar = str.charAt(i);
    2059            if (Character.isDigit(tempChar)) {
    2060                strDigits.append(tempChar);
    2061            }
    2062        }
    2063        return strDigits.toString();
    2064    }
    2065
    2066    /**
    2067     * <p>Find the Fuzzy Distance which indicates the similarity score between two Strings.</p>
    2068     *
    2069     * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
    2070     * TextMate, Atom and others. One point is given for every matched character. Subsequent
    2071     * matches yield two bonus points. A higher score indicates a higher similarity.</p>
    2072     *
    2073     * <pre>
    2074     * StringUtils.getFuzzyDistance(null, null, null)                                    = IllegalArgumentException
    2075     * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH)                              = 0
    2076     * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH)                     = 0
    2077     * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH)                         = 1
    2078     * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH)                     = 1
    2079     * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH)                    = 2
    2080     * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH)                    = 4
    2081     * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
    2082     * </pre>
    2083     *
    2084     * @param term a full term that should be matched against, must not be null
    2085     * @param query the query that will be matched against a term, must not be null
    2086     * @param locale This string matching logic is case insensitive. A locale is necessary to normalize
    2087     *  both Strings to lower case.
    2088     * @return result score
    2089     * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
    2090     * @since 3.4
    2091     * @deprecated as of 3.6, use commons-text
    2092     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
    2093     * FuzzyScore</a> instead
    2094     */
    2095    @Deprecated
    2096    public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
    2097        if (term == null || query == null) {
    2098            throw new IllegalArgumentException("Strings must not be null");
    2099        } else if (locale == null) {
    2100            throw new IllegalArgumentException("Locale must not be null");
    2101        }
    2102
    2103        // fuzzy logic is case insensitive. We normalize the Strings to lower
    2104        // case right from the start. Turning characters to lower case
    2105        // via Character.toLowerCase(char) is unfortunately insufficient
    2106        // as it does not accept a locale.
    2107        final String termLowerCase = term.toString().toLowerCase(locale);
    2108        final String queryLowerCase = query.toString().toLowerCase(locale);
    2109
    2110        // the resulting score
    2111        int score = 0;
    2112
    2113        // the position in the term which will be scanned next for potential
    2114        // query character matches
    2115        int termIndex = 0;
    2116
    2117        // index of the previously matched character in the term
    2118        int previousMatchingCharacterIndex = Integer.MIN_VALUE;
    2119
    2120        for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
    2121            final char queryChar = queryLowerCase.charAt(queryIndex);
    2122
    2123            boolean termCharacterMatchFound = false;
    2124            for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
    2125                final char termChar = termLowerCase.charAt(termIndex);
    2126
    2127                if (queryChar == termChar) {
    2128                    // simple character matches result in one point
    2129                    score++;
    2130
    2131                    // subsequent character matches further improve
    2132                    // the score.
    2133                    if (previousMatchingCharacterIndex + 1 == termIndex) {
    2134                        score += 2;
    2135                    }
    2136
    2137                    previousMatchingCharacterIndex = termIndex;
    2138
    2139                    // we can leave the nested loop. Every character in the
    2140                    // query can match at most one character in the term.
    2141                    termCharacterMatchFound = true;
    2142                }
    2143            }
    2144        }
    2145
    2146        return score;
    2147    }
    2148
    2149    /**
    2150     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    2151     * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.</p>
    2152     *
    2153     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2154     *
    2155     * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
    2156     *
    2157     * <pre>
    2158     * {@code
    2159     * StringUtils.getIfBlank(null, () -> "NULL")   = "NULL"
    2160     * StringUtils.getIfBlank("", () -> "NULL")     = "NULL"
    2161     * StringUtils.getIfBlank(" ", () -> "NULL")    = "NULL"
    2162     * StringUtils.getIfBlank("bat", () -> "NULL")  = "bat"
    2163     * StringUtils.getIfBlank("", () -> null)       = null
    2164     * StringUtils.getIfBlank("", null)             = null
    2165     * }</pre>
    2166     * @param <T> the specific kind of CharSequence
    2167     * @param str the CharSequence to check, may be null
    2168     * @param defaultSupplier the supplier of default CharSequence to return
    2169     *  if the input is whitespace, empty ("") or {@code null}, may be null
    2170     * @return the passed in CharSequence, or the default
    2171     * @see StringUtils#defaultString(String, String)
    2172     * @since 3.10
    2173     */
    2174    public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
    2175        return isBlank(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str;
    2176    }
    2177
    2178    /**
    2179     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    2180     * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.</p>
    2181     *
    2182     * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
    2183     *
    2184     * <pre>
    2185     * {@code
    2186     * StringUtils.getIfEmpty(null, () -> "NULL")    = "NULL"
    2187     * StringUtils.getIfEmpty("", () -> "NULL")      = "NULL"
    2188     * StringUtils.getIfEmpty(" ", () -> "NULL")     = " "
    2189     * StringUtils.getIfEmpty("bat", () -> "NULL")   = "bat"
    2190     * StringUtils.getIfEmpty("", () -> null)        = null
    2191     * StringUtils.getIfEmpty("", null)              = null
    2192     * }
    2193     * </pre>
    2194     * @param <T> the specific kind of CharSequence
    2195     * @param str  the CharSequence to check, may be null
    2196     * @param defaultSupplier  the supplier of default CharSequence to return
    2197     *  if the input is empty ("") or {@code null}, may be null
    2198     * @return the passed in CharSequence, or the default
    2199     * @see StringUtils#defaultString(String, String)
    2200     * @since 3.10
    2201     */
    2202    public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
    2203        return isEmpty(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str;
    2204    }
    2205
    2206    /**
    2207     * <p>Find the Jaro Winkler Distance which indicates the similarity score between two Strings.</p>
    2208     *
    2209     * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
    2210     * Winkler increased this measure for matching initial characters.</p>
    2211     *
    2212     * <p>This implementation is based on the Jaro Winkler similarity algorithm
    2213     * from <a href="http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p>
    2214     *
    2215     * <pre>
    2216     * StringUtils.getJaroWinklerDistance(null, null)          = IllegalArgumentException
    2217     * StringUtils.getJaroWinklerDistance("", "")              = 0.0
    2218     * StringUtils.getJaroWinklerDistance("", "a")             = 0.0
    2219     * StringUtils.getJaroWinklerDistance("aaapppp", "")       = 0.0
    2220     * StringUtils.getJaroWinklerDistance("frog", "fog")       = 0.93
    2221     * StringUtils.getJaroWinklerDistance("fly", "ant")        = 0.0
    2222     * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
    2223     * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
    2224     * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
    2225     * StringUtils.getJaroWinklerDistance("hello", "hallo")    = 0.88
    2226     * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
    2227     * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D &amp; H Enterprises, Inc.") = 0.95
    2228     * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
    2229     * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
    2230     * </pre>
    2231     *
    2232     * @param first the first String, must not be null
    2233     * @param second the second String, must not be null
    2234     * @return result distance
    2235     * @throws IllegalArgumentException if either String input {@code null}
    2236     * @since 3.3
    2237     * @deprecated as of 3.6, use commons-text
    2238     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
    2239     * JaroWinklerDistance</a> instead
    2240     */
    2241    @Deprecated
    2242    public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
    2243        final double DEFAULT_SCALING_FACTOR = 0.1;
    2244
    2245        if (first == null || second == null) {
    2246            throw new IllegalArgumentException("Strings must not be null");
    2247        }
    2248
    2249        final int[] mtp = matches(first, second);
    2250        final double m = mtp[0];
    2251        if (m == 0) {
    2252            return 0D;
    2253        }
    2254        final double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3;
    2255        final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
    2256        return Math.round(jw * 100.0D) / 100.0D;
    2257    }
    2258
    2259    // Misc
    2260    //-----------------------------------------------------------------------
    2261    /**
    2262     * <p>Find the Levenshtein distance between two Strings.</p>
    2263     *
    2264     * <p>This is the number of changes needed to change one String into
    2265     * another, where each change is a single character modification (deletion,
    2266     * insertion or substitution).</p>
    2267     *
    2268     * <p>The implementation uses a single-dimensional array of length s.length() + 1. See
    2269     * <a href="http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
    2270     * http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p>
    2271     *
    2272     * <pre>
    2273     * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
    2274     * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
    2275     * StringUtils.getLevenshteinDistance("", "")              = 0
    2276     * StringUtils.getLevenshteinDistance("", "a")             = 1
    2277     * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
    2278     * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
    2279     * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
    2280     * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
    2281     * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
    2282     * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
    2283     * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
    2284     * </pre>
    2285     *
    2286     * @param s  the first String, must not be null
    2287     * @param t  the second String, must not be null
    2288     * @return result distance
    2289     * @throws IllegalArgumentException if either String input {@code null}
    2290     * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
    2291     * getLevenshteinDistance(CharSequence, CharSequence)
    2292     * @deprecated as of 3.6, use commons-text
    2293     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
    2294     * LevenshteinDistance</a> instead
    2295     */
    2296    @Deprecated
    2297    public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
    2298        if (s == null || t == null) {
    2299            throw new IllegalArgumentException("Strings must not be null");
    2300        }
    2301
    2302        int n = s.length();
    2303        int m = t.length();
    2304
    2305        if (n == 0) {
    2306            return m;
    2307        } else if (m == 0) {
    2308            return n;
    2309        }
    2310
    2311        if (n > m) {
    2312            // swap the input strings to consume less memory
    2313            final CharSequence tmp = s;
    2314            s = t;
    2315            t = tmp;
    2316            n = m;
    2317            m = t.length();
    2318        }
    2319
    2320        final int p[] = new int[n + 1];
    2321        // indexes into strings s and t
    2322        int i; // iterates through s
    2323        int j; // iterates through t
    2324        int upper_left;
    2325        int upper;
    2326
    2327        char t_j; // jth character of t
    2328        int cost;
    2329
    2330        for (i = 0; i <= n; i++) {
    2331            p[i] = i;
    2332        }
    2333
    2334        for (j = 1; j <= m; j++) {
    2335            upper_left = p[0];
    2336            t_j = t.charAt(j - 1);
    2337            p[0] = j;
    2338
    2339            for (i = 1; i <= n; i++) {
    2340                upper = p[i];
    2341                cost = s.charAt(i - 1) == t_j ? 0 : 1;
    2342                // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
    2343                p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost);
    2344                upper_left = upper;
    2345            }
    2346        }
    2347
    2348        return p[n];
    2349    }
    2350
    2351    /**
    2352     * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given
    2353     * threshold.</p>
    2354     *
    2355     * <p>This is the number of changes needed to change one String into
    2356     * another, where each change is a single character modification (deletion,
    2357     * insertion or substitution).</p>
    2358     *
    2359     * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
    2360     * and Chas Emerick's implementation of the Levenshtein distance algorithm from
    2361     * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
    2362     *
    2363     * <pre>
    2364     * StringUtils.getLevenshteinDistance(null, *, *)             = IllegalArgumentException
    2365     * StringUtils.getLevenshteinDistance(*, null, *)             = IllegalArgumentException
    2366     * StringUtils.getLevenshteinDistance(*, *, -1)               = IllegalArgumentException
    2367     * StringUtils.getLevenshteinDistance("", "", 0)              = 0
    2368     * StringUtils.getLevenshteinDistance("aaapppp", "", 8)       = 7
    2369     * StringUtils.getLevenshteinDistance("aaapppp", "", 7)       = 7
    2370     * StringUtils.getLevenshteinDistance("aaapppp", "", 6))      = -1
    2371     * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
    2372     * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
    2373     * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
    2374     * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
    2375     * </pre>
    2376     *
    2377     * @param s  the first String, must not be null
    2378     * @param t  the second String, must not be null
    2379     * @param threshold the target threshold, must not be negative
    2380     * @return result distance, or {@code -1} if the distance would be greater than the threshold
    2381     * @throws IllegalArgumentException if either String input {@code null} or negative threshold
    2382     * @deprecated as of 3.6, use commons-text
    2383     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
    2384     * LevenshteinDistance</a> instead
    2385     */
    2386    @Deprecated
    2387    public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
    2388        if (s == null || t == null) {
    2389            throw new IllegalArgumentException("Strings must not be null");
    2390        }
    2391        if (threshold < 0) {
    2392            throw new IllegalArgumentException("Threshold must not be negative");
    2393        }
    2394
    2395        /*
    2396        This implementation only computes the distance if it's less than or equal to the
    2397        threshold value, returning -1 if it's greater.  The advantage is performance: unbounded
    2398        distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
    2399        computing a diagonal stripe of width 2k + 1 of the cost table.
    2400        It is also possible to use this to compute the unbounded Levenshtein distance by starting
    2401        the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
    2402        d is the distance.
    2403
    2404        One subtlety comes from needing to ignore entries on the border of our stripe
    2405        eg.
    2406        p[] = |#|#|#|*
    2407        d[] =  *|#|#|#|
    2408        We must ignore the entry to the left of the leftmost member
    2409        We must ignore the entry above the rightmost member
    2410
    2411        Another subtlety comes from our stripe running off the matrix if the strings aren't
    2412        of the same size.  Since string s is always swapped to be the shorter of the two,
    2413        the stripe will always run off to the upper right instead of the lower left of the matrix.
    2414
    2415        As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
    2416        In this case we're going to walk a stripe of length 3.  The matrix would look like so:
    2417
    2418           1 2 3 4 5
    2419        1 |#|#| | | |
    2420        2 |#|#|#| | |
    2421        3 | |#|#|#| |
    2422        4 | | |#|#|#|
    2423        5 | | | |#|#|
    2424        6 | | | | |#|
    2425        7 | | | | | |
    2426
    2427        Note how the stripe leads off the table as there is no possible way to turn a string of length 5
    2428        into one of length 7 in edit distance of 1.
    2429
    2430        Additionally, this implementation decreases memory usage by using two
    2431        single-dimensional arrays and swapping them back and forth instead of allocating
    2432        an entire n by m matrix.  This requires a few minor changes, such as immediately returning
    2433        when it's detected that the stripe has run off the matrix and initially filling the arrays with
    2434        large values so that entries we don't compute are ignored.
    2435
    2436        See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
    2437         */
    2438
    2439        int n = s.length(); // length of s
    2440        int m = t.length(); // length of t
    2441
    2442        // if one string is empty, the edit distance is necessarily the length of the other
    2443        if (n == 0) {
    2444            return m <= threshold ? m : -1;
    2445        } else if (m == 0) {
    2446            return n <= threshold ? n : -1;
    2447        } else if (Math.abs(n - m) > threshold) {
    2448            // no need to calculate the distance if the length difference is greater than the threshold
    2449            return -1;
    2450        }
    2451
    2452        if (n > m) {
    2453            // swap the two strings to consume less memory
    2454            final CharSequence tmp = s;
    2455            s = t;
    2456            t = tmp;
    2457            n = m;
    2458            m = t.length();
    2459        }
    2460
    2461        int p[] = new int[n + 1]; // 'previous' cost array, horizontally
    2462        int d[] = new int[n + 1]; // cost array, horizontally
    2463        int _d[]; // placeholder to assist in swapping p and d
    2464
    2465        // fill in starting table values
    2466        final int boundary = Math.min(n, threshold) + 1;
    2467        for (int i = 0; i < boundary; i++) {
    2468            p[i] = i;
    2469        }
    2470        // these fills ensure that the value above the rightmost entry of our
    2471        // stripe will be ignored in following loop iterations
    2472        Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
    2473        Arrays.fill(d, Integer.MAX_VALUE);
    2474
    2475        // iterates through t
    2476        for (int j = 1; j <= m; j++) {
    2477            final char t_j = t.charAt(j - 1); // jth character of t
    2478            d[0] = j;
    2479
    2480            // compute stripe indices, constrain to array size
    2481            final int min = Math.max(1, j - threshold);
    2482            final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
    2483
    2484            // the stripe may lead off of the table if s and t are of different sizes
    2485            if (min > max) {
    2486                return -1;
    2487            }
    2488
    2489            // ignore entry left of leftmost
    2490            if (min > 1) {
    2491                d[min - 1] = Integer.MAX_VALUE;
    2492            }
    2493
    2494            // iterates through [min, max] in s
    2495            for (int i = min; i <= max; i++) {
    2496                if (s.charAt(i - 1) == t_j) {
    2497                    // diagonally left and up
    2498                    d[i] = p[i - 1];
    2499                } else {
    2500                    // 1 + minimum of cell to the left, to the top, diagonally left and up
    2501                    d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
    2502                }
    2503            }
    2504
    2505            // copy current distance counts to 'previous row' distance counts
    2506            _d = p;
    2507            p = d;
    2508            d = _d;
    2509        }
    2510
    2511        // if p[n] is greater than the threshold, there's no guarantee on it being the correct
    2512        // distance
    2513        if (p[n] <= threshold) {
    2514            return p[n];
    2515        }
    2516        return -1;
    2517    }
    2518
    2519    /**
    2520     * <p>Finds the first index within a CharSequence, handling {@code null}.
    2521     * This method uses {@link String#indexOf(String, int)} if possible.</p>
    2522     *
    2523     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    2524     *
    2525     * <pre>
    2526     * StringUtils.indexOf(null, *)          = -1
    2527     * StringUtils.indexOf(*, null)          = -1
    2528     * StringUtils.indexOf("", "")           = 0
    2529     * StringUtils.indexOf("", *)            = -1 (except when * = "")
    2530     * StringUtils.indexOf("aabaabaa", "a")  = 0
    2531     * StringUtils.indexOf("aabaabaa", "b")  = 2
    2532     * StringUtils.indexOf("aabaabaa", "ab") = 1
    2533     * StringUtils.indexOf("aabaabaa", "")   = 0
    2534     * </pre>
    2535     *
    2536     * @param seq  the CharSequence to check, may be null
    2537     * @param searchSeq  the CharSequence to find, may be null
    2538     * @return the first index of the search CharSequence,
    2539     *  -1 if no match or {@code null} string input
    2540     * @since 2.0
    2541     * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
    2542     */
    2543    public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
    2544        if (seq == null || searchSeq == null) {
    2545            return INDEX_NOT_FOUND;
    2546        }
    2547        return CharSequenceUtils.indexOf(seq, searchSeq, 0);
    2548    }
    2549
    2550    /**
    2551     * <p>Finds the first index within a CharSequence, handling {@code null}.
    2552     * This method uses {@link String#indexOf(String, int)} if possible.</p>
    2553     *
    2554     * <p>A {@code null} CharSequence will return {@code -1}.
    2555     * A negative start position is treated as zero.
    2556     * An empty ("") search CharSequence always matches.
    2557     * A start position greater than the string length only matches
    2558     * an empty search CharSequence.</p>
    2559     *
    2560     * <pre>
    2561     * StringUtils.indexOf(null, *, *)          = -1
    2562     * StringUtils.indexOf(*, null, *)          = -1
    2563     * StringUtils.indexOf("", "", 0)           = 0
    2564     * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
    2565     * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
    2566     * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
    2567     * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
    2568     * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
    2569     * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
    2570     * StringUtils.indexOf("aabaabaa", "b", -1) = 2
    2571     * StringUtils.indexOf("aabaabaa", "", 2)   = 2
    2572     * StringUtils.indexOf("abc", "", 9)        = 3
    2573     * </pre>
    2574     *
    2575     * @param seq  the CharSequence to check, may be null
    2576     * @param searchSeq  the CharSequence to find, may be null
    2577     * @param startPos  the start position, negative treated as zero
    2578     * @return the first index of the search CharSequence (always &ge; startPos),
    2579     *  -1 if no match or {@code null} string input
    2580     * @since 2.0
    2581     * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
    2582     */
    2583    public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
    2584        if (seq == null || searchSeq == null) {
    2585            return INDEX_NOT_FOUND;
    2586        }
    2587        return CharSequenceUtils.indexOf(seq, searchSeq, startPos);
    2588    }
    2589
    2590    // IndexOf
    2591    //-----------------------------------------------------------------------
    2592    /**
    2593     * Returns the index within {@code seq} of the first occurrence of
    2594     * the specified character. If a character with value
    2595     * {@code searchChar} occurs in the character sequence represented by
    2596     * {@code seq} {@code CharSequence} object, then the index (in Unicode
    2597     * code units) of the first such occurrence is returned. For
    2598     * values of {@code searchChar} in the range from 0 to 0xFFFF
    2599     * (inclusive), this is the smallest value <i>k</i> such that:
    2600     * <blockquote><pre>
    2601     * this.charAt(<i>k</i>) == searchChar
    2602     * </pre></blockquote>
    2603     * is true. For other values of {@code searchChar}, it is the
    2604     * smallest value <i>k</i> such that:
    2605     * <blockquote><pre>
    2606     * this.codePointAt(<i>k</i>) == searchChar
    2607     * </pre></blockquote>
    2608     * is true. In either case, if no such character occurs in {@code seq},
    2609     * then {@code INDEX_NOT_FOUND (-1)} is returned.
    2610     *
    2611     * <p>Furthermore, a {@code null} or empty ("") CharSequence will
    2612     * return {@code INDEX_NOT_FOUND (-1)}.</p>
    2613     *
    2614     * <pre>
    2615     * StringUtils.indexOf(null, *)         = -1
    2616     * StringUtils.indexOf("", *)           = -1
    2617     * StringUtils.indexOf("aabaabaa", 'a') = 0
    2618     * StringUtils.indexOf("aabaabaa", 'b') = 2
    2619     * </pre>
    2620     *
    2621     * @param seq  the CharSequence to check, may be null
    2622     * @param searchChar  the character to find
    2623     * @return the first index of the search character,
    2624     *  -1 if no match or {@code null} string input
    2625     * @since 2.0
    2626     * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
    2627     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    2628     */
    2629    public static int indexOf(final CharSequence seq, final int searchChar) {
    2630        if (isEmpty(seq)) {
    2631            return INDEX_NOT_FOUND;
    2632        }
    2633        return CharSequenceUtils.indexOf(seq, searchChar, 0);
    2634    }
    2635
    2636    /**
    2637     *
    2638     * Returns the index within {@code seq} of the first occurrence of the
    2639     * specified character, starting the search at the specified index.
    2640     * <p>
    2641     * If a character with value {@code searchChar} occurs in the
    2642     * character sequence represented by the {@code seq} {@code CharSequence}
    2643     * object at an index no smaller than {@code startPos}, then
    2644     * the index of the first such occurrence is returned. For values
    2645     * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive),
    2646     * this is the smallest value <i>k</i> such that:
    2647     * <blockquote><pre>
    2648     * (this.charAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &gt;= startPos)
    2649     * </pre></blockquote>
    2650     * is true. For other values of {@code searchChar}, it is the
    2651     * smallest value <i>k</i> such that:
    2652     * <blockquote><pre>
    2653     * (this.codePointAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &gt;= startPos)
    2654     * </pre></blockquote>
    2655     * is true. In either case, if no such character occurs in {@code seq}
    2656     * at or after position {@code startPos}, then
    2657     * {@code -1} is returned.
    2658     *
    2659     * <p>
    2660     * There is no restriction on the value of {@code startPos}. If it
    2661     * is negative, it has the same effect as if it were zero: this entire
    2662     * string may be searched. If it is greater than the length of this
    2663     * string, it has the same effect as if it were equal to the length of
    2664     * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a
    2665     * {@code null} or empty ("") CharSequence will
    2666     * return {@code (INDEX_NOT_FOUND) -1}.
    2667     *
    2668     * <p>All indices are specified in {@code char} values
    2669     * (Unicode code units).
    2670     *
    2671     * <pre>
    2672     * StringUtils.indexOf(null, *, *)          = -1
    2673     * StringUtils.indexOf("", *, *)            = -1
    2674     * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
    2675     * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
    2676     * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
    2677     * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
    2678     * </pre>
    2679     *
    2680     * @param seq  the CharSequence to check, may be null
    2681     * @param searchChar  the character to find
    2682     * @param startPos  the start position, negative treated as zero
    2683     * @return the first index of the search character (always &ge; startPos),
    2684     *  -1 if no match or {@code null} string input
    2685     * @since 2.0
    2686     * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
    2687     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    2688     */
    2689    public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
    2690        if (isEmpty(seq)) {
    2691            return INDEX_NOT_FOUND;
    2692        }
    2693        return CharSequenceUtils.indexOf(seq, searchChar, startPos);
    2694    }
    2695
    2696    // IndexOfAny chars
    2697    //-----------------------------------------------------------------------
    2698    /**
    2699     * <p>Search a CharSequence to find the first index of any
    2700     * character in the given set of characters.</p>
    2701     *
    2702     * <p>A {@code null} String will return {@code -1}.
    2703     * A {@code null} or zero length search array will return {@code -1}.</p>
    2704     *
    2705     * <pre>
    2706     * StringUtils.indexOfAny(null, *)                  = -1
    2707     * StringUtils.indexOfAny("", *)                    = -1
    2708     * StringUtils.indexOfAny(*, null)                  = -1
    2709     * StringUtils.indexOfAny(*, [])                    = -1
    2710     * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0
    2711     * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3
    2712     * StringUtils.indexOfAny("aba", ['z'])             = -1
    2713     * </pre>
    2714     *
    2715     * @param cs  the CharSequence to check, may be null
    2716     * @param searchChars  the chars to search for, may be null
    2717     * @return the index of any of the chars, -1 if no match or null input
    2718     * @since 2.0
    2719     * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
    2720     */
    2721    public static int indexOfAny(final CharSequence cs, final char... searchChars) {
    2722        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    2723            return INDEX_NOT_FOUND;
    2724        }
    2725        final int csLen = cs.length();
    2726        final int csLast = csLen - 1;
    2727        final int searchLen = searchChars.length;
    2728        final int searchLast = searchLen - 1;
    2729        for (int i = 0; i < csLen; i++) {
    2730            final char ch = cs.charAt(i);
    2731            for (int j = 0; j < searchLen; j++) {
    2732                if (searchChars[j] == ch) {
    2733                    if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
    2734                        // ch is a supplementary character
    2735                        if (searchChars[j + 1] == cs.charAt(i + 1)) {
    2736                            return i;
    2737                        }
    2738                    } else {
    2739                        return i;
    2740                    }
    2741                }
    2742            }
    2743        }
    2744        return INDEX_NOT_FOUND;
    2745    }
    2746
    2747    // IndexOfAny strings
    2748    //-----------------------------------------------------------------------
    2749    /**
    2750     * <p>Find the first index of any of a set of potential substrings.</p>
    2751     *
    2752     * <p>A {@code null} CharSequence will return {@code -1}.
    2753     * A {@code null} or zero length search array will return {@code -1}.
    2754     * A {@code null} search array entry will be ignored, but a search
    2755     * array containing "" will return {@code 0} if {@code str} is not
    2756     * null. This method uses {@link String#indexOf(String)} if possible.</p>
    2757     *
    2758     * <pre>
    2759     * StringUtils.indexOfAny(null, *)                      = -1
    2760     * StringUtils.indexOfAny(*, null)                      = -1
    2761     * StringUtils.indexOfAny(*, [])                        = -1
    2762     * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"])   = 2
    2763     * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"])   = 2
    2764     * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"])   = -1
    2765     * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1
    2766     * StringUtils.indexOfAny("zzabyycdxx", [""])           = 0
    2767     * StringUtils.indexOfAny("", [""])                     = 0
    2768     * StringUtils.indexOfAny("", ["a"])                    = -1
    2769     * </pre>
    2770     *
    2771     * @param str  the CharSequence to check, may be null
    2772     * @param searchStrs  the CharSequences to search for, may be null
    2773     * @return the first index of any of the searchStrs in str, -1 if no match
    2774     * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
    2775     */
    2776    public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
    2777        if (str == null || searchStrs == null) {
    2778            return INDEX_NOT_FOUND;
    2779        }
    2780
    2781        // String's can't have a MAX_VALUEth index.
    2782        int ret = Integer.MAX_VALUE;
    2783
    2784        int tmp = 0;
    2785        for (final CharSequence search : searchStrs) {
    2786            if (search == null) {
    2787                continue;
    2788            }
    2789            tmp = CharSequenceUtils.indexOf(str, search, 0);
    2790            if (tmp == INDEX_NOT_FOUND) {
    2791                continue;
    2792            }
    2793
    2794            if (tmp < ret) {
    2795                ret = tmp;
    2796            }
    2797        }
    2798
    2799        return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
    2800    }
    2801
    2802    /**
    2803     * <p>Search a CharSequence to find the first index of any
    2804     * character in the given set of characters.</p>
    2805     *
    2806     * <p>A {@code null} String will return {@code -1}.
    2807     * A {@code null} search string will return {@code -1}.</p>
    2808     *
    2809     * <pre>
    2810     * StringUtils.indexOfAny(null, *)            = -1
    2811     * StringUtils.indexOfAny("", *)              = -1
    2812     * StringUtils.indexOfAny(*, null)            = -1
    2813     * StringUtils.indexOfAny(*, "")              = -1
    2814     * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
    2815     * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
    2816     * StringUtils.indexOfAny("aba", "z")         = -1
    2817     * </pre>
    2818     *
    2819     * @param cs  the CharSequence to check, may be null
    2820     * @param searchChars  the chars to search for, may be null
    2821     * @return the index of any of the chars, -1 if no match or null input
    2822     * @since 2.0
    2823     * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
    2824     */
    2825    public static int indexOfAny(final CharSequence cs, final String searchChars) {
    2826        if (isEmpty(cs) || isEmpty(searchChars)) {
    2827            return INDEX_NOT_FOUND;
    2828        }
    2829        return indexOfAny(cs, searchChars.toCharArray());
    2830    }
    2831
    2832    // IndexOfAnyBut chars
    2833    //-----------------------------------------------------------------------
    2834    /**
    2835     * <p>Searches a CharSequence to find the first index of any
    2836     * character not in the given set of characters.</p>
    2837     *
    2838     * <p>A {@code null} CharSequence will return {@code -1}.
    2839     * A {@code null} or zero length search array will return {@code -1}.</p>
    2840     *
    2841     * <pre>
    2842     * StringUtils.indexOfAnyBut(null, *)                              = -1
    2843     * StringUtils.indexOfAnyBut("", *)                                = -1
    2844     * StringUtils.indexOfAnyBut(*, null)                              = -1
    2845     * StringUtils.indexOfAnyBut(*, [])                                = -1
    2846     * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
    2847     * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
    2848     * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1
    2849
    2850     * </pre>
    2851     *
    2852     * @param cs  the CharSequence to check, may be null
    2853     * @param searchChars  the chars to search for, may be null
    2854     * @return the index of any of the chars, -1 if no match or null input
    2855     * @since 2.0
    2856     * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
    2857     */
    2858    public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
    2859        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    2860            return INDEX_NOT_FOUND;
    2861        }
    2862        final int csLen = cs.length();
    2863        final int csLast = csLen - 1;
    2864        final int searchLen = searchChars.length;
    2865        final int searchLast = searchLen - 1;
    2866        outer:
    2867        for (int i = 0; i < csLen; i++) {
    2868            final char ch = cs.charAt(i);
    2869            for (int j = 0; j < searchLen; j++) {
    2870                if (searchChars[j] == ch) {
    2871                    if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
    2872                        if (searchChars[j + 1] == cs.charAt(i + 1)) {
    2873                            continue outer;
    2874                        }
    2875                    } else {
    2876                        continue outer;
    2877                    }
    2878                }
    2879            }
    2880            return i;
    2881        }
    2882        return INDEX_NOT_FOUND;
    2883    }
    2884
    2885    /**
    2886     * <p>Search a CharSequence to find the first index of any
    2887     * character not in the given set of characters.</p>
    2888     *
    2889     * <p>A {@code null} CharSequence will return {@code -1}.
    2890     * A {@code null} or empty search string will return {@code -1}.</p>
    2891     *
    2892     * <pre>
    2893     * StringUtils.indexOfAnyBut(null, *)            = -1
    2894     * StringUtils.indexOfAnyBut("", *)              = -1
    2895     * StringUtils.indexOfAnyBut(*, null)            = -1
    2896     * StringUtils.indexOfAnyBut(*, "")              = -1
    2897     * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
    2898     * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
    2899     * StringUtils.indexOfAnyBut("aba", "ab")        = -1
    2900     * </pre>
    2901     *
    2902     * @param seq  the CharSequence to check, may be null
    2903     * @param searchChars  the chars to search for, may be null
    2904     * @return the index of any of the chars, -1 if no match or null input
    2905     * @since 2.0
    2906     * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
    2907     */
    2908    public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
    2909        if (isEmpty(seq) || isEmpty(searchChars)) {
    2910            return INDEX_NOT_FOUND;
    2911        }
    2912        final int strLen = seq.length();
    2913        for (int i = 0; i < strLen; i++) {
    2914            final char ch = seq.charAt(i);
    2915            final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;
    2916            if (i + 1 < strLen && Character.isHighSurrogate(ch)) {
    2917                final char ch2 = seq.charAt(i + 1);
    2918                if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {
    2919                    return i;
    2920                }
    2921            } else {
    2922                if (!chFound) {
    2923                    return i;
    2924                }
    2925            }
    2926        }
    2927        return INDEX_NOT_FOUND;
    2928    }
    2929
    2930    /**
    2931     * <p>Compares all CharSequences in an array and returns the index at which the
    2932     * CharSequences begin to differ.</p>
    2933     *
    2934     * <p>For example,
    2935     * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p>
    2936     *
    2937     * <pre>
    2938     * StringUtils.indexOfDifference(null) = -1
    2939     * StringUtils.indexOfDifference(new String[] {}) = -1
    2940     * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
    2941     * StringUtils.indexOfDifference(new String[] {null, null}) = -1
    2942     * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
    2943     * StringUtils.indexOfDifference(new String[] {"", null}) = 0
    2944     * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
    2945     * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
    2946     * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
    2947     * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
    2948     * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
    2949     * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
    2950     * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
    2951     * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
    2952     * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
    2953     * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
    2954     * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
    2955     * </pre>
    2956     *
    2957     * @param css  array of CharSequences, entries may be null
    2958     * @return the index where the strings begin to differ; -1 if they are all equal
    2959     * @since 2.4
    2960     * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
    2961     */
    2962    public static int indexOfDifference(final CharSequence... css) {
    2963        if (ArrayUtils.getLength(css) <= 1) {
    2964            return INDEX_NOT_FOUND;
    2965        }
    2966        boolean anyStringNull = false;
    2967        boolean allStringsNull = true;
    2968        final int arrayLen = css.length;
    2969        int shortestStrLen = Integer.MAX_VALUE;
    2970        int longestStrLen = 0;
    2971
    2972        // find the min and max string lengths; this avoids checking to make
    2973        // sure we are not exceeding the length of the string each time through
    2974        // the bottom loop.
    2975        for (final CharSequence cs : css) {
    2976            if (cs == null) {
    2977                anyStringNull = true;
    2978                shortestStrLen = 0;
    2979            } else {
    2980                allStringsNull = false;
    2981                shortestStrLen = Math.min(cs.length(), shortestStrLen);
    2982                longestStrLen = Math.max(cs.length(), longestStrLen);
    2983            }
    2984        }
    2985
    2986        // handle lists containing all nulls or all empty strings
    2987        if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
    2988            return INDEX_NOT_FOUND;
    2989        }
    2990
    2991        // handle lists containing some nulls or some empty strings
    2992        if (shortestStrLen == 0) {
    2993            return 0;
    2994        }
    2995
    2996        // find the position with the first difference across all strings
    2997        int firstDiff = -1;
    2998        for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
    2999            final char comparisonChar = css[0].charAt(stringPos);
    3000            for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
    3001                if (css[arrayPos].charAt(stringPos) != comparisonChar) {
    3002                    firstDiff = stringPos;
    3003                    break;
    3004                }
    3005            }
    3006            if (firstDiff != -1) {
    3007                break;
    3008            }
    3009        }
    3010
    3011        if (firstDiff == -1 && shortestStrLen != longestStrLen) {
    3012            // we compared all of the characters up to the length of the
    3013            // shortest string and didn't find a match, but the string lengths
    3014            // vary, so return the length of the shortest string.
    3015            return shortestStrLen;
    3016        }
    3017        return firstDiff;
    3018    }
    3019
    3020    /**
    3021     * <p>Compares two CharSequences, and returns the index at which the
    3022     * CharSequences begin to differ.</p>
    3023     *
    3024     * <p>For example,
    3025     * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p>
    3026     *
    3027     * <pre>
    3028     * StringUtils.indexOfDifference(null, null) = -1
    3029     * StringUtils.indexOfDifference("", "") = -1
    3030     * StringUtils.indexOfDifference("", "abc") = 0
    3031     * StringUtils.indexOfDifference("abc", "") = 0
    3032     * StringUtils.indexOfDifference("abc", "abc") = -1
    3033     * StringUtils.indexOfDifference("ab", "abxyz") = 2
    3034     * StringUtils.indexOfDifference("abcde", "abxyz") = 2
    3035     * StringUtils.indexOfDifference("abcde", "xyz") = 0
    3036     * </pre>
    3037     *
    3038     * @param cs1  the first CharSequence, may be null
    3039     * @param cs2  the second CharSequence, may be null
    3040     * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
    3041     * @since 2.0
    3042     * @since 3.0 Changed signature from indexOfDifference(String, String) to
    3043     * indexOfDifference(CharSequence, CharSequence)
    3044     */
    3045    public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
    3046        if (cs1 == cs2) {
    3047            return INDEX_NOT_FOUND;
    3048        }
    3049        if (cs1 == null || cs2 == null) {
    3050            return 0;
    3051        }
    3052        int i;
    3053        for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
    3054            if (cs1.charAt(i) != cs2.charAt(i)) {
    3055                break;
    3056            }
    3057        }
    3058        if (i < cs2.length() || i < cs1.length()) {
    3059            return i;
    3060        }
    3061        return INDEX_NOT_FOUND;
    3062    }
    3063
    3064    /**
    3065     * <p>Case in-sensitive find of the first index within a CharSequence.</p>
    3066     *
    3067     * <p>A {@code null} CharSequence will return {@code -1}.
    3068     * A negative start position is treated as zero.
    3069     * An empty ("") search CharSequence always matches.
    3070     * A start position greater than the string length only matches
    3071     * an empty search CharSequence.</p>
    3072     *
    3073     * <pre>
    3074     * StringUtils.indexOfIgnoreCase(null, *)          = -1
    3075     * StringUtils.indexOfIgnoreCase(*, null)          = -1
    3076     * StringUtils.indexOfIgnoreCase("", "")           = 0
    3077     * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
    3078     * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
    3079     * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
    3080     * </pre>
    3081     *
    3082     * @param str  the CharSequence to check, may be null
    3083     * @param searchStr  the CharSequence to find, may be null
    3084     * @return the first index of the search CharSequence,
    3085     *  -1 if no match or {@code null} string input
    3086     * @since 2.5
    3087     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
    3088     */
    3089    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    3090        return indexOfIgnoreCase(str, searchStr, 0);
    3091    }
    3092
    3093    /**
    3094     * <p>Case in-sensitive find of the first index within a CharSequence
    3095     * from the specified position.</p>
    3096     *
    3097     * <p>A {@code null} CharSequence will return {@code -1}.
    3098     * A negative start position is treated as zero.
    3099     * An empty ("") search CharSequence always matches.
    3100     * A start position greater than the string length only matches
    3101     * an empty search CharSequence.</p>
    3102     *
    3103     * <pre>
    3104     * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
    3105     * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
    3106     * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
    3107     * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    3108     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
    3109     * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
    3110     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
    3111     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
    3112     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
    3113     * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
    3114     * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1
    3115     * </pre>
    3116     *
    3117     * @param str  the CharSequence to check, may be null
    3118     * @param searchStr  the CharSequence to find, may be null
    3119     * @param startPos  the start position, negative treated as zero
    3120     * @return the first index of the search CharSequence (always &ge; startPos),
    3121     *  -1 if no match or {@code null} string input
    3122     * @since 2.5
    3123     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
    3124     */
    3125    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
    3126        if (str == null || searchStr == null) {
    3127            return INDEX_NOT_FOUND;
    3128        }
    3129        if (startPos < 0) {
    3130            startPos = 0;
    3131        }
    3132        final int endLimit = str.length() - searchStr.length() + 1;
    3133        if (startPos > endLimit) {
    3134            return INDEX_NOT_FOUND;
    3135        }
    3136        if (searchStr.length() == 0) {
    3137            return startPos;
    3138        }
    3139        for (int i = startPos; i < endLimit; i++) {
    3140            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
    3141                return i;
    3142            }
    3143        }
    3144        return INDEX_NOT_FOUND;
    3145    }
    3146
    3147    /**
    3148     * <p>Checks if all of the CharSequences are empty (""), null or whitespace only.</p>
    3149     *
    3150     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3151     *
    3152     * <pre>
    3153     * StringUtils.isAllBlank(null)             = true
    3154     * StringUtils.isAllBlank(null, "foo")      = false
    3155     * StringUtils.isAllBlank(null, null)       = true
    3156     * StringUtils.isAllBlank("", "bar")        = false
    3157     * StringUtils.isAllBlank("bob", "")        = false
    3158     * StringUtils.isAllBlank("  bob  ", null)  = false
    3159     * StringUtils.isAllBlank(" ", "bar")       = false
    3160     * StringUtils.isAllBlank("foo", "bar")     = false
    3161     * StringUtils.isAllBlank(new String[] {})  = true
    3162     * </pre>
    3163     *
    3164     * @param css  the CharSequences to check, may be null or empty
    3165     * @return {@code true} if all of the CharSequences are empty or null or whitespace only
    3166     * @since 3.6
    3167     */
    3168    public static boolean isAllBlank(final CharSequence... css) {
    3169        if (ArrayUtils.isEmpty(css)) {
    3170            return true;
    3171        }
    3172        for (final CharSequence cs : css) {
    3173            if (isNotBlank(cs)) {
    3174               return false;
    3175            }
    3176        }
    3177        return true;
    3178    }
    3179
    3180    /**
    3181     * <p>Checks if all of the CharSequences are empty ("") or null.</p>
    3182     *
    3183     * <pre>
    3184     * StringUtils.isAllEmpty(null)             = true
    3185     * StringUtils.isAllEmpty(null, "")         = true
    3186     * StringUtils.isAllEmpty(new String[] {})  = true
    3187     * StringUtils.isAllEmpty(null, "foo")      = false
    3188     * StringUtils.isAllEmpty("", "bar")        = false
    3189     * StringUtils.isAllEmpty("bob", "")        = false
    3190     * StringUtils.isAllEmpty("  bob  ", null)  = false
    3191     * StringUtils.isAllEmpty(" ", "bar")       = false
    3192     * StringUtils.isAllEmpty("foo", "bar")     = false
    3193     * </pre>
    3194     *
    3195     * @param css  the CharSequences to check, may be null or empty
    3196     * @return {@code true} if all of the CharSequences are empty or null
    3197     * @since 3.6
    3198     */
    3199    public static boolean isAllEmpty(final CharSequence... css) {
    3200        if (ArrayUtils.isEmpty(css)) {
    3201            return true;
    3202        }
    3203        for (final CharSequence cs : css) {
    3204            if (isNotEmpty(cs)) {
    3205                return false;
    3206            }
    3207        }
    3208        return true;
    3209    }
    3210
    3211    /**
    3212     * <p>Checks if the CharSequence contains only lowercase characters.</p>
    3213     *
    3214     * <p>{@code null} will return {@code false}.
    3215     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3216     *
    3217     * <pre>
    3218     * StringUtils.isAllLowerCase(null)   = false
    3219     * StringUtils.isAllLowerCase("")     = false
    3220     * StringUtils.isAllLowerCase("  ")   = false
    3221     * StringUtils.isAllLowerCase("abc")  = true
    3222     * StringUtils.isAllLowerCase("abC")  = false
    3223     * StringUtils.isAllLowerCase("ab c") = false
    3224     * StringUtils.isAllLowerCase("ab1c") = false
    3225     * StringUtils.isAllLowerCase("ab/c") = false
    3226     * </pre>
    3227     *
    3228     * @param cs  the CharSequence to check, may be null
    3229     * @return {@code true} if only contains lowercase characters, and is non-null
    3230     * @since 2.5
    3231     * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
    3232     */
    3233    public static boolean isAllLowerCase(final CharSequence cs) {
    3234        if (isEmpty(cs)) {
    3235            return false;
    3236        }
    3237        final int sz = cs.length();
    3238        for (int i = 0; i < sz; i++) {
    3239            if (!Character.isLowerCase(cs.charAt(i))) {
    3240                return false;
    3241            }
    3242        }
    3243        return true;
    3244    }
    3245
    3246    /**
    3247     * <p>Checks if the CharSequence contains only uppercase characters.</p>
    3248     *
    3249     * <p>{@code null} will return {@code false}.
    3250     * An empty String (length()=0) will return {@code false}.</p>
    3251     *
    3252     * <pre>
    3253     * StringUtils.isAllUpperCase(null)   = false
    3254     * StringUtils.isAllUpperCase("")     = false
    3255     * StringUtils.isAllUpperCase("  ")   = false
    3256     * StringUtils.isAllUpperCase("ABC")  = true
    3257     * StringUtils.isAllUpperCase("aBC")  = false
    3258     * StringUtils.isAllUpperCase("A C")  = false
    3259     * StringUtils.isAllUpperCase("A1C")  = false
    3260     * StringUtils.isAllUpperCase("A/C")  = false
    3261     * </pre>
    3262     *
    3263     * @param cs the CharSequence to check, may be null
    3264     * @return {@code true} if only contains uppercase characters, and is non-null
    3265     * @since 2.5
    3266     * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
    3267     */
    3268    public static boolean isAllUpperCase(final CharSequence cs) {
    3269        if (isEmpty(cs)) {
    3270            return false;
    3271        }
    3272        final int sz = cs.length();
    3273        for (int i = 0; i < sz; i++) {
    3274            if (!Character.isUpperCase(cs.charAt(i))) {
    3275                return false;
    3276            }
    3277        }
    3278        return true;
    3279    }
    3280
    3281    // Character Tests
    3282    //-----------------------------------------------------------------------
    3283    /**
    3284     * <p>Checks if the CharSequence contains only Unicode letters.</p>
    3285     *
    3286     * <p>{@code null} will return {@code false}.
    3287     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3288     *
    3289     * <pre>
    3290     * StringUtils.isAlpha(null)   = false
    3291     * StringUtils.isAlpha("")     = false
    3292     * StringUtils.isAlpha("  ")   = false
    3293     * StringUtils.isAlpha("abc")  = true
    3294     * StringUtils.isAlpha("ab2c") = false
    3295     * StringUtils.isAlpha("ab-c") = false
    3296     * </pre>
    3297     *
    3298     * @param cs  the CharSequence to check, may be null
    3299     * @return {@code true} if only contains letters, and is non-null
    3300     * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
    3301     * @since 3.0 Changed "" to return false and not true
    3302     */
    3303    public static boolean isAlpha(final CharSequence cs) {
    3304        if (isEmpty(cs)) {
    3305            return false;
    3306        }
    3307        final int sz = cs.length();
    3308        for (int i = 0; i < sz; i++) {
    3309            if (!Character.isLetter(cs.charAt(i))) {
    3310                return false;
    3311            }
    3312        }
    3313        return true;
    3314    }
    3315
    3316    /**
    3317     * <p>Checks if the CharSequence contains only Unicode letters or digits.</p>
    3318     *
    3319     * <p>{@code null} will return {@code false}.
    3320     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3321     *
    3322     * <pre>
    3323     * StringUtils.isAlphanumeric(null)   = false
    3324     * StringUtils.isAlphanumeric("")     = false
    3325     * StringUtils.isAlphanumeric("  ")   = false
    3326     * StringUtils.isAlphanumeric("abc")  = true
    3327     * StringUtils.isAlphanumeric("ab c") = false
    3328     * StringUtils.isAlphanumeric("ab2c") = true
    3329     * StringUtils.isAlphanumeric("ab-c") = false
    3330     * </pre>
    3331     *
    3332     * @param cs  the CharSequence to check, may be null
    3333     * @return {@code true} if only contains letters or digits,
    3334     *  and is non-null
    3335     * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
    3336     * @since 3.0 Changed "" to return false and not true
    3337     */
    3338    public static boolean isAlphanumeric(final CharSequence cs) {
    3339        if (isEmpty(cs)) {
    3340            return false;
    3341        }
    3342        final int sz = cs.length();
    3343        for (int i = 0; i < sz; i++) {
    3344            if (!Character.isLetterOrDigit(cs.charAt(i))) {
    3345                return false;
    3346            }
    3347        }
    3348        return true;
    3349    }
    3350
    3351    /**
    3352     * <p>Checks if the CharSequence contains only Unicode letters, digits
    3353     * or space ({@code ' '}).</p>
    3354     *
    3355     * <p>{@code null} will return {@code false}.
    3356     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3357     *
    3358     * <pre>
    3359     * StringUtils.isAlphanumericSpace(null)   = false
    3360     * StringUtils.isAlphanumericSpace("")     = true
    3361     * StringUtils.isAlphanumericSpace("  ")   = true
    3362     * StringUtils.isAlphanumericSpace("abc")  = true
    3363     * StringUtils.isAlphanumericSpace("ab c") = true
    3364     * StringUtils.isAlphanumericSpace("ab2c") = true
    3365     * StringUtils.isAlphanumericSpace("ab-c") = false
    3366     * </pre>
    3367     *
    3368     * @param cs  the CharSequence to check, may be null
    3369     * @return {@code true} if only contains letters, digits or space,
    3370     *  and is non-null
    3371     * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
    3372     */
    3373    public static boolean isAlphanumericSpace(final CharSequence cs) {
    3374        if (cs == null) {
    3375            return false;
    3376        }
    3377        final int sz = cs.length();
    3378        for (int i = 0; i < sz; i++) {
    3379            if (!Character.isLetterOrDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3380                return false;
    3381            }
    3382        }
    3383        return true;
    3384    }
    3385
    3386    /**
    3387     * <p>Checks if the CharSequence contains only Unicode letters and
    3388     * space (' ').</p>
    3389     *
    3390     * <p>{@code null} will return {@code false}
    3391     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3392     *
    3393     * <pre>
    3394     * StringUtils.isAlphaSpace(null)   = false
    3395     * StringUtils.isAlphaSpace("")     = true
    3396     * StringUtils.isAlphaSpace("  ")   = true
    3397     * StringUtils.isAlphaSpace("abc")  = true
    3398     * StringUtils.isAlphaSpace("ab c") = true
    3399     * StringUtils.isAlphaSpace("ab2c") = false
    3400     * StringUtils.isAlphaSpace("ab-c") = false
    3401     * </pre>
    3402     *
    3403     * @param cs  the CharSequence to check, may be null
    3404     * @return {@code true} if only contains letters and space,
    3405     *  and is non-null
    3406     * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
    3407     */
    3408    public static boolean isAlphaSpace(final CharSequence cs) {
    3409        if (cs == null) {
    3410            return false;
    3411        }
    3412        final int sz = cs.length();
    3413        for (int i = 0; i < sz; i++) {
    3414            if (!Character.isLetter(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3415                return false;
    3416            }
    3417        }
    3418        return true;
    3419    }
    3420
    3421    /**
    3422     * <p>Checks if any of the CharSequences are empty ("") or null or whitespace only.</p>
    3423     *
    3424     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3425     *
    3426     * <pre>
    3427     * StringUtils.isAnyBlank((String) null)    = true
    3428     * StringUtils.isAnyBlank((String[]) null)  = false
    3429     * StringUtils.isAnyBlank(null, "foo")      = true
    3430     * StringUtils.isAnyBlank(null, null)       = true
    3431     * StringUtils.isAnyBlank("", "bar")        = true
    3432     * StringUtils.isAnyBlank("bob", "")        = true
    3433     * StringUtils.isAnyBlank("  bob  ", null)  = true
    3434     * StringUtils.isAnyBlank(" ", "bar")       = true
    3435     * StringUtils.isAnyBlank(new String[] {})  = false
    3436     * StringUtils.isAnyBlank(new String[]{""}) = true
    3437     * StringUtils.isAnyBlank("foo", "bar")     = false
    3438     * </pre>
    3439     *
    3440     * @param css  the CharSequences to check, may be null or empty
    3441     * @return {@code true} if any of the CharSequences are empty or null or whitespace only
    3442     * @since 3.2
    3443     */
    3444    public static boolean isAnyBlank(final CharSequence... css) {
    3445      if (ArrayUtils.isEmpty(css)) {
    3446        return false;
    3447      }
    3448      for (final CharSequence cs : css) {
    3449        if (isBlank(cs)) {
    3450          return true;
    3451        }
    3452      }
    3453      return false;
    3454    }
    3455
    3456    /**
    3457     * <p>Checks if any of the CharSequences are empty ("") or null.</p>
    3458     *
    3459     * <pre>
    3460     * StringUtils.isAnyEmpty((String) null)    = true
    3461     * StringUtils.isAnyEmpty((String[]) null)  = false
    3462     * StringUtils.isAnyEmpty(null, "foo")      = true
    3463     * StringUtils.isAnyEmpty("", "bar")        = true
    3464     * StringUtils.isAnyEmpty("bob", "")        = true
    3465     * StringUtils.isAnyEmpty("  bob  ", null)  = true
    3466     * StringUtils.isAnyEmpty(" ", "bar")       = false
    3467     * StringUtils.isAnyEmpty("foo", "bar")     = false
    3468     * StringUtils.isAnyEmpty(new String[]{})   = false
    3469     * StringUtils.isAnyEmpty(new String[]{""}) = true
    3470     * </pre>
    3471     *
    3472     * @param css  the CharSequences to check, may be null or empty
    3473     * @return {@code true} if any of the CharSequences are empty or null
    3474     * @since 3.2
    3475     */
    3476    public static boolean isAnyEmpty(final CharSequence... css) {
    3477      if (ArrayUtils.isEmpty(css)) {
    3478        return false;
    3479      }
    3480      for (final CharSequence cs : css) {
    3481        if (isEmpty(cs)) {
    3482          return true;
    3483        }
    3484      }
    3485      return false;
    3486    }
    3487
    3488    /**
    3489     * <p>Checks if the CharSequence contains only ASCII printable characters.</p>
    3490     *
    3491     * <p>{@code null} will return {@code false}.
    3492     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3493     *
    3494     * <pre>
    3495     * StringUtils.isAsciiPrintable(null)     = false
    3496     * StringUtils.isAsciiPrintable("")       = true
    3497     * StringUtils.isAsciiPrintable(" ")      = true
    3498     * StringUtils.isAsciiPrintable("Ceki")   = true
    3499     * StringUtils.isAsciiPrintable("ab2c")   = true
    3500     * StringUtils.isAsciiPrintable("!ab-c~") = true
    3501     * StringUtils.isAsciiPrintable("\u0020") = true
    3502     * StringUtils.isAsciiPrintable("\u0021") = true
    3503     * StringUtils.isAsciiPrintable("\u007e") = true
    3504     * StringUtils.isAsciiPrintable("\u007f") = false
    3505     * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
    3506     * </pre>
    3507     *
    3508     * @param cs the CharSequence to check, may be null
    3509     * @return {@code true} if every character is in the range
    3510     *  32 thru 126
    3511     * @since 2.1
    3512     * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
    3513     */
    3514    public static boolean isAsciiPrintable(final CharSequence cs) {
    3515        if (cs == null) {
    3516            return false;
    3517        }
    3518        final int sz = cs.length();
    3519        for (int i = 0; i < sz; i++) {
    3520            if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
    3521                return false;
    3522            }
    3523        }
    3524        return true;
    3525    }
    3526
    3527    // Nested extraction
    3528    //-----------------------------------------------------------------------
    3529
    3530    /**
    3531     * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
    3532     *
    3533     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3534     *
    3535     * <pre>
    3536     * StringUtils.isBlank(null)      = true
    3537     * StringUtils.isBlank("")        = true
    3538     * StringUtils.isBlank(" ")       = true
    3539     * StringUtils.isBlank("bob")     = false
    3540     * StringUtils.isBlank("  bob  ") = false
    3541     * </pre>
    3542     *
    3543     * @param cs  the CharSequence to check, may be null
    3544     * @return {@code true} if the CharSequence is null, empty or whitespace only
    3545     * @since 2.0
    3546     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
    3547     */
    3548    public static boolean isBlank(final CharSequence cs) {
    3549        final int strLen = length(cs);
    3550        if (strLen == 0) {
    3551            return true;
    3552        }
    3553        for (int i = 0; i < strLen; i++) {
    3554            if (!Character.isWhitespace(cs.charAt(i))) {
    3555                return false;
    3556            }
    3557        }
    3558        return true;
    3559    }
    3560
    3561    // Empty checks
    3562    //-----------------------------------------------------------------------
    3563    /**
    3564     * <p>Checks if a CharSequence is empty ("") or null.</p>
    3565     *
    3566     * <pre>
    3567     * StringUtils.isEmpty(null)      = true
    3568     * StringUtils.isEmpty("")        = true
    3569     * StringUtils.isEmpty(" ")       = false
    3570     * StringUtils.isEmpty("bob")     = false
    3571     * StringUtils.isEmpty("  bob  ") = false
    3572     * </pre>
    3573     *
    3574     * <p>NOTE: This method changed in Lang version 2.0.
    3575     * It no longer trims the CharSequence.
    3576     * That functionality is available in isBlank().</p>
    3577     *
    3578     * @param cs  the CharSequence to check, may be null
    3579     * @return {@code true} if the CharSequence is empty or null
    3580     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
    3581     */
    3582    public static boolean isEmpty(final CharSequence cs) {
    3583        return cs == null || cs.length() == 0;
    3584    }
    3585
    3586    /**
    3587     * <p>Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.</p>
    3588     *
    3589     * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return
    3590     * {@code false}.</p>
    3591     *
    3592     * <pre>
    3593     * StringUtils.isMixedCase(null)    = false
    3594     * StringUtils.isMixedCase("")      = false
    3595     * StringUtils.isMixedCase("ABC")   = false
    3596     * StringUtils.isMixedCase("abc")   = false
    3597     * StringUtils.isMixedCase("aBc")   = true
    3598     * StringUtils.isMixedCase("A c")   = true
    3599     * StringUtils.isMixedCase("A1c")   = true
    3600     * StringUtils.isMixedCase("a/C")   = true
    3601     * StringUtils.isMixedCase("aC\t")  = true
    3602     * </pre>
    3603     *
    3604     * @param cs the CharSequence to check, may be null
    3605     * @return {@code true} if the CharSequence contains both uppercase and lowercase characters
    3606     * @since 3.5
    3607     */
    3608    public static boolean isMixedCase(final CharSequence cs) {
    3609        if (isEmpty(cs) || cs.length() == 1) {
    3610            return false;
    3611        }
    3612        boolean containsUppercase = false;
    3613        boolean containsLowercase = false;
    3614        final int sz = cs.length();
    3615        for (int i = 0; i < sz; i++) {
    3616            if (containsUppercase && containsLowercase) {
    3617                return true;
    3618            } else if (Character.isUpperCase(cs.charAt(i))) {
    3619                containsUppercase = true;
    3620            } else if (Character.isLowerCase(cs.charAt(i))) {
    3621                containsLowercase = true;
    3622            }
    3623        }
    3624        return containsUppercase && containsLowercase;
    3625    }
    3626
    3627    /**
    3628     * <p>Checks if none of the CharSequences are empty (""), null or whitespace only.</p>
    3629     *
    3630     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3631     *
    3632     * <pre>
    3633     * StringUtils.isNoneBlank((String) null)    = false
    3634     * StringUtils.isNoneBlank((String[]) null)  = true
    3635     * StringUtils.isNoneBlank(null, "foo")      = false
    3636     * StringUtils.isNoneBlank(null, null)       = false
    3637     * StringUtils.isNoneBlank("", "bar")        = false
    3638     * StringUtils.isNoneBlank("bob", "")        = false
    3639     * StringUtils.isNoneBlank("  bob  ", null)  = false
    3640     * StringUtils.isNoneBlank(" ", "bar")       = false
    3641     * StringUtils.isNoneBlank(new String[] {})  = true
    3642     * StringUtils.isNoneBlank(new String[]{""}) = false
    3643     * StringUtils.isNoneBlank("foo", "bar")     = true
    3644     * </pre>
    3645     *
    3646     * @param css  the CharSequences to check, may be null or empty
    3647     * @return {@code true} if none of the CharSequences are empty or null or whitespace only
    3648     * @since 3.2
    3649     */
    3650    public static boolean isNoneBlank(final CharSequence... css) {
    3651      return !isAnyBlank(css);
    3652    }
    3653
    3654    /**
    3655     * <p>Checks if none of the CharSequences are empty ("") or null.</p>
    3656     *
    3657     * <pre>
    3658     * StringUtils.isNoneEmpty((String) null)    = false
    3659     * StringUtils.isNoneEmpty((String[]) null)  = true
    3660     * StringUtils.isNoneEmpty(null, "foo")      = false
    3661     * StringUtils.isNoneEmpty("", "bar")        = false
    3662     * StringUtils.isNoneEmpty("bob", "")        = false
    3663     * StringUtils.isNoneEmpty("  bob  ", null)  = false
    3664     * StringUtils.isNoneEmpty(new String[] {})  = true
    3665     * StringUtils.isNoneEmpty(new String[]{""}) = false
    3666     * StringUtils.isNoneEmpty(" ", "bar")       = true
    3667     * StringUtils.isNoneEmpty("foo", "bar")     = true
    3668     * </pre>
    3669     *
    3670     * @param css  the CharSequences to check, may be null or empty
    3671     * @return {@code true} if none of the CharSequences are empty or null
    3672     * @since 3.2
    3673     */
    3674    public static boolean isNoneEmpty(final CharSequence... css) {
    3675      return !isAnyEmpty(css);
    3676    }
    3677
    3678    /**
    3679     * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
    3680     *
    3681     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3682     *
    3683     * <pre>
    3684     * StringUtils.isNotBlank(null)      = false
    3685     * StringUtils.isNotBlank("")        = false
    3686     * StringUtils.isNotBlank(" ")       = false
    3687     * StringUtils.isNotBlank("bob")     = true
    3688     * StringUtils.isNotBlank("  bob  ") = true
    3689     * </pre>
    3690     *
    3691     * @param cs  the CharSequence to check, may be null
    3692     * @return {@code true} if the CharSequence is
    3693     *  not empty and not null and not whitespace only
    3694     * @since 2.0
    3695     * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
    3696     */
    3697    public static boolean isNotBlank(final CharSequence cs) {
    3698        return !isBlank(cs);
    3699    }
    3700
    3701    /**
    3702     * <p>Checks if a CharSequence is not empty ("") and not null.</p>
    3703     *
    3704     * <pre>
    3705     * StringUtils.isNotEmpty(null)      = false
    3706     * StringUtils.isNotEmpty("")        = false
    3707     * StringUtils.isNotEmpty(" ")       = true
    3708     * StringUtils.isNotEmpty("bob")     = true
    3709     * StringUtils.isNotEmpty("  bob  ") = true
    3710     * </pre>
    3711     *
    3712     * @param cs  the CharSequence to check, may be null
    3713     * @return {@code true} if the CharSequence is not empty and not null
    3714     * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
    3715     */
    3716    public static boolean isNotEmpty(final CharSequence cs) {
    3717        return !isEmpty(cs);
    3718    }
    3719
    3720    /**
    3721     * <p>Checks if the CharSequence contains only Unicode digits.
    3722     * A decimal point is not a Unicode digit and returns false.</p>
    3723     *
    3724     * <p>{@code null} will return {@code false}.
    3725     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3726     *
    3727     * <p>Note that the method does not allow for a leading sign, either positive or negative.
    3728     * Also, if a String passes the numeric test, it may still generate a NumberFormatException
    3729     * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
    3730     * for int or long respectively.</p>
    3731     *
    3732     * <pre>
    3733     * StringUtils.isNumeric(null)   = false
    3734     * StringUtils.isNumeric("")     = false
    3735     * StringUtils.isNumeric("  ")   = false
    3736     * StringUtils.isNumeric("123")  = true
    3737     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
    3738     * StringUtils.isNumeric("12 3") = false
    3739     * StringUtils.isNumeric("ab2c") = false
    3740     * StringUtils.isNumeric("12-3") = false
    3741     * StringUtils.isNumeric("12.3") = false
    3742     * StringUtils.isNumeric("-123") = false
    3743     * StringUtils.isNumeric("+123") = false
    3744     * </pre>
    3745     *
    3746     * @param cs  the CharSequence to check, may be null
    3747     * @return {@code true} if only contains digits, and is non-null
    3748     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
    3749     * @since 3.0 Changed "" to return false and not true
    3750     */
    3751    public static boolean isNumeric(final CharSequence cs) {
    3752        if (isEmpty(cs)) {
    3753            return false;
    3754        }
    3755        final int sz = cs.length();
    3756        for (int i = 0; i < sz; i++) {
    3757            if (!Character.isDigit(cs.charAt(i))) {
    3758                return false;
    3759            }
    3760        }
    3761        return true;
    3762    }
    3763
    3764    /**
    3765     * <p>Checks if the CharSequence contains only Unicode digits or space
    3766     * ({@code ' '}).
    3767     * A decimal point is not a Unicode digit and returns false.</p>
    3768     *
    3769     * <p>{@code null} will return {@code false}.
    3770     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3771     *
    3772     * <pre>
    3773     * StringUtils.isNumericSpace(null)   = false
    3774     * StringUtils.isNumericSpace("")     = true
    3775     * StringUtils.isNumericSpace("  ")   = true
    3776     * StringUtils.isNumericSpace("123")  = true
    3777     * StringUtils.isNumericSpace("12 3") = true
    3778     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
    3779     * StringUtils.isNumeric("\u0967\u0968 \u0969")  = true
    3780     * StringUtils.isNumericSpace("ab2c") = false
    3781     * StringUtils.isNumericSpace("12-3") = false
    3782     * StringUtils.isNumericSpace("12.3") = false
    3783     * </pre>
    3784     *
    3785     * @param cs  the CharSequence to check, may be null
    3786     * @return {@code true} if only contains digits or space,
    3787     *  and is non-null
    3788     * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
    3789     */
    3790    public static boolean isNumericSpace(final CharSequence cs) {
    3791        if (cs == null) {
    3792            return false;
    3793        }
    3794        final int sz = cs.length();
    3795        for (int i = 0; i < sz; i++) {
    3796            if (!Character.isDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3797                return false;
    3798            }
    3799        }
    3800        return true;
    3801    }
    3802
    3803    /**
    3804     * <p>Checks if the CharSequence contains only whitespace.</p>
    3805     *
    3806     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3807     *
    3808     * <p>{@code null} will return {@code false}.
    3809     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3810     *
    3811     * <pre>
    3812     * StringUtils.isWhitespace(null)   = false
    3813     * StringUtils.isWhitespace("")     = true
    3814     * StringUtils.isWhitespace("  ")   = true
    3815     * StringUtils.isWhitespace("abc")  = false
    3816     * StringUtils.isWhitespace("ab2c") = false
    3817     * StringUtils.isWhitespace("ab-c") = false
    3818     * </pre>
    3819     *
    3820     * @param cs  the CharSequence to check, may be null
    3821     * @return {@code true} if only contains whitespace, and is non-null
    3822     * @since 2.0
    3823     * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
    3824     */
    3825    public static boolean isWhitespace(final CharSequence cs) {
    3826        if (cs == null) {
    3827            return false;
    3828        }
    3829        final int sz = cs.length();
    3830        for (int i = 0; i < sz; i++) {
    3831            if (!Character.isWhitespace(cs.charAt(i))) {
    3832                return false;
    3833            }
    3834        }
    3835        return true;
    3836    }
    3837
    3838    /**
    3839     * <p>
    3840     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3841     * </p>
    3842     *
    3843     * <p>
    3844     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3845     * by empty strings.
    3846     * </p>
    3847     *
    3848     * <pre>
    3849     * StringUtils.join(null, *)               = null
    3850     * StringUtils.join([], *)                 = ""
    3851     * StringUtils.join([null], *)             = ""
    3852     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3853     * StringUtils.join([1, 2, 3], null) = "123"
    3854     * </pre>
    3855     *
    3856     * @param array
    3857     *            the array of values to join together, may be null
    3858     * @param separator
    3859     *            the separator character to use
    3860     * @return the joined String, {@code null} if null array input
    3861     * @since 3.2
    3862     */
    3863    public static String join(final byte[] array, final char separator) {
    3864        if (array == null) {
    3865            return null;
    3866        }
    3867        return join(array, separator, 0, array.length);
    3868    }
    3869
    3870    /**
    3871     * <p>
    3872     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3873     * </p>
    3874     *
    3875     * <p>
    3876     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3877     * by empty strings.
    3878     * </p>
    3879     *
    3880     * <pre>
    3881     * StringUtils.join(null, *)               = null
    3882     * StringUtils.join([], *)                 = ""
    3883     * StringUtils.join([null], *)             = ""
    3884     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3885     * StringUtils.join([1, 2, 3], null) = "123"
    3886     * </pre>
    3887     *
    3888     * @param array
    3889     *            the array of values to join together, may be null
    3890     * @param separator
    3891     *            the separator character to use
    3892     * @param startIndex
    3893     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    3894     *            array
    3895     * @param endIndex
    3896     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    3897     *            the array
    3898     * @return the joined String, {@code null} if null array input
    3899     * @since 3.2
    3900     */
    3901    public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
    3902        if (array == null) {
    3903            return null;
    3904        }
    3905        final int noOfItems = endIndex - startIndex;
    3906        if (noOfItems <= 0) {
    3907            return EMPTY;
    3908        }
    3909        final StringBuilder buf = newStringBuilder(noOfItems);
    3910        buf.append(array[startIndex]);
    3911        for (int i = startIndex + 1; i < endIndex; i++) {
    3912            buf.append(separator);
    3913            buf.append(array[i]);
    3914        }
    3915        return buf.toString();
    3916    }
    3917
    3918    /**
    3919     * <p>
    3920     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3921     * </p>
    3922     *
    3923     * <p>
    3924     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3925     * by empty strings.
    3926     * </p>
    3927     *
    3928     * <pre>
    3929     * StringUtils.join(null, *)               = null
    3930     * StringUtils.join([], *)                 = ""
    3931     * StringUtils.join([null], *)             = ""
    3932     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3933     * StringUtils.join([1, 2, 3], null) = "123"
    3934     * </pre>
    3935     *
    3936     * @param array
    3937     *            the array of values to join together, may be null
    3938     * @param separator
    3939     *            the separator character to use
    3940     * @return the joined String, {@code null} if null array input
    3941     * @since 3.2
    3942     */
    3943    public static String join(final char[] array, final char separator) {
    3944        if (array == null) {
    3945            return null;
    3946        }
    3947        return join(array, separator, 0, array.length);
    3948    }
    3949
    3950    /**
    3951     * <p>
    3952     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3953     * </p>
    3954     *
    3955     * <p>
    3956     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3957     * by empty strings.
    3958     * </p>
    3959     *
    3960     * <pre>
    3961     * StringUtils.join(null, *)               = null
    3962     * StringUtils.join([], *)                 = ""
    3963     * StringUtils.join([null], *)             = ""
    3964     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3965     * StringUtils.join([1, 2, 3], null) = "123"
    3966     * </pre>
    3967     *
    3968     * @param array
    3969     *            the array of values to join together, may be null
    3970     * @param separator
    3971     *            the separator character to use
    3972     * @param startIndex
    3973     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    3974     *            array
    3975     * @param endIndex
    3976     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    3977     *            the array
    3978     * @return the joined String, {@code null} if null array input
    3979     * @since 3.2
    3980     */
    3981    public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
    3982        if (array == null) {
    3983            return null;
    3984        }
    3985        final int noOfItems = endIndex - startIndex;
    3986        if (noOfItems <= 0) {
    3987            return EMPTY;
    3988        }
    3989        final StringBuilder buf = newStringBuilder(noOfItems);
    3990        buf.append(array[startIndex]);
    3991        for (int i = startIndex + 1; i < endIndex; i++) {
    3992            buf.append(separator);
    3993            buf.append(array[i]);
    3994        }
    3995        return buf.toString();
    3996    }
    3997
    3998    /**
    3999     * <p>
    4000     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4001     * </p>
    4002     *
    4003     * <p>
    4004     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4005     * by empty strings.
    4006     * </p>
    4007     *
    4008     * <pre>
    4009     * StringUtils.join(null, *)               = null
    4010     * StringUtils.join([], *)                 = ""
    4011     * StringUtils.join([null], *)             = ""
    4012     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4013     * StringUtils.join([1, 2, 3], null) = "123"
    4014     * </pre>
    4015     *
    4016     * @param array
    4017     *            the array of values to join together, may be null
    4018     * @param separator
    4019     *            the separator character to use
    4020     * @return the joined String, {@code null} if null array input
    4021     * @since 3.2
    4022     */
    4023    public static String join(final double[] array, final char separator) {
    4024        if (array == null) {
    4025            return null;
    4026        }
    4027        return join(array, separator, 0, array.length);
    4028    }
    4029
    4030    /**
    4031     * <p>
    4032     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4033     * </p>
    4034     *
    4035     * <p>
    4036     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4037     * by empty strings.
    4038     * </p>
    4039     *
    4040     * <pre>
    4041     * StringUtils.join(null, *)               = null
    4042     * StringUtils.join([], *)                 = ""
    4043     * StringUtils.join([null], *)             = ""
    4044     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4045     * StringUtils.join([1, 2, 3], null) = "123"
    4046     * </pre>
    4047     *
    4048     * @param array
    4049     *            the array of values to join together, may be null
    4050     * @param separator
    4051     *            the separator character to use
    4052     * @param startIndex
    4053     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4054     *            array
    4055     * @param endIndex
    4056     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4057     *            the array
    4058     * @return the joined String, {@code null} if null array input
    4059     * @since 3.2
    4060     */
    4061    public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
    4062        if (array == null) {
    4063            return null;
    4064        }
    4065        final int noOfItems = endIndex - startIndex;
    4066        if (noOfItems <= 0) {
    4067            return EMPTY;
    4068        }
    4069        final StringBuilder buf = newStringBuilder(noOfItems);
    4070        buf.append(array[startIndex]);
    4071        for (int i = startIndex + 1; i < endIndex; i++) {
    4072            buf.append(separator);
    4073            buf.append(array[i]);
    4074        }
    4075        return buf.toString();
    4076    }
    4077
    4078    /**
    4079     * <p>
    4080     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4081     * </p>
    4082     *
    4083     * <p>
    4084     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4085     * by empty strings.
    4086     * </p>
    4087     *
    4088     * <pre>
    4089     * StringUtils.join(null, *)               = null
    4090     * StringUtils.join([], *)                 = ""
    4091     * StringUtils.join([null], *)             = ""
    4092     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4093     * StringUtils.join([1, 2, 3], null) = "123"
    4094     * </pre>
    4095     *
    4096     * @param array
    4097     *            the array of values to join together, may be null
    4098     * @param separator
    4099     *            the separator character to use
    4100     * @return the joined String, {@code null} if null array input
    4101     * @since 3.2
    4102     */
    4103    public static String join(final float[] array, final char separator) {
    4104        if (array == null) {
    4105            return null;
    4106        }
    4107        return join(array, separator, 0, array.length);
    4108    }
    4109
    4110    /**
    4111     * <p>
    4112     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4113     * </p>
    4114     *
    4115     * <p>
    4116     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4117     * by empty strings.
    4118     * </p>
    4119     *
    4120     * <pre>
    4121     * StringUtils.join(null, *)               = null
    4122     * StringUtils.join([], *)                 = ""
    4123     * StringUtils.join([null], *)             = ""
    4124     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4125     * StringUtils.join([1, 2, 3], null) = "123"
    4126     * </pre>
    4127     *
    4128     * @param array
    4129     *            the array of values to join together, may be null
    4130     * @param separator
    4131     *            the separator character to use
    4132     * @param startIndex
    4133     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4134     *            array
    4135     * @param endIndex
    4136     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4137     *            the array
    4138     * @return the joined String, {@code null} if null array input
    4139     * @since 3.2
    4140     */
    4141    public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
    4142        if (array == null) {
    4143            return null;
    4144        }
    4145        final int noOfItems = endIndex - startIndex;
    4146        if (noOfItems <= 0) {
    4147            return EMPTY;
    4148        }
    4149        final StringBuilder buf = newStringBuilder(noOfItems);
    4150        buf.append(array[startIndex]);
    4151        for (int i = startIndex + 1; i < endIndex; i++) {
    4152            buf.append(separator);
    4153            buf.append(array[i]);
    4154        }
    4155        return buf.toString();
    4156    }
    4157
    4158    /**
    4159     * <p>
    4160     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4161     * </p>
    4162     *
    4163     * <p>
    4164     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4165     * by empty strings.
    4166     * </p>
    4167     *
    4168     * <pre>
    4169     * StringUtils.join(null, *)               = null
    4170     * StringUtils.join([], *)                 = ""
    4171     * StringUtils.join([null], *)             = ""
    4172     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4173     * StringUtils.join([1, 2, 3], null) = "123"
    4174     * </pre>
    4175     *
    4176     * @param array
    4177     *            the array of values to join together, may be null
    4178     * @param separator
    4179     *            the separator character to use
    4180     * @return the joined String, {@code null} if null array input
    4181     * @since 3.2
    4182     */
    4183    public static String join(final int[] array, final char separator) {
    4184        if (array == null) {
    4185            return null;
    4186        }
    4187        return join(array, separator, 0, array.length);
    4188    }
    4189
    4190    /**
    4191     * <p>
    4192     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4193     * </p>
    4194     *
    4195     * <p>
    4196     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4197     * by empty strings.
    4198     * </p>
    4199     *
    4200     * <pre>
    4201     * StringUtils.join(null, *)               = null
    4202     * StringUtils.join([], *)                 = ""
    4203     * StringUtils.join([null], *)             = ""
    4204     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4205     * StringUtils.join([1, 2, 3], null) = "123"
    4206     * </pre>
    4207     *
    4208     * @param array
    4209     *            the array of values to join together, may be null
    4210     * @param separator
    4211     *            the separator character to use
    4212     * @param startIndex
    4213     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4214     *            array
    4215     * @param endIndex
    4216     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4217     *            the array
    4218     * @return the joined String, {@code null} if null array input
    4219     * @since 3.2
    4220     */
    4221    public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
    4222        if (array == null) {
    4223            return null;
    4224        }
    4225        final int noOfItems = endIndex - startIndex;
    4226        if (noOfItems <= 0) {
    4227            return EMPTY;
    4228        }
    4229        final StringBuilder buf = newStringBuilder(noOfItems);
    4230        buf.append(array[startIndex]);
    4231        for (int i = startIndex + 1; i < endIndex; i++) {
    4232            buf.append(separator);
    4233            buf.append(array[i]);
    4234        }
    4235        return buf.toString();
    4236    }
    4237
    4238    /**
    4239     * <p>Joins the elements of the provided {@code Iterable} into
    4240     * a single String containing the provided elements.</p>
    4241     *
    4242     * <p>No delimiter is added before or after the list. Null objects or empty
    4243     * strings within the iteration are represented by empty strings.</p>
    4244     *
    4245     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    4246     *
    4247     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    4248     * @param separator  the separator character to use
    4249     * @return the joined String, {@code null} if null iterator input
    4250     * @since 2.3
    4251     */
    4252    public static String join(final Iterable<?> iterable, final char separator) {
    4253        if (iterable == null) {
    4254            return null;
    4255        }
    4256        return join(iterable.iterator(), separator);
    4257    }
    4258
    4259    /**
    4260     * <p>Joins the elements of the provided {@code Iterable} into
    4261     * a single String containing the provided elements.</p>
    4262     *
    4263     * <p>No delimiter is added before or after the list.
    4264     * A {@code null} separator is the same as an empty String ("").</p>
    4265     *
    4266     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    4267     *
    4268     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    4269     * @param separator  the separator character to use, null treated as ""
    4270     * @return the joined String, {@code null} if null iterator input
    4271     * @since 2.3
    4272     */
    4273    public static String join(final Iterable<?> iterable, final String separator) {
    4274        if (iterable == null) {
    4275            return null;
    4276        }
    4277        return join(iterable.iterator(), separator);
    4278    }
    4279
    4280    /**
    4281     * <p>Joins the elements of the provided {@code Iterator} into
    4282     * a single String containing the provided elements.</p>
    4283     *
    4284     * <p>No delimiter is added before or after the list. Null objects or empty
    4285     * strings within the iteration are represented by empty strings.</p>
    4286     *
    4287     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    4288     *
    4289     * @param iterator  the {@code Iterator} of values to join together, may be null
    4290     * @param separator  the separator character to use
    4291     * @return the joined String, {@code null} if null iterator input
    4292     * @since 2.0
    4293     */
    4294    public static String join(final Iterator<?> iterator, final char separator) {
    4295
    4296        // handle null, zero and one elements before building a buffer
    4297        if (iterator == null) {
    4298            return null;
    4299        }
    4300        if (!iterator.hasNext()) {
    4301            return EMPTY;
    4302        }
    4303        final Object first = iterator.next();
    4304        if (!iterator.hasNext()) {
    4305            return Objects.toString(first, EMPTY);
    4306        }
    4307
    4308        // two or more elements
    4309        final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
    4310        if (first != null) {
    4311            buf.append(first);
    4312        }
    4313
    4314        while (iterator.hasNext()) {
    4315            buf.append(separator);
    4316            final Object obj = iterator.next();
    4317            if (obj != null) {
    4318                buf.append(obj);
    4319            }
    4320        }
    4321
    4322        return buf.toString();
    4323    }
    4324
    4325    /**
    4326     * <p>Joins the elements of the provided {@code Iterator} into
    4327     * a single String containing the provided elements.</p>
    4328     *
    4329     * <p>No delimiter is added before or after the list.
    4330     * A {@code null} separator is the same as an empty String ("").</p>
    4331     *
    4332     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    4333     *
    4334     * @param iterator  the {@code Iterator} of values to join together, may be null
    4335     * @param separator  the separator character to use, null treated as ""
    4336     * @return the joined String, {@code null} if null iterator input
    4337     */
    4338    public static String join(final Iterator<?> iterator, final String separator) {
    4339
    4340        // handle null, zero and one elements before building a buffer
    4341        if (iterator == null) {
    4342            return null;
    4343        }
    4344        if (!iterator.hasNext()) {
    4345            return EMPTY;
    4346        }
    4347        final Object first = iterator.next();
    4348        if (!iterator.hasNext()) {
    4349            return Objects.toString(first, "");
    4350        }
    4351
    4352        // two or more elements
    4353        final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
    4354        if (first != null) {
    4355            buf.append(first);
    4356        }
    4357
    4358        while (iterator.hasNext()) {
    4359            if (separator != null) {
    4360                buf.append(separator);
    4361            }
    4362            final Object obj = iterator.next();
    4363            if (obj != null) {
    4364                buf.append(obj);
    4365            }
    4366        }
    4367        return buf.toString();
    4368    }
    4369
    4370    /**
    4371     * <p>Joins the elements of the provided {@code List} into a single String
    4372     * containing the provided list of elements.</p>
    4373     *
    4374     * <p>No delimiter is added before or after the list.
    4375     * Null objects or empty strings within the array are represented by
    4376     * empty strings.</p>
    4377     *
    4378     * <pre>
    4379     * StringUtils.join(null, *)               = null
    4380     * StringUtils.join([], *)                 = ""
    4381     * StringUtils.join([null], *)             = ""
    4382     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4383     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4384     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4385     * </pre>
    4386     *
    4387     * @param list  the {@code List} of values to join together, may be null
    4388     * @param separator  the separator character to use
    4389     * @param startIndex the first index to start joining from.  It is
    4390     * an error to pass in a start index past the end of the list
    4391     * @param endIndex the index to stop joining from (exclusive). It is
    4392     * an error to pass in an end index past the end of the list
    4393     * @return the joined String, {@code null} if null list input
    4394     * @since 3.8
    4395     */
    4396    public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
    4397        if (list == null) {
    4398            return null;
    4399        }
    4400        final int noOfItems = endIndex - startIndex;
    4401        if (noOfItems <= 0) {
    4402            return EMPTY;
    4403        }
    4404        final List<?> subList = list.subList(startIndex, endIndex);
    4405        return join(subList.iterator(), separator);
    4406    }
    4407
    4408    /**
    4409     * <p>Joins the elements of the provided {@code List} into a single String
    4410     * containing the provided list of elements.</p>
    4411     *
    4412     * <p>No delimiter is added before or after the list.
    4413     * Null objects or empty strings within the array are represented by
    4414     * empty strings.</p>
    4415     *
    4416     * <pre>
    4417     * StringUtils.join(null, *)               = null
    4418     * StringUtils.join([], *)                 = ""
    4419     * StringUtils.join([null], *)             = ""
    4420     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4421     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4422     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4423     * </pre>
    4424     *
    4425     * @param list  the {@code List} of values to join together, may be null
    4426     * @param separator  the separator character to use
    4427     * @param startIndex the first index to start joining from.  It is
    4428     * an error to pass in a start index past the end of the list
    4429     * @param endIndex the index to stop joining from (exclusive). It is
    4430     * an error to pass in an end index past the end of the list
    4431     * @return the joined String, {@code null} if null list input
    4432     * @since 3.8
    4433     */
    4434    public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
    4435        if (list == null) {
    4436            return null;
    4437        }
    4438        final int noOfItems = endIndex - startIndex;
    4439        if (noOfItems <= 0) {
    4440            return EMPTY;
    4441        }
    4442        final List<?> subList = list.subList(startIndex, endIndex);
    4443        return join(subList.iterator(), separator);
    4444    }
    4445
    4446
    4447    /**
    4448     * <p>
    4449     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4450     * </p>
    4451     *
    4452     * <p>
    4453     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4454     * by empty strings.
    4455     * </p>
    4456     *
    4457     * <pre>
    4458     * StringUtils.join(null, *)               = null
    4459     * StringUtils.join([], *)                 = ""
    4460     * StringUtils.join([null], *)             = ""
    4461     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4462     * StringUtils.join([1, 2, 3], null) = "123"
    4463     * </pre>
    4464     *
    4465     * @param array
    4466     *            the array of values to join together, may be null
    4467     * @param separator
    4468     *            the separator character to use
    4469     * @return the joined String, {@code null} if null array input
    4470     * @since 3.2
    4471     */
    4472    public static String join(final long[] array, final char separator) {
    4473        if (array == null) {
    4474            return null;
    4475        }
    4476        return join(array, separator, 0, array.length);
    4477    }
    4478
    4479    /**
    4480     * <p>
    4481     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4482     * </p>
    4483     *
    4484     * <p>
    4485     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4486     * by empty strings.
    4487     * </p>
    4488     *
    4489     * <pre>
    4490     * StringUtils.join(null, *)               = null
    4491     * StringUtils.join([], *)                 = ""
    4492     * StringUtils.join([null], *)             = ""
    4493     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4494     * StringUtils.join([1, 2, 3], null) = "123"
    4495     * </pre>
    4496     *
    4497     * @param array
    4498     *            the array of values to join together, may be null
    4499     * @param separator
    4500     *            the separator character to use
    4501     * @param startIndex
    4502     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4503     *            array
    4504     * @param endIndex
    4505     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4506     *            the array
    4507     * @return the joined String, {@code null} if null array input
    4508     * @since 3.2
    4509     */
    4510    public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
    4511        if (array == null) {
    4512            return null;
    4513        }
    4514        final int noOfItems = endIndex - startIndex;
    4515        if (noOfItems <= 0) {
    4516            return EMPTY;
    4517        }
    4518        final StringBuilder buf = newStringBuilder(noOfItems);
    4519        buf.append(array[startIndex]);
    4520        for (int i = startIndex + 1; i < endIndex; i++) {
    4521            buf.append(separator);
    4522            buf.append(array[i]);
    4523        }
    4524        return buf.toString();
    4525    }
    4526
    4527    /**
    4528     * <p>Joins the elements of the provided array into a single String
    4529     * containing the provided list of elements.</p>
    4530     *
    4531     * <p>No delimiter is added before or after the list.
    4532     * Null objects or empty strings within the array are represented by
    4533     * empty strings.</p>
    4534     *
    4535     * <pre>
    4536     * StringUtils.join(null, *)               = null
    4537     * StringUtils.join([], *)                 = ""
    4538     * StringUtils.join([null], *)             = ""
    4539     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4540     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4541     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4542     * </pre>
    4543     *
    4544     * @param array  the array of values to join together, may be null
    4545     * @param separator  the separator character to use
    4546     * @return the joined String, {@code null} if null array input
    4547     * @since 2.0
    4548     */
    4549    public static String join(final Object[] array, final char separator) {
    4550        if (array == null) {
    4551            return null;
    4552        }
    4553        return join(array, separator, 0, array.length);
    4554    }
    4555
    4556    /**
    4557     * <p>Joins the elements of the provided array into a single String
    4558     * containing the provided list of elements.</p>
    4559     *
    4560     * <p>No delimiter is added before or after the list.
    4561     * Null objects or empty strings within the array are represented by
    4562     * empty strings.</p>
    4563     *
    4564     * <pre>
    4565     * StringUtils.join(null, *)               = null
    4566     * StringUtils.join([], *)                 = ""
    4567     * StringUtils.join([null], *)             = ""
    4568     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4569     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4570     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4571     * </pre>
    4572     *
    4573     * @param array  the array of values to join together, may be null
    4574     * @param separator  the separator character to use
    4575     * @param startIndex the first index to start joining from.  It is
    4576     * an error to pass in a start index past the end of the array
    4577     * @param endIndex the index to stop joining from (exclusive). It is
    4578     * an error to pass in an end index past the end of the array
    4579     * @return the joined String, {@code null} if null array input
    4580     * @since 2.0
    4581     */
    4582    public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
    4583        if (array == null) {
    4584            return null;
    4585        }
    4586        final int noOfItems = endIndex - startIndex;
    4587        if (noOfItems <= 0) {
    4588            return EMPTY;
    4589        }
    4590        final StringBuilder buf = newStringBuilder(noOfItems);
    4591        if (array[startIndex] != null) {
    4592            buf.append(array[startIndex]);
    4593        }
    4594        for (int i = startIndex + 1; i < endIndex; i++) {
    4595            buf.append(separator);
    4596            if (array[i] != null) {
    4597                buf.append(array[i]);
    4598            }
    4599        }
    4600        return buf.toString();
    4601    }
    4602
    4603    /**
    4604     * <p>Joins the elements of the provided array into a single String
    4605     * containing the provided list of elements.</p>
    4606     *
    4607     * <p>No delimiter is added before or after the list.
    4608     * A {@code null} separator is the same as an empty String ("").
    4609     * Null objects or empty strings within the array are represented by
    4610     * empty strings.</p>
    4611     *
    4612     * <pre>
    4613     * StringUtils.join(null, *)                = null
    4614     * StringUtils.join([], *)                  = ""
    4615     * StringUtils.join([null], *)              = ""
    4616     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    4617     * StringUtils.join(["a", "b", "c"], null)  = "abc"
    4618     * StringUtils.join(["a", "b", "c"], "")    = "abc"
    4619     * StringUtils.join([null, "", "a"], ',')   = ",,a"
    4620     * </pre>
    4621     *
    4622     * @param array  the array of values to join together, may be null
    4623     * @param separator  the separator character to use, null treated as ""
    4624     * @return the joined String, {@code null} if null array input
    4625     */
    4626    public static String join(final Object[] array, final String separator) {
    4627        if (array == null) {
    4628            return null;
    4629        }
    4630        return join(array, separator, 0, array.length);
    4631    }
    4632
    4633    /**
    4634     * <p>Joins the elements of the provided array into a single String
    4635     * containing the provided list of elements.</p>
    4636     *
    4637     * <p>No delimiter is added before or after the list.
    4638     * A {@code null} separator is the same as an empty String ("").
    4639     * Null objects or empty strings within the array are represented by
    4640     * empty strings.</p>
    4641     *
    4642     * <pre>
    4643     * StringUtils.join(null, *, *, *)                = null
    4644     * StringUtils.join([], *, *, *)                  = ""
    4645     * StringUtils.join([null], *, *, *)              = ""
    4646     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
    4647     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
    4648     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
    4649     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
    4650     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
    4651     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
    4652     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
    4653     * </pre>
    4654     *
    4655     * @param array  the array of values to join together, may be null
    4656     * @param separator  the separator character to use, null treated as ""
    4657     * @param startIndex the first index to start joining from.
    4658     * @param endIndex the index to stop joining from (exclusive).
    4659     * @return the joined String, {@code null} if null array input; or the empty string
    4660     * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
    4661     * {@code endIndex - startIndex}
    4662     * @throws ArrayIndexOutOfBoundsException ife<br>
    4663     * {@code startIndex < 0} or <br>
    4664     * {@code startIndex >= array.length()} or <br>
    4665     * {@code endIndex < 0} or <br>
    4666     * {@code endIndex > array.length()}
    4667     */
    4668    public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
    4669        if (array == null) {
    4670            return null;
    4671        }
    4672        if (separator == null) {
    4673            separator = EMPTY;
    4674        }
    4675
    4676        // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    4677        //           (Assuming that all Strings are roughly equally long)
    4678        final int noOfItems = endIndex - startIndex;
    4679        if (noOfItems <= 0) {
    4680            return EMPTY;
    4681        }
    4682
    4683        final StringBuilder buf = newStringBuilder(noOfItems);
    4684
    4685        if (array[startIndex] != null) {
    4686            buf.append(array[startIndex]);
    4687        }
    4688
    4689        for (int i = startIndex + 1; i < endIndex; i++) {
    4690            buf.append(separator);
    4691
    4692            if (array[i] != null) {
    4693                buf.append(array[i]);
    4694            }
    4695        }
    4696        return buf.toString();
    4697    }
    4698
    4699    /**
    4700     * <p>
    4701     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4702     * </p>
    4703     *
    4704     * <p>
    4705     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4706     * by empty strings.
    4707     * </p>
    4708     *
    4709     * <pre>
    4710     * StringUtils.join(null, *)               = null
    4711     * StringUtils.join([], *)                 = ""
    4712     * StringUtils.join([null], *)             = ""
    4713     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4714     * StringUtils.join([1, 2, 3], null) = "123"
    4715     * </pre>
    4716     *
    4717     * @param array
    4718     *            the array of values to join together, may be null
    4719     * @param separator
    4720     *            the separator character to use
    4721     * @return the joined String, {@code null} if null array input
    4722     * @since 3.2
    4723     */
    4724    public static String join(final short[] array, final char separator) {
    4725        if (array == null) {
    4726            return null;
    4727        }
    4728        return join(array, separator, 0, array.length);
    4729    }
    4730
    4731    /**
    4732     * <p>
    4733     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4734     * </p>
    4735     *
    4736     * <p>
    4737     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4738     * by empty strings.
    4739     * </p>
    4740     *
    4741     * <pre>
    4742     * StringUtils.join(null, *)               = null
    4743     * StringUtils.join([], *)                 = ""
    4744     * StringUtils.join([null], *)             = ""
    4745     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4746     * StringUtils.join([1, 2, 3], null) = "123"
    4747     * </pre>
    4748     *
    4749     * @param array
    4750     *            the array of values to join together, may be null
    4751     * @param separator
    4752     *            the separator character to use
    4753     * @param startIndex
    4754     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4755     *            array
    4756     * @param endIndex
    4757     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4758     *            the array
    4759     * @return the joined String, {@code null} if null array input
    4760     * @since 3.2
    4761     */
    4762    public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
    4763        if (array == null) {
    4764            return null;
    4765        }
    4766        final int noOfItems = endIndex - startIndex;
    4767        if (noOfItems <= 0) {
    4768            return EMPTY;
    4769        }
    4770        final StringBuilder buf = newStringBuilder(noOfItems);
    4771        buf.append(array[startIndex]);
    4772        for (int i = startIndex + 1; i < endIndex; i++) {
    4773            buf.append(separator);
    4774            buf.append(array[i]);
    4775        }
    4776        return buf.toString();
    4777    }
    4778
    4779
    4780    // Joining
    4781    //-----------------------------------------------------------------------
    4782    /**
    4783     * <p>Joins the elements of the provided array into a single String
    4784     * containing the provided list of elements.</p>
    4785     *
    4786     * <p>No separator is added to the joined String.
    4787     * Null objects or empty strings within the array are represented by
    4788     * empty strings.</p>
    4789     *
    4790     * <pre>
    4791     * StringUtils.join(null)            = null
    4792     * StringUtils.join([])              = ""
    4793     * StringUtils.join([null])          = ""
    4794     * StringUtils.join(["a", "b", "c"]) = "abc"
    4795     * StringUtils.join([null, "", "a"]) = "a"
    4796     * </pre>
    4797     *
    4798     * @param <T> the specific type of values to join together
    4799     * @param elements  the values to join together, may be null
    4800     * @return the joined String, {@code null} if null array input
    4801     * @since 2.0
    4802     * @since 3.0 Changed signature to use varargs
    4803     */
    4804    @SafeVarargs
    4805    public static <T> String join(final T... elements) {
    4806        return join(elements, null);
    4807    }
    4808
    4809    /**
    4810     * <p>Joins the elements of the provided varargs into a
    4811     * single String containing the provided elements.</p>
    4812     *
    4813     * <p>No delimiter is added before or after the list.
    4814     * {@code null} elements and separator are treated as empty Strings ("").</p>
    4815     *
    4816     * <pre>
    4817     * StringUtils.joinWith(",", {"a", "b"})        = "a,b"
    4818     * StringUtils.joinWith(",", {"a", "b",""})     = "a,b,"
    4819     * StringUtils.joinWith(",", {"a", null, "b"})  = "a,,b"
    4820     * StringUtils.joinWith(null, {"a", "b"})       = "ab"
    4821     * </pre>
    4822     *
    4823     * @param separator the separator character to use, null treated as ""
    4824     * @param objects the varargs providing the values to join together. {@code null} elements are treated as ""
    4825     * @return the joined String.
    4826     * @throws java.lang.IllegalArgumentException if a null varargs is provided
    4827     * @since 3.5
    4828     */
    4829    public static String joinWith(final String separator, final Object... objects) {
    4830        if (objects == null) {
    4831            throw new IllegalArgumentException("Object varargs must not be null");
    4832        }
    4833
    4834        final String sanitizedSeparator = defaultString(separator);
    4835
    4836        final StringBuilder result = new StringBuilder();
    4837
    4838        final Iterator<Object> iterator = Arrays.asList(objects).iterator();
    4839        while (iterator.hasNext()) {
    4840            final String value = Objects.toString(iterator.next(), "");
    4841            result.append(value);
    4842
    4843            if (iterator.hasNext()) {
    4844                result.append(sanitizedSeparator);
    4845            }
    4846        }
    4847
    4848        return result.toString();
    4849    }
    4850
    4851    /**
    4852     * <p>Finds the last index within a CharSequence, handling {@code null}.
    4853     * This method uses {@link String#lastIndexOf(String)} if possible.</p>
    4854     *
    4855     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    4856     *
    4857     * <pre>
    4858     * StringUtils.lastIndexOf(null, *)          = -1
    4859     * StringUtils.lastIndexOf(*, null)          = -1
    4860     * StringUtils.lastIndexOf("", "")           = 0
    4861     * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
    4862     * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
    4863     * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
    4864     * StringUtils.lastIndexOf("aabaabaa", "")   = 8
    4865     * </pre>
    4866     *
    4867     * @param seq  the CharSequence to check, may be null
    4868     * @param searchSeq  the CharSequence to find, may be null
    4869     * @return the last index of the search String,
    4870     *  -1 if no match or {@code null} string input
    4871     * @since 2.0
    4872     * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
    4873     */
    4874    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
    4875        if (seq == null || searchSeq == null) {
    4876            return INDEX_NOT_FOUND;
    4877        }
    4878        return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());
    4879    }
    4880
    4881    /**
    4882     * <p>Finds the last index within a CharSequence, handling {@code null}.
    4883     * This method uses {@link String#lastIndexOf(String, int)} if possible.</p>
    4884     *
    4885     * <p>A {@code null} CharSequence will return {@code -1}.
    4886     * A negative start position returns {@code -1}.
    4887     * An empty ("") search CharSequence always matches unless the start position is negative.
    4888     * A start position greater than the string length searches the whole string.
    4889     * The search starts at the startPos and works backwards; matches starting after the start
    4890     * position are ignored.
    4891     * </p>
    4892     *
    4893     * <pre>
    4894     * StringUtils.lastIndexOf(null, *, *)          = -1
    4895     * StringUtils.lastIndexOf(*, null, *)          = -1
    4896     * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
    4897     * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
    4898     * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
    4899     * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
    4900     * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
    4901     * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
    4902     * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
    4903     * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1
    4904     * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2
    4905     * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2
    4906     * </pre>
    4907     *
    4908     * @param seq  the CharSequence to check, may be null
    4909     * @param searchSeq  the CharSequence to find, may be null
    4910     * @param startPos  the start position, negative treated as zero
    4911     * @return the last index of the search CharSequence (always &le; startPos),
    4912     *  -1 if no match or {@code null} string input
    4913     * @since 2.0
    4914     * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
    4915     */
    4916    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
    4917        if (seq == null || searchSeq == null) {
    4918            return INDEX_NOT_FOUND;
    4919        }
    4920        return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);
    4921    }
    4922
    4923    // LastIndexOf
    4924    //-----------------------------------------------------------------------
    4925    /**
    4926     * Returns the index within {@code seq} of the last occurrence of
    4927     * the specified character. For values of {@code searchChar} in the
    4928     * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
    4929     * units) returned is the largest value <i>k</i> such that:
    4930     * <blockquote><pre>
    4931     * this.charAt(<i>k</i>) == searchChar
    4932     * </pre></blockquote>
    4933     * is true. For other values of {@code searchChar}, it is the
    4934     * largest value <i>k</i> such that:
    4935     * <blockquote><pre>
    4936     * this.codePointAt(<i>k</i>) == searchChar
    4937     * </pre></blockquote>
    4938     * is true.  In either case, if no such character occurs in this
    4939     * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
    4940     * {@code CharSequence} will return {@code -1}. The
    4941     * {@code seq} {@code CharSequence} object is searched backwards
    4942     * starting at the last character.
    4943     *
    4944     * <pre>
    4945     * StringUtils.lastIndexOf(null, *)         = -1
    4946     * StringUtils.lastIndexOf("", *)           = -1
    4947     * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
    4948     * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
    4949     * </pre>
    4950     *
    4951     * @param seq  the {@code CharSequence} to check, may be null
    4952     * @param searchChar  the character to find
    4953     * @return the last index of the search character,
    4954     *  -1 if no match or {@code null} string input
    4955     * @since 2.0
    4956     * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
    4957     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    4958     */
    4959    public static int lastIndexOf(final CharSequence seq, final int searchChar) {
    4960        if (isEmpty(seq)) {
    4961            return INDEX_NOT_FOUND;
    4962        }
    4963        return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
    4964    }
    4965
    4966    /**
    4967     * Returns the index within {@code seq} of the last occurrence of
    4968     * the specified character, searching backward starting at the
    4969     * specified index. For values of {@code searchChar} in the range
    4970     * from 0 to 0xFFFF (inclusive), the index returned is the largest
    4971     * value <i>k</i> such that:
    4972     * <blockquote><pre>
    4973     * (this.charAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &lt;= startPos)
    4974     * </pre></blockquote>
    4975     * is true. For other values of {@code searchChar}, it is the
    4976     * largest value <i>k</i> such that:
    4977     * <blockquote><pre>
    4978     * (this.codePointAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &lt;= startPos)
    4979     * </pre></blockquote>
    4980     * is true. In either case, if no such character occurs in {@code seq}
    4981     * at or before position {@code startPos}, then
    4982     * {@code -1} is returned. Furthermore, a {@code null} or empty ("")
    4983     * {@code CharSequence} will return {@code -1}. A start position greater
    4984     * than the string length searches the whole string.
    4985     * The search starts at the {@code startPos} and works backwards;
    4986     * matches starting after the start position are ignored.
    4987     *
    4988     * <p>All indices are specified in {@code char} values
    4989     * (Unicode code units).
    4990     *
    4991     * <pre>
    4992     * StringUtils.lastIndexOf(null, *, *)          = -1
    4993     * StringUtils.lastIndexOf("", *,  *)           = -1
    4994     * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
    4995     * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
    4996     * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
    4997     * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
    4998     * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
    4999     * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
    5000     * </pre>
    5001     *
    5002     * @param seq  the CharSequence to check, may be null
    5003     * @param searchChar  the character to find
    5004     * @param startPos  the start position
    5005     * @return the last index of the search character (always &le; startPos),
    5006     *  -1 if no match or {@code null} string input
    5007     * @since 2.0
    5008     * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
    5009     */
    5010    public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
    5011        if (isEmpty(seq)) {
    5012            return INDEX_NOT_FOUND;
    5013        }
    5014        return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
    5015    }
    5016
    5017    /**
    5018     * <p>Find the latest index of any of a set of potential substrings.</p>
    5019     *
    5020     * <p>A {@code null} CharSequence will return {@code -1}.
    5021     * A {@code null} search array will return {@code -1}.
    5022     * A {@code null} or zero length search array entry will be ignored,
    5023     * but a search array containing "" will return the length of {@code str}
    5024     * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p>
    5025     *
    5026     * <pre>
    5027     * StringUtils.lastIndexOfAny(null, *)                    = -1
    5028     * StringUtils.lastIndexOfAny(*, null)                    = -1
    5029     * StringUtils.lastIndexOfAny(*, [])                      = -1
    5030     * StringUtils.lastIndexOfAny(*, [null])                  = -1
    5031     * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
    5032     * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
    5033     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
    5034     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
    5035     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""])   = 10
    5036     * </pre>
    5037     *
    5038     * @param str  the CharSequence to check, may be null
    5039     * @param searchStrs  the CharSequences to search for, may be null
    5040     * @return the last index of any of the CharSequences, -1 if no match
    5041     * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
    5042     */
    5043    public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
    5044        if (str == null || searchStrs == null) {
    5045            return INDEX_NOT_FOUND;
    5046        }
    5047        int ret = INDEX_NOT_FOUND;
    5048        int tmp = 0;
    5049        for (final CharSequence search : searchStrs) {
    5050            if (search == null) {
    5051                continue;
    5052            }
    5053            tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
    5054            if (tmp > ret) {
    5055                ret = tmp;
    5056            }
    5057        }
    5058        return ret;
    5059    }
    5060
    5061    /**
    5062     * <p>Case in-sensitive find of the last index within a CharSequence.</p>
    5063     *
    5064     * <p>A {@code null} CharSequence will return {@code -1}.
    5065     * A negative start position returns {@code -1}.
    5066     * An empty ("") search CharSequence always matches unless the start position is negative.
    5067     * A start position greater than the string length searches the whole string.</p>
    5068     *
    5069     * <pre>
    5070     * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
    5071     * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
    5072     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
    5073     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
    5074     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
    5075     * </pre>
    5076     *
    5077     * @param str  the CharSequence to check, may be null
    5078     * @param searchStr  the CharSequence to find, may be null
    5079     * @return the first index of the search CharSequence,
    5080     *  -1 if no match or {@code null} string input
    5081     * @since 2.5
    5082     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
    5083     */
    5084    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    5085        if (str == null || searchStr == null) {
    5086            return INDEX_NOT_FOUND;
    5087        }
    5088        return lastIndexOfIgnoreCase(str, searchStr, str.length());
    5089    }
    5090
    5091    /**
    5092     * <p>Case in-sensitive find of the last index within a CharSequence
    5093     * from the specified position.</p>
    5094     *
    5095     * <p>A {@code null} CharSequence will return {@code -1}.
    5096     * A negative start position returns {@code -1}.
    5097     * An empty ("") search CharSequence always matches unless the start position is negative.
    5098     * A start position greater than the string length searches the whole string.
    5099     * The search starts at the startPos and works backwards; matches starting after the start
    5100     * position are ignored.
    5101     * </p>
    5102     *
    5103     * <pre>
    5104     * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
    5105     * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
    5106     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
    5107     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
    5108     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
    5109     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
    5110     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
    5111     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    5112     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
    5113     * </pre>
    5114     *
    5115     * @param str  the CharSequence to check, may be null
    5116     * @param searchStr  the CharSequence to find, may be null
    5117     * @param startPos  the start position
    5118     * @return the last index of the search CharSequence (always &le; startPos),
    5119     *  -1 if no match or {@code null} input
    5120     * @since 2.5
    5121     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
    5122     */
    5123    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
    5124        if (str == null || searchStr == null) {
    5125            return INDEX_NOT_FOUND;
    5126        }
    5127        if (startPos > str.length() - searchStr.length()) {
    5128            startPos = str.length() - searchStr.length();
    5129        }
    5130        if (startPos < 0) {
    5131            return INDEX_NOT_FOUND;
    5132        }
    5133        if (searchStr.length() == 0) {
    5134            return startPos;
    5135        }
    5136
    5137        for (int i = startPos; i >= 0; i--) {
    5138            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
    5139                return i;
    5140            }
    5141        }
    5142        return INDEX_NOT_FOUND;
    5143    }
    5144
    5145    /**
    5146     * <p>Finds the n-th last index within a String, handling {@code null}.
    5147     * This method uses {@link String#lastIndexOf(String)}.</p>
    5148     *
    5149     * <p>A {@code null} String will return {@code -1}.</p>
    5150     *
    5151     * <pre>
    5152     * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
    5153     * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
    5154     * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
    5155     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
    5156     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
    5157     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
    5158     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
    5159     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
    5160     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
    5161     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
    5162     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
    5163     * </pre>
    5164     *
    5165     * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p>
    5166     *
    5167     * <pre>
    5168     *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
    5169     * </pre>
    5170     *
    5171     * @param str  the CharSequence to check, may be null
    5172     * @param searchStr  the CharSequence to find, may be null
    5173     * @param ordinal  the n-th last {@code searchStr} to find
    5174     * @return the n-th last index of the search CharSequence,
    5175     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5176     * @since 2.5
    5177     * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
    5178     */
    5179    public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
    5180        return ordinalIndexOf(str, searchStr, ordinal, true);
    5181    }
    5182
    5183    // Left/Right/Mid
    5184    //-----------------------------------------------------------------------
    5185    /**
    5186     * <p>Gets the leftmost {@code len} characters of a String.</p>
    5187     *
    5188     * <p>If {@code len} characters are not available, or the
    5189     * String is {@code null}, the String will be returned without
    5190     * an exception. An empty String is returned if len is negative.</p>
    5191     *
    5192     * <pre>
    5193     * StringUtils.left(null, *)    = null
    5194     * StringUtils.left(*, -ve)     = ""
    5195     * StringUtils.left("", *)      = ""
    5196     * StringUtils.left("abc", 0)   = ""
    5197     * StringUtils.left("abc", 2)   = "ab"
    5198     * StringUtils.left("abc", 4)   = "abc"
    5199     * </pre>
    5200     *
    5201     * @param str  the String to get the leftmost characters from, may be null
    5202     * @param len  the length of the required String
    5203     * @return the leftmost characters, {@code null} if null String input
    5204     */
    5205    public static String left(final String str, final int len) {
    5206        if (str == null) {
    5207            return null;
    5208        }
    5209        if (len < 0) {
    5210            return EMPTY;
    5211        }
    5212        if (str.length() <= len) {
    5213            return str;
    5214        }
    5215        return str.substring(0, len);
    5216    }
    5217
    5218    /**
    5219     * <p>Left pad a String with spaces (' ').</p>
    5220     *
    5221     * <p>The String is padded to the size of {@code size}.</p>
    5222     *
    5223     * <pre>
    5224     * StringUtils.leftPad(null, *)   = null
    5225     * StringUtils.leftPad("", 3)     = "   "
    5226     * StringUtils.leftPad("bat", 3)  = "bat"
    5227     * StringUtils.leftPad("bat", 5)  = "  bat"
    5228     * StringUtils.leftPad("bat", 1)  = "bat"
    5229     * StringUtils.leftPad("bat", -1) = "bat"
    5230     * </pre>
    5231     *
    5232     * @param str  the String to pad out, may be null
    5233     * @param size  the size to pad to
    5234     * @return left padded String or original String if no padding is necessary,
    5235     *  {@code null} if null String input
    5236     */
    5237    public static String leftPad(final String str, final int size) {
    5238        return leftPad(str, size, ' ');
    5239    }
    5240
    5241    /**
    5242     * <p>Left pad a String with a specified character.</p>
    5243     *
    5244     * <p>Pad to a size of {@code size}.</p>
    5245     *
    5246     * <pre>
    5247     * StringUtils.leftPad(null, *, *)     = null
    5248     * StringUtils.leftPad("", 3, 'z')     = "zzz"
    5249     * StringUtils.leftPad("bat", 3, 'z')  = "bat"
    5250     * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
    5251     * StringUtils.leftPad("bat", 1, 'z')  = "bat"
    5252     * StringUtils.leftPad("bat", -1, 'z') = "bat"
    5253     * </pre>
    5254     *
    5255     * @param str  the String to pad out, may be null
    5256     * @param size  the size to pad to
    5257     * @param padChar  the character to pad with
    5258     * @return left padded String or original String if no padding is necessary,
    5259     *  {@code null} if null String input
    5260     * @since 2.0
    5261     */
    5262    public static String leftPad(final String str, final int size, final char padChar) {
    5263        if (str == null) {
    5264            return null;
    5265        }
    5266        final int pads = size - str.length();
    5267        if (pads <= 0) {
    5268            return str; // returns original String when possible
    5269        }
    5270        if (pads > PAD_LIMIT) {
    5271            return leftPad(str, size, String.valueOf(padChar));
    5272        }
    5273        return repeat(padChar, pads).concat(str);
    5274    }
    5275
    5276    /**
    5277     * <p>Left pad a String with a specified String.</p>
    5278     *
    5279     * <p>Pad to a size of {@code size}.</p>
    5280     *
    5281     * <pre>
    5282     * StringUtils.leftPad(null, *, *)      = null
    5283     * StringUtils.leftPad("", 3, "z")      = "zzz"
    5284     * StringUtils.leftPad("bat", 3, "yz")  = "bat"
    5285     * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
    5286     * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
    5287     * StringUtils.leftPad("bat", 1, "yz")  = "bat"
    5288     * StringUtils.leftPad("bat", -1, "yz") = "bat"
    5289     * StringUtils.leftPad("bat", 5, null)  = "  bat"
    5290     * StringUtils.leftPad("bat", 5, "")    = "  bat"
    5291     * </pre>
    5292     *
    5293     * @param str  the String to pad out, may be null
    5294     * @param size  the size to pad to
    5295     * @param padStr  the String to pad with, null or empty treated as single space
    5296     * @return left padded String or original String if no padding is necessary,
    5297     *  {@code null} if null String input
    5298     */
    5299    public static String leftPad(final String str, final int size, String padStr) {
    5300        if (str == null) {
    5301            return null;
    5302        }
    5303        if (isEmpty(padStr)) {
    5304            padStr = SPACE;
    5305        }
    5306        final int padLen = padStr.length();
    5307        final int strLen = str.length();
    5308        final int pads = size - strLen;
    5309        if (pads <= 0) {
    5310            return str; // returns original String when possible
    5311        }
    5312        if (padLen == 1 && pads <= PAD_LIMIT) {
    5313            return leftPad(str, size, padStr.charAt(0));
    5314        }
    5315
    5316        if (pads == padLen) {
    5317            return padStr.concat(str);
    5318        } else if (pads < padLen) {
    5319            return padStr.substring(0, pads).concat(str);
    5320        } else {
    5321            final char[] padding = new char[pads];
    5322            final char[] padChars = padStr.toCharArray();
    5323            for (int i = 0; i < pads; i++) {
    5324                padding[i] = padChars[i % padLen];
    5325            }
    5326            return new String(padding).concat(str);
    5327        }
    5328    }
    5329
    5330    /**
    5331     * Gets a CharSequence length or {@code 0} if the CharSequence is
    5332     * {@code null}.
    5333     *
    5334     * @param cs
    5335     *            a CharSequence or {@code null}
    5336     * @return CharSequence length or {@code 0} if the CharSequence is
    5337     *         {@code null}.
    5338     * @since 2.4
    5339     * @since 3.0 Changed signature from length(String) to length(CharSequence)
    5340     */
    5341    public static int length(final CharSequence cs) {
    5342        return cs == null ? 0 : cs.length();
    5343    }
    5344
    5345    /**
    5346     * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
    5347     *
    5348     * <p>A {@code null} input String returns {@code null}.</p>
    5349     *
    5350     * <pre>
    5351     * StringUtils.lowerCase(null)  = null
    5352     * StringUtils.lowerCase("")    = ""
    5353     * StringUtils.lowerCase("aBc") = "abc"
    5354     * </pre>
    5355     *
    5356     * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
    5357     * the result of this method is affected by the current locale.
    5358     * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5359     * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5360     *
    5361     * @param str  the String to lower case, may be null
    5362     * @return the lower cased String, {@code null} if null String input
    5363     */
    5364    public static String lowerCase(final String str) {
    5365        if (str == null) {
    5366            return null;
    5367        }
    5368        return str.toLowerCase();
    5369    }
    5370
    5371    /**
    5372     * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
    5373     *
    5374     * <p>A {@code null} input String returns {@code null}.</p>
    5375     *
    5376     * <pre>
    5377     * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
    5378     * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
    5379     * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
    5380     * </pre>
    5381     *
    5382     * @param str  the String to lower case, may be null
    5383     * @param locale  the locale that defines the case transformation rules, must not be null
    5384     * @return the lower cased String, {@code null} if null String input
    5385     * @since 2.5
    5386     */
    5387    public static String lowerCase(final String str, final Locale locale) {
    5388        if (str == null) {
    5389            return null;
    5390        }
    5391        return str.toLowerCase(locale);
    5392    }
    5393
    5394    private static int[] matches(final CharSequence first, final CharSequence second) {
    5395        CharSequence max, min;
    5396        if (first.length() > second.length()) {
    5397            max = first;
    5398            min = second;
    5399        } else {
    5400            max = second;
    5401            min = first;
    5402        }
    5403        final int range = Math.max(max.length() / 2 - 1, 0);
    5404        final int[] matchIndexes = new int[min.length()];
    5405        Arrays.fill(matchIndexes, -1);
    5406        final boolean[] matchFlags = new boolean[max.length()];
    5407        int matches = 0;
    5408        for (int mi = 0; mi < min.length(); mi++) {
    5409            final char c1 = min.charAt(mi);
    5410            for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
    5411                if (!matchFlags[xi] && c1 == max.charAt(xi)) {
    5412                    matchIndexes[mi] = xi;
    5413                    matchFlags[xi] = true;
    5414                    matches++;
    5415                    break;
    5416                }
    5417            }
    5418        }
    5419        final char[] ms1 = new char[matches];
    5420        final char[] ms2 = new char[matches];
    5421        for (int i = 0, si = 0; i < min.length(); i++) {
    5422            if (matchIndexes[i] != -1) {
    5423                ms1[si] = min.charAt(i);
    5424                si++;
    5425            }
    5426        }
    5427        for (int i = 0, si = 0; i < max.length(); i++) {
    5428            if (matchFlags[i]) {
    5429                ms2[si] = max.charAt(i);
    5430                si++;
    5431            }
    5432        }
    5433        int transpositions = 0;
    5434        for (int mi = 0; mi < ms1.length; mi++) {
    5435            if (ms1[mi] != ms2[mi]) {
    5436                transpositions++;
    5437            }
    5438        }
    5439        int prefix = 0;
    5440        for (int mi = 0; mi < min.length(); mi++) {
    5441            if (first.charAt(mi) == second.charAt(mi)) {
    5442                prefix++;
    5443            } else {
    5444                break;
    5445            }
    5446        }
    5447        return new int[] { matches, transpositions / 2, prefix, max.length() };
    5448    }
    5449
    5450    /**
    5451     * <p>Gets {@code len} characters from the middle of a String.</p>
    5452     *
    5453     * <p>If {@code len} characters are not available, the remainder
    5454     * of the String will be returned without an exception. If the
    5455     * String is {@code null}, {@code null} will be returned.
    5456     * An empty String is returned if len is negative or exceeds the
    5457     * length of {@code str}.</p>
    5458     *
    5459     * <pre>
    5460     * StringUtils.mid(null, *, *)    = null
    5461     * StringUtils.mid(*, *, -ve)     = ""
    5462     * StringUtils.mid("", 0, *)      = ""
    5463     * StringUtils.mid("abc", 0, 2)   = "ab"
    5464     * StringUtils.mid("abc", 0, 4)   = "abc"
    5465     * StringUtils.mid("abc", 2, 4)   = "c"
    5466     * StringUtils.mid("abc", 4, 2)   = ""
    5467     * StringUtils.mid("abc", -2, 2)  = "ab"
    5468     * </pre>
    5469     *
    5470     * @param str  the String to get the characters from, may be null
    5471     * @param pos  the position to start from, negative treated as zero
    5472     * @param len  the length of the required String
    5473     * @return the middle characters, {@code null} if null String input
    5474     */
    5475    public static String mid(final String str, int pos, final int len) {
    5476        if (str == null) {
    5477            return null;
    5478        }
    5479        if (len < 0 || pos > str.length()) {
    5480            return EMPTY;
    5481        }
    5482        if (pos < 0) {
    5483            pos = 0;
    5484        }
    5485        if (str.length() <= pos + len) {
    5486            return str.substring(pos);
    5487        }
    5488        return str.substring(pos, pos + len);
    5489    }
    5490
    5491    private static StringBuilder newStringBuilder(final int noOfItems) {
    5492        return new StringBuilder(noOfItems * 16);
    5493    }
    5494
    5495    /**
    5496     * <p>
    5497     * Similar to <a
    5498     * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize
    5499     * -space</a>
    5500     * </p>
    5501     * <p>
    5502     * The function returns the argument string with whitespace normalized by using
    5503     * {@code {@link #trim(String)}} to remove leading and trailing whitespace
    5504     * and then replacing sequences of whitespace characters by a single space.
    5505     * </p>
    5506     * In XML Whitespace characters are the same as those allowed by the <a
    5507     * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
    5508     * <p>
    5509     * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
    5510     *
    5511     * <p>For reference:</p>
    5512     * <ul>
    5513     * <li>\x0B = vertical tab</li>
    5514     * <li>\f = #xC = form feed</li>
    5515     * <li>#x20 = space</li>
    5516     * <li>#x9 = \t</li>
    5517     * <li>#xA = \n</li>
    5518     * <li>#xD = \r</li>
    5519     * </ul>
    5520     *
    5521     * <p>
    5522     * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
    5523     * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char &lt;= 32) from both
    5524     * ends of this String.
    5525     * </p>
    5526     *
    5527     * @see Pattern
    5528     * @see #trim(String)
    5529     * @see <a
    5530     *      href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a>
    5531     * @param str the source String to normalize whitespaces from, may be null
    5532     * @return the modified string with whitespace normalized, {@code null} if null String input
    5533     *
    5534     * @since 3.0
    5535     */
    5536    public static String normalizeSpace(final String str) {
    5537        // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
    5538        // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
    5539        if (isEmpty(str)) {
    5540            return str;
    5541        }
    5542        final int size = str.length();
    5543        final char[] newChars = new char[size];
    5544        int count = 0;
    5545        int whitespacesCount = 0;
    5546        boolean startWhitespaces = true;
    5547        for (int i = 0; i < size; i++) {
    5548            final char actualChar = str.charAt(i);
    5549            final boolean isWhitespace = Character.isWhitespace(actualChar);
    5550            if (isWhitespace) {
    5551                if (whitespacesCount == 0 && !startWhitespaces) {
    5552                    newChars[count++] = SPACE.charAt(0);
    5553                }
    5554                whitespacesCount++;
    5555            } else {
    5556                startWhitespaces = false;
    5557                newChars[count++] = (actualChar == 160 ? 32 : actualChar);
    5558                whitespacesCount = 0;
    5559            }
    5560        }
    5561        if (startWhitespaces) {
    5562            return EMPTY;
    5563        }
    5564        return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
    5565    }
    5566
    5567    /**
    5568     * <p>Finds the n-th index within a CharSequence, handling {@code null}.
    5569     * This method uses {@link String#indexOf(String)} if possible.</p>
    5570     * <p><b>Note:</b> The code starts looking for a match at the start of the target,
    5571     * incrementing the starting index by one after each successful match
    5572     * (unless {@code searchStr} is an empty string in which case the position
    5573     * is never incremented and {@code 0} is returned immediately).
    5574     * This means that matches may overlap.</p>
    5575     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    5576     *
    5577     * <pre>
    5578     * StringUtils.ordinalIndexOf(null, *, *)          = -1
    5579     * StringUtils.ordinalIndexOf(*, null, *)          = -1
    5580     * StringUtils.ordinalIndexOf("", "", *)           = 0
    5581     * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
    5582     * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
    5583     * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
    5584     * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
    5585     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
    5586     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
    5587     * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
    5588     * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
    5589     * </pre>
    5590     *
    5591     * <p>Matches may overlap:</p>
    5592     * <pre>
    5593     * StringUtils.ordinalIndexOf("ababab", "aba", 1)   = 0
    5594     * StringUtils.ordinalIndexOf("ababab", "aba", 2)   = 2
    5595     * StringUtils.ordinalIndexOf("ababab", "aba", 3)   = -1
    5596     *
    5597     * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
    5598     * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
    5599     * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
    5600     * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
    5601     * </pre>
    5602     *
    5603     * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p>
    5604     *
    5605     * <pre>
    5606     *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
    5607     * </pre>
    5608     *
    5609     * @param str  the CharSequence to check, may be null
    5610     * @param searchStr  the CharSequence to find, may be null
    5611     * @param ordinal  the n-th {@code searchStr} to find
    5612     * @return the n-th index of the search CharSequence,
    5613     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5614     * @since 2.1
    5615     * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
    5616     */
    5617    public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
    5618        return ordinalIndexOf(str, searchStr, ordinal, false);
    5619    }
    5620
    5621    /**
    5622     * <p>Finds the n-th index within a String, handling {@code null}.
    5623     * This method uses {@link String#indexOf(String)} if possible.</p>
    5624     * <p>Note that matches may overlap<p>
    5625     *
    5626     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    5627     *
    5628     * @param str  the CharSequence to check, may be null
    5629     * @param searchStr  the CharSequence to find, may be null
    5630     * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
    5631     * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
    5632     * @return the n-th index of the search CharSequence,
    5633     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5634     */
    5635    // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
    5636    private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
    5637        if (str == null || searchStr == null || ordinal <= 0) {
    5638            return INDEX_NOT_FOUND;
    5639        }
    5640        if (searchStr.length() == 0) {
    5641            return lastIndex ? str.length() : 0;
    5642        }
    5643        int found = 0;
    5644        // set the initial index beyond the end of the string
    5645        // this is to allow for the initial index decrement/increment
    5646        int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
    5647        do {
    5648            if (lastIndex) {
    5649                index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string
    5650            } else {
    5651                index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
    5652            }
    5653            if (index < 0) {
    5654                return index;
    5655            }
    5656            found++;
    5657        } while (found < ordinal);
    5658        return index;
    5659    }
    5660
    5661    // Overlay
    5662    //-----------------------------------------------------------------------
    5663    /**
    5664     * <p>Overlays part of a String with another String.</p>
    5665     *
    5666     * <p>A {@code null} string input returns {@code null}.
    5667     * A negative index is treated as zero.
    5668     * An index greater than the string length is treated as the string length.
    5669     * The start index is always the smaller of the two indices.</p>
    5670     *
    5671     * <pre>
    5672     * StringUtils.overlay(null, *, *, *)            = null
    5673     * StringUtils.overlay("", "abc", 0, 0)          = "abc"
    5674     * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
    5675     * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
    5676     * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
    5677     * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
    5678     * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
    5679     * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
    5680     * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
    5681     * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
    5682     * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
    5683     * </pre>
    5684     *
    5685     * @param str  the String to do overlaying in, may be null
    5686     * @param overlay  the String to overlay, may be null
    5687     * @param start  the position to start overlaying at
    5688     * @param end  the position to stop overlaying before
    5689     * @return overlayed String, {@code null} if null String input
    5690     * @since 2.0
    5691     */
    5692    public static String overlay(final String str, String overlay, int start, int end) {
    5693        if (str == null) {
    5694            return null;
    5695        }
    5696        if (overlay == null) {
    5697            overlay = EMPTY;
    5698        }
    5699        final int len = str.length();
    5700        if (start < 0) {
    5701            start = 0;
    5702        }
    5703        if (start > len) {
    5704            start = len;
    5705        }
    5706        if (end < 0) {
    5707            end = 0;
    5708        }
    5709        if (end > len) {
    5710            end = len;
    5711        }
    5712        if (start > end) {
    5713            final int temp = start;
    5714            start = end;
    5715            end = temp;
    5716        }
    5717        return str.substring(0, start) +
    5718            overlay +
    5719            str.substring(end);
    5720    }
    5721
    5722    /**
    5723     * Prepends the prefix to the start of the string if the string does not
    5724     * already start with any of the prefixes.
    5725     *
    5726     * @param str The string.
    5727     * @param prefix The prefix to prepend to the start of the string.
    5728     * @param ignoreCase Indicates whether the compare should ignore case.
    5729     * @param prefixes Additional prefixes that are valid (optional).
    5730     *
    5731     * @return A new String if prefix was prepended, the same string otherwise.
    5732     */
    5733    private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
    5734        if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) {
    5735            return str;
    5736        }
    5737        if (ArrayUtils.isNotEmpty(prefixes)) {
    5738            for (final CharSequence p : prefixes) {
    5739                if (startsWith(str, p, ignoreCase)) {
    5740                    return str;
    5741                }
    5742            }
    5743        }
    5744        return prefix.toString() + str;
    5745    }
    5746
    5747    /**
    5748     * Prepends the prefix to the start of the string if the string does not
    5749     * already start with any of the prefixes.
    5750     *
    5751     * <pre>
    5752     * StringUtils.prependIfMissing(null, null) = null
    5753     * StringUtils.prependIfMissing("abc", null) = "abc"
    5754     * StringUtils.prependIfMissing("", "xyz") = "xyz"
    5755     * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
    5756     * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
    5757     * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
    5758     * </pre>
    5759     * <p>With additional prefixes,</p>
    5760     * <pre>
    5761     * StringUtils.prependIfMissing(null, null, null) = null
    5762     * StringUtils.prependIfMissing("abc", null, null) = "abc"
    5763     * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
    5764     * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
    5765     * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
    5766     * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
    5767     * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
    5768     * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
    5769     * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
    5770     * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
    5771     * </pre>
    5772     *
    5773     * @param str The string.
    5774     * @param prefix The prefix to prepend to the start of the string.
    5775     * @param prefixes Additional prefixes that are valid.
    5776     *
    5777     * @return A new String if prefix was prepended, the same string otherwise.
    5778     *
    5779     * @since 3.2
    5780     */
    5781    public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
    5782        return prependIfMissing(str, prefix, false, prefixes);
    5783    }
    5784
    5785    /**
    5786     * Prepends the prefix to the start of the string if the string does not
    5787     * already start, case insensitive, with any of the prefixes.
    5788     *
    5789     * <pre>
    5790     * StringUtils.prependIfMissingIgnoreCase(null, null) = null
    5791     * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
    5792     * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
    5793     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
    5794     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
    5795     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
    5796     * </pre>
    5797     * <p>With additional prefixes,</p>
    5798     * <pre>
    5799     * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
    5800     * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
    5801     * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
    5802     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
    5803     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
    5804     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
    5805     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
    5806     * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
    5807     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
    5808     * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
    5809     * </pre>
    5810     *
    5811     * @param str The string.
    5812     * @param prefix The prefix to prepend to the start of the string.
    5813     * @param prefixes Additional prefixes that are valid (optional).
    5814     *
    5815     * @return A new String if prefix was prepended, the same string otherwise.
    5816     *
    5817     * @since 3.2
    5818     */
    5819    public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
    5820        return prependIfMissing(str, prefix, true, prefixes);
    5821    }
    5822
    5823    /**
    5824     * <p>Removes all occurrences of a character from within the source string.</p>
    5825     *
    5826     * <p>A {@code null} source string will return {@code null}.
    5827     * An empty ("") source string will return the empty string.</p>
    5828     *
    5829     * <pre>
    5830     * StringUtils.remove(null, *)       = null
    5831     * StringUtils.remove("", *)         = ""
    5832     * StringUtils.remove("queued", 'u') = "qeed"
    5833     * StringUtils.remove("queued", 'z') = "queued"
    5834     * </pre>
    5835     *
    5836     * @param str  the source String to search, may be null
    5837     * @param remove  the char to search for and remove, may be null
    5838     * @return the substring with the char removed if found,
    5839     *  {@code null} if null String input
    5840     * @since 2.1
    5841     */
    5842    public static String remove(final String str, final char remove) {
    5843        if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
    5844            return str;
    5845        }
    5846        final char[] chars = str.toCharArray();
    5847        int pos = 0;
    5848        for (int i = 0; i < chars.length; i++) {
    5849            if (chars[i] != remove) {
    5850                chars[pos++] = chars[i];
    5851            }
    5852        }
    5853        return new String(chars, 0, pos);
    5854    }
    5855
    5856    /**
    5857     * <p>Removes all occurrences of a substring from within the source string.</p>
    5858     *
    5859     * <p>A {@code null} source string will return {@code null}.
    5860     * An empty ("") source string will return the empty string.
    5861     * A {@code null} remove string will return the source string.
    5862     * An empty ("") remove string will return the source string.</p>
    5863     *
    5864     * <pre>
    5865     * StringUtils.remove(null, *)        = null
    5866     * StringUtils.remove("", *)          = ""
    5867     * StringUtils.remove(*, null)        = *
    5868     * StringUtils.remove(*, "")          = *
    5869     * StringUtils.remove("queued", "ue") = "qd"
    5870     * StringUtils.remove("queued", "zz") = "queued"
    5871     * </pre>
    5872     *
    5873     * @param str  the source String to search, may be null
    5874     * @param remove  the String to search for and remove, may be null
    5875     * @return the substring with the string removed if found,
    5876     *  {@code null} if null String input
    5877     * @since 2.1
    5878     */
    5879    public static String remove(final String str, final String remove) {
    5880        if (isEmpty(str) || isEmpty(remove)) {
    5881            return str;
    5882        }
    5883        return replace(str, remove, EMPTY, -1);
    5884    }
    5885
    5886    /**
    5887     * <p>Removes each substring of the text String that matches the given regular expression.</p>
    5888     *
    5889     * This method is a {@code null} safe equivalent to:
    5890     * <ul>
    5891     *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
    5892     *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
    5893     * </ul>
    5894     *
    5895     * <p>A {@code null} reference passed to this method is a no-op.</p>
    5896     *
    5897     * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
    5898     * is NOT automatically added.
    5899     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    5900     * DOTALL is also known as single-line mode in Perl.</p>
    5901     *
    5902     * <pre>
    5903     * StringUtils.removeAll(null, *)      = null
    5904     * StringUtils.removeAll("any", (String) null)  = "any"
    5905     * StringUtils.removeAll("any", "")    = "any"
    5906     * StringUtils.removeAll("any", ".*")  = ""
    5907     * StringUtils.removeAll("any", ".+")  = ""
    5908     * StringUtils.removeAll("abc", ".?")  = ""
    5909     * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\nB"
    5910     * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
    5911     * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
    5912     * </pre>
    5913     *
    5914     * @param text  text to remove from, may be null
    5915     * @param regex  the regular expression to which this string is to be matched
    5916     * @return  the text with any removes processed,
    5917     *              {@code null} if null String input
    5918     *
    5919     * @throws  java.util.regex.PatternSyntaxException
    5920     *              if the regular expression's syntax is invalid
    5921     *
    5922     * @see #replaceAll(String, String, String)
    5923     * @see #removePattern(String, String)
    5924     * @see String#replaceAll(String, String)
    5925     * @see java.util.regex.Pattern
    5926     * @see java.util.regex.Pattern#DOTALL
    5927     * @since 3.5
    5928     *
    5929     * @deprecated Moved to RegExUtils.
    5930     */
    5931    @Deprecated
    5932    public static String removeAll(final String text, final String regex) {
    5933        return RegExUtils.removeAll(text, regex);
    5934    }
    5935
    5936    /**
    5937     * <p>Removes a substring only if it is at the end of a source string,
    5938     * otherwise returns the source string.</p>
    5939     *
    5940     * <p>A {@code null} source string will return {@code null}.
    5941     * An empty ("") source string will return the empty string.
    5942     * A {@code null} search string will return the source string.</p>
    5943     *
    5944     * <pre>
    5945     * StringUtils.removeEnd(null, *)      = null
    5946     * StringUtils.removeEnd("", *)        = ""
    5947     * StringUtils.removeEnd(*, null)      = *
    5948     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
    5949     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
    5950     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
    5951     * StringUtils.removeEnd("abc", "")    = "abc"
    5952     * </pre>
    5953     *
    5954     * @param str  the source String to search, may be null
    5955     * @param remove  the String to search for and remove, may be null
    5956     * @return the substring with the string removed if found,
    5957     *  {@code null} if null String input
    5958     * @since 2.1
    5959     */
    5960    public static String removeEnd(final String str, final String remove) {
    5961        if (isEmpty(str) || isEmpty(remove)) {
    5962            return str;
    5963        }
    5964        if (str.endsWith(remove)) {
    5965            return str.substring(0, str.length() - remove.length());
    5966        }
    5967        return str;
    5968    }
    5969
    5970    /**
    5971     * <p>Case insensitive removal of a substring if it is at the end of a source string,
    5972     * otherwise returns the source string.</p>
    5973     *
    5974     * <p>A {@code null} source string will return {@code null}.
    5975     * An empty ("") source string will return the empty string.
    5976     * A {@code null} search string will return the source string.</p>
    5977     *
    5978     * <pre>
    5979     * StringUtils.removeEndIgnoreCase(null, *)      = null
    5980     * StringUtils.removeEndIgnoreCase("", *)        = ""
    5981     * StringUtils.removeEndIgnoreCase(*, null)      = *
    5982     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
    5983     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
    5984     * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    5985     * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
    5986     * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
    5987     * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
    5988     * </pre>
    5989     *
    5990     * @param str  the source String to search, may be null
    5991     * @param remove  the String to search for (case insensitive) and remove, may be null
    5992     * @return the substring with the string removed if found,
    5993     *  {@code null} if null String input
    5994     * @since 2.4
    5995     */
    5996    public static String removeEndIgnoreCase(final String str, final String remove) {
    5997        if (isEmpty(str) || isEmpty(remove)) {
    5998            return str;
    5999        }
    6000        if (endsWithIgnoreCase(str, remove)) {
    6001            return str.substring(0, str.length() - remove.length());
    6002        }
    6003        return str;
    6004    }
    6005
    6006    /**
    6007     * <p>Removes the first substring of the text string that matches the given regular expression.</p>
    6008     *
    6009     * This method is a {@code null} safe equivalent to:
    6010     * <ul>
    6011     *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
    6012     *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
    6013     * </ul>
    6014     *
    6015     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6016     *
    6017     * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
    6018     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    6019     * DOTALL is also known as single-line mode in Perl.</p>
    6020     *
    6021     * <pre>
    6022     * StringUtils.removeFirst(null, *)      = null
    6023     * StringUtils.removeFirst("any", (String) null)  = "any"
    6024     * StringUtils.removeFirst("any", "")    = "any"
    6025     * StringUtils.removeFirst("any", ".*")  = ""
    6026     * StringUtils.removeFirst("any", ".+")  = ""
    6027     * StringUtils.removeFirst("abc", ".?")  = "bc"
    6028     * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\n&lt;__&gt;B"
    6029     * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
    6030     * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
    6031     * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
    6032     * </pre>
    6033     *
    6034     * @param text  text to remove from, may be null
    6035     * @param regex  the regular expression to which this string is to be matched
    6036     * @return  the text with the first replacement processed,
    6037     *              {@code null} if null String input
    6038     *
    6039     * @throws  java.util.regex.PatternSyntaxException
    6040     *              if the regular expression's syntax is invalid
    6041     *
    6042     * @see #replaceFirst(String, String, String)
    6043     * @see String#replaceFirst(String, String)
    6044     * @see java.util.regex.Pattern
    6045     * @see java.util.regex.Pattern#DOTALL
    6046     * @since 3.5
    6047     *
    6048     * @deprecated Moved to RegExUtils.
    6049     */
    6050    @Deprecated
    6051    public static String removeFirst(final String text, final String regex) {
    6052        return replaceFirst(text, regex, EMPTY);
    6053    }
    6054
    6055    /**
    6056     * <p>
    6057     * Case insensitive removal of all occurrences of a substring from within
    6058     * the source string.
    6059     * </p>
    6060     *
    6061     * <p>
    6062     * A {@code null} source string will return {@code null}. An empty ("")
    6063     * source string will return the empty string. A {@code null} remove string
    6064     * will return the source string. An empty ("") remove string will return
    6065     * the source string.
    6066     * </p>
    6067     *
    6068     * <pre>
    6069     * StringUtils.removeIgnoreCase(null, *)        = null
    6070     * StringUtils.removeIgnoreCase("", *)          = ""
    6071     * StringUtils.removeIgnoreCase(*, null)        = *
    6072     * StringUtils.removeIgnoreCase(*, "")          = *
    6073     * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
    6074     * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
    6075     * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
    6076     * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
    6077     * </pre>
    6078     *
    6079     * @param str
    6080     *            the source String to search, may be null
    6081     * @param remove
    6082     *            the String to search for (case insensitive) and remove, may be
    6083     *            null
    6084     * @return the substring with the string removed if found, {@code null} if
    6085     *         null String input
    6086     * @since 3.5
    6087     */
    6088    public static String removeIgnoreCase(final String str, final String remove) {
    6089        if (isEmpty(str) || isEmpty(remove)) {
    6090            return str;
    6091        }
    6092        return replaceIgnoreCase(str, remove, EMPTY, -1);
    6093    }
    6094
    6095    /**
    6096     * <p>Removes each substring of the source String that matches the given regular expression using the DOTALL option.
    6097     * </p>
    6098     *
    6099     * This call is a {@code null} safe equivalent to:
    6100     * <ul>
    6101     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
    6102     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
    6103     * </ul>
    6104     *
    6105     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6106     *
    6107     * <pre>
    6108     * StringUtils.removePattern(null, *)       = null
    6109     * StringUtils.removePattern("any", (String) null)   = "any"
    6110     * StringUtils.removePattern("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")  = "AB"
    6111     * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
    6112     * </pre>
    6113     *
    6114     * @param source
    6115     *            the source string
    6116     * @param regex
    6117     *            the regular expression to which this string is to be matched
    6118     * @return The resulting {@code String}
    6119     * @see #replacePattern(String, String, String)
    6120     * @see String#replaceAll(String, String)
    6121     * @see Pattern#DOTALL
    6122     * @since 3.2
    6123     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
    6124     *
    6125     * @deprecated Moved to RegExUtils.
    6126     */
    6127    @Deprecated
    6128    public static String removePattern(final String source, final String regex) {
    6129        return RegExUtils.removePattern(source, regex);
    6130    }
    6131
    6132    // Remove
    6133    //-----------------------------------------------------------------------
    6134    /**
    6135     * <p>Removes a substring only if it is at the beginning of a source string,
    6136     * otherwise returns the source string.</p>
    6137     *
    6138     * <p>A {@code null} source string will return {@code null}.
    6139     * An empty ("") source string will return the empty string.
    6140     * A {@code null} search string will return the source string.</p>
    6141     *
    6142     * <pre>
    6143     * StringUtils.removeStart(null, *)      = null
    6144     * StringUtils.removeStart("", *)        = ""
    6145     * StringUtils.removeStart(*, null)      = *
    6146     * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
    6147     * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
    6148     * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
    6149     * StringUtils.removeStart("abc", "")    = "abc"
    6150     * </pre>
    6151     *
    6152     * @param str  the source String to search, may be null
    6153     * @param remove  the String to search for and remove, may be null
    6154     * @return the substring with the string removed if found,
    6155     *  {@code null} if null String input
    6156     * @since 2.1
    6157     */
    6158    public static String removeStart(final String str, final String remove) {
    6159        if (isEmpty(str) || isEmpty(remove)) {
    6160            return str;
    6161        }
    6162        if (str.startsWith(remove)) {
    6163            return str.substring(remove.length());
    6164        }
    6165        return str;
    6166    }
    6167
    6168    /**
    6169     * <p>Case insensitive removal of a substring if it is at the beginning of a source string,
    6170     * otherwise returns the source string.</p>
    6171     *
    6172     * <p>A {@code null} source string will return {@code null}.
    6173     * An empty ("") source string will return the empty string.
    6174     * A {@code null} search string will return the source string.</p>
    6175     *
    6176     * <pre>
    6177     * StringUtils.removeStartIgnoreCase(null, *)      = null
    6178     * StringUtils.removeStartIgnoreCase("", *)        = ""
    6179     * StringUtils.removeStartIgnoreCase(*, null)      = *
    6180     * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
    6181     * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
    6182     * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
    6183     * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    6184     * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
    6185     * </pre>
    6186     *
    6187     * @param str  the source String to search, may be null
    6188     * @param remove  the String to search for (case insensitive) and remove, may be null
    6189     * @return the substring with the string removed if found,
    6190     *  {@code null} if null String input
    6191     * @since 2.4
    6192     */
    6193    public static String removeStartIgnoreCase(final String str, final String remove) {
    6194        if (isEmpty(str) || isEmpty(remove)) {
    6195            return str;
    6196        }
    6197        if (startsWithIgnoreCase(str, remove)) {
    6198            return str.substring(remove.length());
    6199        }
    6200        return str;
    6201    }
    6202
    6203    /**
    6204     * <p>Returns padding using the specified delimiter repeated
    6205     * to a given length.</p>
    6206     *
    6207     * <pre>
    6208     * StringUtils.repeat('e', 0)  = ""
    6209     * StringUtils.repeat('e', 3)  = "eee"
    6210     * StringUtils.repeat('e', -2) = ""
    6211     * </pre>
    6212     *
    6213     * <p>Note: this method does not support padding with
    6214     * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
    6215     * as they require a pair of {@code char}s to be represented.
    6216     * If you are needing to support full I18N of your applications
    6217     * consider using {@link #repeat(String, int)} instead.
    6218     * </p>
    6219     *
    6220     * @param ch  character to repeat
    6221     * @param repeat  number of times to repeat char, negative treated as zero
    6222     * @return String with repeated character
    6223     * @see #repeat(String, int)
    6224     */
    6225    public static String repeat(final char ch, final int repeat) {
    6226        if (repeat <= 0) {
    6227            return EMPTY;
    6228        }
    6229        final char[] buf = new char[repeat];
    6230        for (int i = repeat - 1; i >= 0; i--) {
    6231            buf[i] = ch;
    6232        }
    6233        return new String(buf);
    6234    }
    6235
    6236    // Padding
    6237    //-----------------------------------------------------------------------
    6238    /**
    6239     * <p>Repeat a String {@code repeat} times to form a
    6240     * new String.</p>
    6241     *
    6242     * <pre>
    6243     * StringUtils.repeat(null, 2) = null
    6244     * StringUtils.repeat("", 0)   = ""
    6245     * StringUtils.repeat("", 2)   = ""
    6246     * StringUtils.repeat("a", 3)  = "aaa"
    6247     * StringUtils.repeat("ab", 2) = "abab"
    6248     * StringUtils.repeat("a", -2) = ""
    6249     * </pre>
    6250     *
    6251     * @param str  the String to repeat, may be null
    6252     * @param repeat  number of times to repeat str, negative treated as zero
    6253     * @return a new String consisting of the original String repeated,
    6254     *  {@code null} if null String input
    6255     */
    6256    public static String repeat(final String str, final int repeat) {
    6257        // Performance tuned for 2.0 (JDK1.4)
    6258
    6259        if (str == null) {
    6260            return null;
    6261        }
    6262        if (repeat <= 0) {
    6263            return EMPTY;
    6264        }
    6265        final int inputLength = str.length();
    6266        if (repeat == 1 || inputLength == 0) {
    6267            return str;
    6268        }
    6269        if (inputLength == 1 && repeat <= PAD_LIMIT) {
    6270            return repeat(str.charAt(0), repeat);
    6271        }
    6272
    6273        final int outputLength = inputLength * repeat;
    6274        switch (inputLength) {
    6275            case 1 :
    6276                return repeat(str.charAt(0), repeat);
    6277            case 2 :
    6278                final char ch0 = str.charAt(0);
    6279                final char ch1 = str.charAt(1);
    6280                final char[] output2 = new char[outputLength];
    6281                for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
    6282                    output2[i] = ch0;
    6283                    output2[i + 1] = ch1;
    6284                }
    6285                return new String(output2);
    6286            default :
    6287                final StringBuilder buf = new StringBuilder(outputLength);
    6288                for (int i = 0; i < repeat; i++) {
    6289                    buf.append(str);
    6290                }
    6291                return buf.toString();
    6292        }
    6293    }
    6294
    6295    // Conversion
    6296    //-----------------------------------------------------------------------
    6297
    6298    /**
    6299     * <p>Repeat a String {@code repeat} times to form a
    6300     * new String, with a String separator injected each time. </p>
    6301     *
    6302     * <pre>
    6303     * StringUtils.repeat(null, null, 2) = null
    6304     * StringUtils.repeat(null, "x", 2)  = null
    6305     * StringUtils.repeat("", null, 0)   = ""
    6306     * StringUtils.repeat("", "", 2)     = ""
    6307     * StringUtils.repeat("", "x", 3)    = "xxx"
    6308     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
    6309     * </pre>
    6310     *
    6311     * @param str        the String to repeat, may be null
    6312     * @param separator  the String to inject, may be null
    6313     * @param repeat     number of times to repeat str, negative treated as zero
    6314     * @return a new String consisting of the original String repeated,
    6315     *  {@code null} if null String input
    6316     * @since 2.5
    6317     */
    6318    public static String repeat(final String str, final String separator, final int repeat) {
    6319        if (str == null || separator == null) {
    6320            return repeat(str, repeat);
    6321        }
    6322        // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
    6323        final String result = repeat(str + separator, repeat);
    6324        return removeEnd(result, separator);
    6325    }
    6326
    6327    /**
    6328     * <p>Replaces all occurrences of a String within another String.</p>
    6329     *
    6330     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6331     *
    6332     * <pre>
    6333     * StringUtils.replace(null, *, *)        = null
    6334     * StringUtils.replace("", *, *)          = ""
    6335     * StringUtils.replace("any", null, *)    = "any"
    6336     * StringUtils.replace("any", *, null)    = "any"
    6337     * StringUtils.replace("any", "", *)      = "any"
    6338     * StringUtils.replace("aba", "a", null)  = "aba"
    6339     * StringUtils.replace("aba", "a", "")    = "b"
    6340     * StringUtils.replace("aba", "a", "z")   = "zbz"
    6341     * </pre>
    6342     *
    6343     * @see #replace(String text, String searchString, String replacement, int max)
    6344     * @param text  text to search and replace in, may be null
    6345     * @param searchString  the String to search for, may be null
    6346     * @param replacement  the String to replace it with, may be null
    6347     * @return the text with any replacements processed,
    6348     *  {@code null} if null String input
    6349     */
    6350    public static String replace(final String text, final String searchString, final String replacement) {
    6351        return replace(text, searchString, replacement, -1);
    6352    }
    6353
    6354    /**
    6355     * <p>Replaces a String with another String inside a larger String,
    6356     * for the first {@code max} values of the search String.</p>
    6357     *
    6358     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6359     *
    6360     * <pre>
    6361     * StringUtils.replace(null, *, *, *)         = null
    6362     * StringUtils.replace("", *, *, *)           = ""
    6363     * StringUtils.replace("any", null, *, *)     = "any"
    6364     * StringUtils.replace("any", *, null, *)     = "any"
    6365     * StringUtils.replace("any", "", *, *)       = "any"
    6366     * StringUtils.replace("any", *, *, 0)        = "any"
    6367     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
    6368     * StringUtils.replace("abaa", "a", "", -1)   = "b"
    6369     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
    6370     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
    6371     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
    6372     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
    6373     * </pre>
    6374     *
    6375     * @param text  text to search and replace in, may be null
    6376     * @param searchString  the String to search for, may be null
    6377     * @param replacement  the String to replace it with, may be null
    6378     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6379     * @return the text with any replacements processed,
    6380     *  {@code null} if null String input
    6381     */
    6382    public static String replace(final String text, final String searchString, final String replacement, final int max) {
    6383        return replace(text, searchString, replacement, max, false);
    6384    }
    6385
    6386    /**
    6387     * <p>Replaces a String with another String inside a larger String,
    6388     * for the first {@code max} values of the search String,
    6389     * case sensitively/insensisitively based on {@code ignoreCase} value.</p>
    6390     *
    6391     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6392     *
    6393     * <pre>
    6394     * StringUtils.replace(null, *, *, *, false)         = null
    6395     * StringUtils.replace("", *, *, *, false)           = ""
    6396     * StringUtils.replace("any", null, *, *, false)     = "any"
    6397     * StringUtils.replace("any", *, null, *, false)     = "any"
    6398     * StringUtils.replace("any", "", *, *, false)       = "any"
    6399     * StringUtils.replace("any", *, *, 0, false)        = "any"
    6400     * StringUtils.replace("abaa", "a", null, -1, false) = "abaa"
    6401     * StringUtils.replace("abaa", "a", "", -1, false)   = "b"
    6402     * StringUtils.replace("abaa", "a", "z", 0, false)   = "abaa"
    6403     * StringUtils.replace("abaa", "A", "z", 1, false)   = "abaa"
    6404     * StringUtils.replace("abaa", "A", "z", 1, true)   = "zbaa"
    6405     * StringUtils.replace("abAa", "a", "z", 2, true)   = "zbza"
    6406     * StringUtils.replace("abAa", "a", "z", -1, true)  = "zbzz"
    6407     * </pre>
    6408     *
    6409     * @param text  text to search and replace in, may be null
    6410     * @param searchString  the String to search for (case insensitive), may be null
    6411     * @param replacement  the String to replace it with, may be null
    6412     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6413     * @param ignoreCase if true replace is case insensitive, otherwise case sensitive
    6414     * @return the text with any replacements processed,
    6415     *  {@code null} if null String input
    6416     */
    6417     private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) {
    6418         if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
    6419             return text;
    6420         }
    6421         if (ignoreCase) {
    6422             searchString = searchString.toLowerCase();
    6423         }
    6424         int start = 0;
    6425         int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start);
    6426         if (end == INDEX_NOT_FOUND) {
    6427             return text;
    6428         }
    6429         final int replLength = searchString.length();
    6430         int increase = replacement.length() - replLength;
    6431         increase = increase < 0 ? 0 : increase;
    6432         increase *= max < 0 ? 16 : max > 64 ? 64 : max;
    6433         final StringBuilder buf = new StringBuilder(text.length() + increase);
    6434         while (end != INDEX_NOT_FOUND) {
    6435             buf.append(text, start, end).append(replacement);
    6436             start = end + replLength;
    6437             if (--max == 0) {
    6438                 break;
    6439             }
    6440             end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start);
    6441         }
    6442         buf.append(text, start, text.length());
    6443         return buf.toString();
    6444     }
    6445
    6446    /**
    6447     * <p>Replaces each substring of the text String that matches the given regular expression
    6448     * with the given replacement.</p>
    6449     *
    6450     * This method is a {@code null} safe equivalent to:
    6451     * <ul>
    6452     *  <li>{@code text.replaceAll(regex, replacement)}</li>
    6453     *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
    6454     * </ul>
    6455     *
    6456     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6457     *
    6458     * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
    6459     * is NOT automatically added.
    6460     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    6461     * DOTALL is also known as single-line mode in Perl.</p>
    6462     *
    6463     * <pre>
    6464     * StringUtils.replaceAll(null, *, *)       = null
    6465     * StringUtils.replaceAll("any", (String) null, *)   = "any"
    6466     * StringUtils.replaceAll("any", *, null)   = "any"
    6467     * StringUtils.replaceAll("", "", "zzz")    = "zzz"
    6468     * StringUtils.replaceAll("", ".*", "zzz")  = "zzz"
    6469     * StringUtils.replaceAll("", ".+", "zzz")  = ""
    6470     * StringUtils.replaceAll("abc", "", "ZZ")  = "ZZaZZbZZcZZ"
    6471     * StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")      = "z\nz"
    6472     * StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;", "(?s)&lt;.*&gt;", "z")  = "z"
    6473     * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")       = "ABC___123"
    6474     * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
    6475     * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
    6476     * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
    6477     * </pre>
    6478     *
    6479     * @param text  text to search and replace in, may be null
    6480     * @param regex  the regular expression to which this string is to be matched
    6481     * @param replacement  the string to be substituted for each match
    6482     * @return  the text with any replacements processed,
    6483     *              {@code null} if null String input
    6484     *
    6485     * @throws  java.util.regex.PatternSyntaxException
    6486     *              if the regular expression's syntax is invalid
    6487     *
    6488     * @see #replacePattern(String, String, String)
    6489     * @see String#replaceAll(String, String)
    6490     * @see java.util.regex.Pattern
    6491     * @see java.util.regex.Pattern#DOTALL
    6492     * @since 3.5
    6493     *
    6494     * @deprecated Moved to RegExUtils.
    6495     */
    6496    @Deprecated
    6497    public static String replaceAll(final String text, final String regex, final String replacement) {
    6498        return RegExUtils.replaceAll(text, regex, replacement);
    6499    }
    6500
    6501    // Replace, character based
    6502    //-----------------------------------------------------------------------
    6503    /**
    6504     * <p>Replaces all occurrences of a character in a String with another.
    6505     * This is a null-safe version of {@link String#replace(char, char)}.</p>
    6506     *
    6507     * <p>A {@code null} string input returns {@code null}.
    6508     * An empty ("") string input returns an empty string.</p>
    6509     *
    6510     * <pre>
    6511     * StringUtils.replaceChars(null, *, *)        = null
    6512     * StringUtils.replaceChars("", *, *)          = ""
    6513     * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
    6514     * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
    6515     * </pre>
    6516     *
    6517     * @param str  String to replace characters in, may be null
    6518     * @param searchChar  the character to search for, may be null
    6519     * @param replaceChar  the character to replace, may be null
    6520     * @return modified String, {@code null} if null string input
    6521     * @since 2.0
    6522     */
    6523    public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
    6524        if (str == null) {
    6525            return null;
    6526        }
    6527        return str.replace(searchChar, replaceChar);
    6528    }
    6529
    6530    /**
    6531     * <p>Replaces multiple characters in a String in one go.
    6532     * This method can also be used to delete characters.</p>
    6533     *
    6534     * <p>For example:<br>
    6535     * {@code replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly}.</p>
    6536     *
    6537     * <p>A {@code null} string input returns {@code null}.
    6538     * An empty ("") string input returns an empty string.
    6539     * A null or empty set of search characters returns the input string.</p>
    6540     *
    6541     * <p>The length of the search characters should normally equal the length
    6542     * of the replace characters.
    6543     * If the search characters is longer, then the extra search characters
    6544     * are deleted.
    6545     * If the search characters is shorter, then the extra replace characters
    6546     * are ignored.</p>
    6547     *
    6548     * <pre>
    6549     * StringUtils.replaceChars(null, *, *)           = null
    6550     * StringUtils.replaceChars("", *, *)             = ""
    6551     * StringUtils.replaceChars("abc", null, *)       = "abc"
    6552     * StringUtils.replaceChars("abc", "", *)         = "abc"
    6553     * StringUtils.replaceChars("abc", "b", null)     = "ac"
    6554     * StringUtils.replaceChars("abc", "b", "")       = "ac"
    6555     * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
    6556     * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
    6557     * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
    6558     * </pre>
    6559     *
    6560     * @param str  String to replace characters in, may be null
    6561     * @param searchChars  a set of characters to search for, may be null
    6562     * @param replaceChars  a set of characters to replace, may be null
    6563     * @return modified String, {@code null} if null string input
    6564     * @since 2.0
    6565     */
    6566    public static String replaceChars(final String str, final String searchChars, String replaceChars) {
    6567        if (isEmpty(str) || isEmpty(searchChars)) {
    6568            return str;
    6569        }
    6570        if (replaceChars == null) {
    6571            replaceChars = EMPTY;
    6572        }
    6573        boolean modified = false;
    6574        final int replaceCharsLength = replaceChars.length();
    6575        final int strLength = str.length();
    6576        final StringBuilder buf = new StringBuilder(strLength);
    6577        for (int i = 0; i < strLength; i++) {
    6578            final char ch = str.charAt(i);
    6579            final int index = searchChars.indexOf(ch);
    6580            if (index >= 0) {
    6581                modified = true;
    6582                if (index < replaceCharsLength) {
    6583                    buf.append(replaceChars.charAt(index));
    6584                }
    6585            } else {
    6586                buf.append(ch);
    6587            }
    6588        }
    6589        if (modified) {
    6590            return buf.toString();
    6591        }
    6592        return str;
    6593    }
    6594
    6595    /**
    6596     * <p>
    6597     * Replaces all occurrences of Strings within another String.
    6598     * </p>
    6599     *
    6600     * <p>
    6601     * A {@code null} reference passed to this method is a no-op, or if
    6602     * any "search string" or "string to replace" is null, that replace will be
    6603     * ignored. This will not repeat. For repeating replaces, call the
    6604     * overloaded method.
    6605     * </p>
    6606     *
    6607     * <pre>
    6608     *  StringUtils.replaceEach(null, *, *)        = null
    6609     *  StringUtils.replaceEach("", *, *)          = ""
    6610     *  StringUtils.replaceEach("aba", null, null) = "aba"
    6611     *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
    6612     *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
    6613     *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
    6614     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
    6615     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
    6616     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
    6617     *  (example of how it does not repeat)
    6618     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
    6619     * </pre>
    6620     *
    6621     * @param text
    6622     *            text to search and replace in, no-op if null
    6623     * @param searchList
    6624     *            the Strings to search for, no-op if null
    6625     * @param replacementList
    6626     *            the Strings to replace them with, no-op if null
    6627     * @return the text with any replacements processed, {@code null} if
    6628     *         null String input
    6629     * @throws IllegalArgumentException
    6630     *             if the lengths of the arrays are not the same (null is ok,
    6631     *             and/or size 0)
    6632     * @since 2.4
    6633     */
    6634    public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
    6635        return replaceEach(text, searchList, replacementList, false, 0);
    6636    }
    6637
    6638    /**
    6639     * <p>
    6640     * Replace all occurrences of Strings within another String.
    6641     * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
    6642     * {@link #replaceEach(String, String[], String[])}
    6643     * </p>
    6644     *
    6645     * <p>
    6646     * A {@code null} reference passed to this method is a no-op, or if
    6647     * any "search string" or "string to replace" is null, that replace will be
    6648     * ignored.
    6649     * </p>
    6650     *
    6651     * <pre>
    6652     *  StringUtils.replaceEach(null, *, *, *, *) = null
    6653     *  StringUtils.replaceEach("", *, *, *, *) = ""
    6654     *  StringUtils.replaceEach("aba", null, null, *, *) = "aba"
    6655     *  StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
    6656     *  StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
    6657     *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
    6658     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
    6659     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
    6660     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
    6661     *  (example of how it repeats)
    6662     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
    6663     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
    6664     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
    6665     * </pre>
    6666     *
    6667     * @param text
    6668     *            text to search and replace in, no-op if null
    6669     * @param searchList
    6670     *            the Strings to search for, no-op if null
    6671     * @param replacementList
    6672     *            the Strings to replace them with, no-op if null
    6673     * @param repeat if true, then replace repeatedly
    6674     *       until there are no more possible replacements or timeToLive < 0
    6675     * @param timeToLive
    6676     *            if less than 0 then there is a circular reference and endless
    6677     *            loop
    6678     * @return the text with any replacements processed, {@code null} if
    6679     *         null String input
    6680     * @throws IllegalStateException
    6681     *             if the search is repeating and there is an endless loop due
    6682     *             to outputs of one being inputs to another
    6683     * @throws IllegalArgumentException
    6684     *             if the lengths of the arrays are not the same (null is ok,
    6685     *             and/or size 0)
    6686     * @since 2.4
    6687     */
    6688    private static String replaceEach(
    6689            final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {
    6690
    6691        // mchyzer Performance note: This creates very few new objects (one major goal)
    6692        // let me know if there are performance requests, we can create a harness to measure
    6693
    6694        if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) {
    6695            return text;
    6696        }
    6697
    6698        // if recursing, this shouldn't be less than 0
    6699        if (timeToLive < 0) {
    6700            throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
    6701                                            "output of one loop is the input of another");
    6702        }
    6703
    6704        final int searchLength = searchList.length;
    6705        final int replacementLength = replacementList.length;
    6706
    6707        // make sure lengths are ok, these need to be equal
    6708        if (searchLength != replacementLength) {
    6709            throw new IllegalArgumentException("Search and Replace array lengths don't match: "
    6710                + searchLength
    6711                + " vs "
    6712                + replacementLength);
    6713        }
    6714
    6715        // keep track of which still have matches
    6716        final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
    6717
    6718        // index on index that the match was found
    6719        int textIndex = -1;
    6720        int replaceIndex = -1;
    6721        int tempIndex = -1;
    6722
    6723        // index of replace array that will replace the search string found
    6724        // NOTE: logic duplicated below START
    6725        for (int i = 0; i < searchLength; i++) {
    6726            if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
    6727                    searchList[i].isEmpty() || replacementList[i] == null) {
    6728                continue;
    6729            }
    6730            tempIndex = text.indexOf(searchList[i]);
    6731
    6732            // see if we need to keep searching for this
    6733            if (tempIndex == -1) {
    6734                noMoreMatchesForReplIndex[i] = true;
    6735            } else {
    6736                if (textIndex == -1 || tempIndex < textIndex) {
    6737                    textIndex = tempIndex;
    6738                    replaceIndex = i;
    6739                }
    6740            }
    6741        }
    6742        // NOTE: logic mostly below END
    6743
    6744        // no search strings found, we are done
    6745        if (textIndex == -1) {
    6746            return text;
    6747        }
    6748
    6749        int start = 0;
    6750
    6751        // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
    6752        int increase = 0;
    6753
    6754        // count the replacement text elements that are larger than their corresponding text being replaced
    6755        for (int i = 0; i < searchList.length; i++) {
    6756            if (searchList[i] == null || replacementList[i] == null) {
    6757                continue;
    6758            }
    6759            final int greater = replacementList[i].length() - searchList[i].length();
    6760            if (greater > 0) {
    6761                increase += 3 * greater; // assume 3 matches
    6762            }
    6763        }
    6764        // have upper-bound at 20% increase, then let Java take over
    6765        increase = Math.min(increase, text.length() / 5);
    6766
    6767        final StringBuilder buf = new StringBuilder(text.length() + increase);
    6768
    6769        while (textIndex != -1) {
    6770
    6771            for (int i = start; i < textIndex; i++) {
    6772                buf.append(text.charAt(i));
    6773            }
    6774            buf.append(replacementList[replaceIndex]);
    6775
    6776            start = textIndex + searchList[replaceIndex].length();
    6777
    6778            textIndex = -1;
    6779            replaceIndex = -1;
    6780            tempIndex = -1;
    6781            // find the next earliest match
    6782            // NOTE: logic mostly duplicated above START
    6783            for (int i = 0; i < searchLength; i++) {
    6784                if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
    6785                        searchList[i].isEmpty() || replacementList[i] == null) {
    6786                    continue;
    6787                }
    6788                tempIndex = text.indexOf(searchList[i], start);
    6789
    6790                // see if we need to keep searching for this
    6791                if (tempIndex == -1) {
    6792                    noMoreMatchesForReplIndex[i] = true;
    6793                } else {
    6794                    if (textIndex == -1 || tempIndex < textIndex) {
    6795                        textIndex = tempIndex;
    6796                        replaceIndex = i;
    6797                    }
    6798                }
    6799            }
    6800            // NOTE: logic duplicated above END
    6801
    6802        }
    6803        final int textLength = text.length();
    6804        for (int i = start; i < textLength; i++) {
    6805            buf.append(text.charAt(i));
    6806        }
    6807        final String result = buf.toString();
    6808        if (!repeat) {
    6809            return result;
    6810        }
    6811
    6812        return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
    6813    }
    6814
    6815    /**
    6816     * <p>
    6817     * Replaces all occurrences of Strings within another String.
    6818     * </p>
    6819     *
    6820     * <p>
    6821     * A {@code null} reference passed to this method is a no-op, or if
    6822     * any "search string" or "string to replace" is null, that replace will be
    6823     * ignored.
    6824     * </p>
    6825     *
    6826     * <pre>
    6827     *  StringUtils.replaceEachRepeatedly(null, *, *) = null
    6828     *  StringUtils.replaceEachRepeatedly("", *, *) = ""
    6829     *  StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
    6830     *  StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
    6831     *  StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
    6832     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
    6833     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
    6834     *  StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
    6835     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
    6836     *  (example of how it repeats)
    6837     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
    6838     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
    6839     * </pre>
    6840     *
    6841     * @param text
    6842     *            text to search and replace in, no-op if null
    6843     * @param searchList
    6844     *            the Strings to search for, no-op if null
    6845     * @param replacementList
    6846     *            the Strings to replace them with, no-op if null
    6847     * @return the text with any replacements processed, {@code null} if
    6848     *         null String input
    6849     * @throws IllegalStateException
    6850     *             if the search is repeating and there is an endless loop due
    6851     *             to outputs of one being inputs to another
    6852     * @throws IllegalArgumentException
    6853     *             if the lengths of the arrays are not the same (null is ok,
    6854     *             and/or size 0)
    6855     * @since 2.4
    6856     */
    6857    public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
    6858        // timeToLive should be 0 if not used or nothing to replace, else it's
    6859        // the length of the replace array
    6860        final int timeToLive = searchList == null ? 0 : searchList.length;
    6861        return replaceEach(text, searchList, replacementList, true, timeToLive);
    6862    }
    6863
    6864    /**
    6865     * <p>Replaces the first substring of the text string that matches the given regular expression
    6866     * with the given replacement.</p>
    6867     *
    6868     * This method is a {@code null} safe equivalent to:
    6869     * <ul>
    6870     *  <li>{@code text.replaceFirst(regex, replacement)}</li>
    6871     *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
    6872     * </ul>
    6873     *
    6874     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6875     *
    6876     * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
    6877     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    6878     * DOTALL is also known as single-line mode in Perl.</p>
    6879     *
    6880     * <pre>
    6881     * StringUtils.replaceFirst(null, *, *)       = null
    6882     * StringUtils.replaceFirst("any", (String) null, *)   = "any"
    6883     * StringUtils.replaceFirst("any", *, null)   = "any"
    6884     * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
    6885     * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
    6886     * StringUtils.replaceFirst("", ".+", "zzz")  = ""
    6887     * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
    6888     * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")      = "z\n&lt;__&gt;"
    6889     * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "(?s)&lt;.*&gt;", "z")  = "z"
    6890     * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
    6891     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
    6892     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
    6893     * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
    6894     * </pre>
    6895     *
    6896     * @param text  text to search and replace in, may be null
    6897     * @param regex  the regular expression to which this string is to be matched
    6898     * @param replacement  the string to be substituted for the first match
    6899     * @return  the text with the first replacement processed,
    6900     *              {@code null} if null String input
    6901     *
    6902     * @throws  java.util.regex.PatternSyntaxException
    6903     *              if the regular expression's syntax is invalid
    6904     *
    6905     * @see String#replaceFirst(String, String)
    6906     * @see java.util.regex.Pattern
    6907     * @see java.util.regex.Pattern#DOTALL
    6908     * @since 3.5
    6909     *
    6910     * @deprecated Moved to RegExUtils.
    6911     */
    6912    @Deprecated
    6913    public static String replaceFirst(final String text, final String regex, final String replacement) {
    6914        return RegExUtils.replaceFirst(text, regex, replacement);
    6915    }
    6916
    6917    /**
    6918    * <p>Case insensitively replaces all occurrences of a String within another String.</p>
    6919    *
    6920    * <p>A {@code null} reference passed to this method is a no-op.</p>
    6921    *
    6922    * <pre>
    6923    * StringUtils.replaceIgnoreCase(null, *, *)        = null
    6924    * StringUtils.replaceIgnoreCase("", *, *)          = ""
    6925    * StringUtils.replaceIgnoreCase("any", null, *)    = "any"
    6926    * StringUtils.replaceIgnoreCase("any", *, null)    = "any"
    6927    * StringUtils.replaceIgnoreCase("any", "", *)      = "any"
    6928    * StringUtils.replaceIgnoreCase("aba", "a", null)  = "aba"
    6929    * StringUtils.replaceIgnoreCase("abA", "A", "")    = "b"
    6930    * StringUtils.replaceIgnoreCase("aba", "A", "z")   = "zbz"
    6931    * </pre>
    6932    *
    6933    * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
    6934    * @param text  text to search and replace in, may be null
    6935    * @param searchString  the String to search for (case insensitive), may be null
    6936    * @param replacement  the String to replace it with, may be null
    6937    * @return the text with any replacements processed,
    6938    *  {@code null} if null String input
    6939    * @since 3.5
    6940    */
    6941   public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
    6942       return replaceIgnoreCase(text, searchString, replacement, -1);
    6943   }
    6944
    6945    /**
    6946     * <p>Case insensitively replaces a String with another String inside a larger String,
    6947     * for the first {@code max} values of the search String.</p>
    6948     *
    6949     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6950     *
    6951     * <pre>
    6952     * StringUtils.replaceIgnoreCase(null, *, *, *)         = null
    6953     * StringUtils.replaceIgnoreCase("", *, *, *)           = ""
    6954     * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"
    6955     * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"
    6956     * StringUtils.replaceIgnoreCase("any", "", *, *)       = "any"
    6957     * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"
    6958     * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
    6959     * StringUtils.replaceIgnoreCase("abaa", "a", "", -1)   = "b"
    6960     * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0)   = "abaa"
    6961     * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1)   = "zbaa"
    6962     * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2)   = "zbza"
    6963     * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1)  = "zbzz"
    6964     * </pre>
    6965     *
    6966     * @param text  text to search and replace in, may be null
    6967     * @param searchString  the String to search for (case insensitive), may be null
    6968     * @param replacement  the String to replace it with, may be null
    6969     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6970     * @return the text with any replacements processed,
    6971     *  {@code null} if null String input
    6972     * @since 3.5
    6973     */
    6974    public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
    6975        return replace(text, searchString, replacement, max, true);
    6976    }
    6977
    6978    // Replacing
    6979    //-----------------------------------------------------------------------
    6980    /**
    6981     * <p>Replaces a String with another String inside a larger String, once.</p>
    6982     *
    6983     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6984     *
    6985     * <pre>
    6986     * StringUtils.replaceOnce(null, *, *)        = null
    6987     * StringUtils.replaceOnce("", *, *)          = ""
    6988     * StringUtils.replaceOnce("any", null, *)    = "any"
    6989     * StringUtils.replaceOnce("any", *, null)    = "any"
    6990     * StringUtils.replaceOnce("any", "", *)      = "any"
    6991     * StringUtils.replaceOnce("aba", "a", null)  = "aba"
    6992     * StringUtils.replaceOnce("aba", "a", "")    = "ba"
    6993     * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
    6994     * </pre>
    6995     *
    6996     * @see #replace(String text, String searchString, String replacement, int max)
    6997     * @param text  text to search and replace in, may be null
    6998     * @param searchString  the String to search for, may be null
    6999     * @param replacement  the String to replace with, may be null
    7000     * @return the text with any replacements processed,
    7001     *  {@code null} if null String input
    7002     */
    7003    public static String replaceOnce(final String text, final String searchString, final String replacement) {
    7004        return replace(text, searchString, replacement, 1);
    7005    }
    7006
    7007    /**
    7008     * <p>Case insensitively replaces a String with another String inside a larger String, once.</p>
    7009     *
    7010     * <p>A {@code null} reference passed to this method is a no-op.</p>
    7011     *
    7012     * <pre>
    7013     * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null
    7014     * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""
    7015     * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"
    7016     * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"
    7017     * StringUtils.replaceOnceIgnoreCase("any", "", *)      = "any"
    7018     * StringUtils.replaceOnceIgnoreCase("aba", "a", null)  = "aba"
    7019     * StringUtils.replaceOnceIgnoreCase("aba", "a", "")    = "ba"
    7020     * StringUtils.replaceOnceIgnoreCase("aba", "a", "z")   = "zba"
    7021     * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
    7022     * </pre>
    7023     *
    7024     * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
    7025     * @param text  text to search and replace in, may be null
    7026     * @param searchString  the String to search for (case insensitive), may be null
    7027     * @param replacement  the String to replace with, may be null
    7028     * @return the text with any replacements processed,
    7029     *  {@code null} if null String input
    7030     * @since 3.5
    7031     */
    7032    public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
    7033        return replaceIgnoreCase(text, searchString, replacement, 1);
    7034    }
    7035
    7036    /**
    7037     * <p>Replaces each substring of the source String that matches the given regular expression with the given
    7038     * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.</p>
    7039     *
    7040     * This call is a {@code null} safe equivalent to:
    7041     * <ul>
    7042     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
    7043     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
    7044     * </ul>
    7045     *
    7046     * <p>A {@code null} reference passed to this method is a no-op.</p>
    7047     *
    7048     * <pre>
    7049     * StringUtils.replacePattern(null, *, *)       = null
    7050     * StringUtils.replacePattern("any", (String) null, *)   = "any"
    7051     * StringUtils.replacePattern("any", *, null)   = "any"
    7052     * StringUtils.replacePattern("", "", "zzz")    = "zzz"
    7053     * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
    7054     * StringUtils.replacePattern("", ".+", "zzz")  = ""
    7055     * StringUtils.replacePattern("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")       = "z"
    7056     * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
    7057     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
    7058     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
    7059     * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
    7060     * </pre>
    7061     *
    7062     * @param source
    7063     *            the source string
    7064     * @param regex
    7065     *            the regular expression to which this string is to be matched
    7066     * @param replacement
    7067     *            the string to be substituted for each match
    7068     * @return The resulting {@code String}
    7069     * @see #replaceAll(String, String, String)
    7070     * @see String#replaceAll(String, String)
    7071     * @see Pattern#DOTALL
    7072     * @since 3.2
    7073     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
    7074     *
    7075     * @deprecated Moved to RegExUtils.
    7076     */
    7077    @Deprecated
    7078    public static String replacePattern(final String source, final String regex, final String replacement) {
    7079        return RegExUtils.replacePattern(source, regex, replacement);
    7080    }
    7081
    7082    // Reversing
    7083    //-----------------------------------------------------------------------
    7084    /**
    7085     * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p>
    7086     *
    7087     * <p>A {@code null} String returns {@code null}.</p>
    7088     *
    7089     * <pre>
    7090     * StringUtils.reverse(null)  = null
    7091     * StringUtils.reverse("")    = ""
    7092     * StringUtils.reverse("bat") = "tab"
    7093     * </pre>
    7094     *
    7095     * @param str  the String to reverse, may be null
    7096     * @return the reversed String, {@code null} if null String input
    7097     */
    7098    public static String reverse(final String str) {
    7099        if (str == null) {
    7100            return null;
    7101        }
    7102        return new StringBuilder(str).reverse().toString();
    7103    }
    7104
    7105    /**
    7106     * <p>Reverses a String that is delimited by a specific character.</p>
    7107     *
    7108     * <p>The Strings between the delimiters are not reversed.
    7109     * Thus java.lang.String becomes String.lang.java (if the delimiter
    7110     * is {@code '.'}).</p>
    7111     *
    7112     * <pre>
    7113     * StringUtils.reverseDelimited(null, *)      = null
    7114     * StringUtils.reverseDelimited("", *)        = ""
    7115     * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
    7116     * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
    7117     * </pre>
    7118     *
    7119     * @param str  the String to reverse, may be null
    7120     * @param separatorChar  the separator character to use
    7121     * @return the reversed String, {@code null} if null String input
    7122     * @since 2.0
    7123     */
    7124    public static String reverseDelimited(final String str, final char separatorChar) {
    7125        if (str == null) {
    7126            return null;
    7127        }
    7128        // could implement manually, but simple way is to reuse other,
    7129        // probably slower, methods.
    7130        final String[] strs = split(str, separatorChar);
    7131        ArrayUtils.reverse(strs);
    7132        return join(strs, separatorChar);
    7133    }
    7134
    7135    /**
    7136     * <p>Gets the rightmost {@code len} characters of a String.</p>
    7137     *
    7138     * <p>If {@code len} characters are not available, or the String
    7139     * is {@code null}, the String will be returned without an
    7140     * an exception. An empty String is returned if len is negative.</p>
    7141     *
    7142     * <pre>
    7143     * StringUtils.right(null, *)    = null
    7144     * StringUtils.right(*, -ve)     = ""
    7145     * StringUtils.right("", *)      = ""
    7146     * StringUtils.right("abc", 0)   = ""
    7147     * StringUtils.right("abc", 2)   = "bc"
    7148     * StringUtils.right("abc", 4)   = "abc"
    7149     * </pre>
    7150     *
    7151     * @param str  the String to get the rightmost characters from, may be null
    7152     * @param len  the length of the required String
    7153     * @return the rightmost characters, {@code null} if null String input
    7154     */
    7155    public static String right(final String str, final int len) {
    7156        if (str == null) {
    7157            return null;
    7158        }
    7159        if (len < 0) {
    7160            return EMPTY;
    7161        }
    7162        if (str.length() <= len) {
    7163            return str;
    7164        }
    7165        return str.substring(str.length() - len);
    7166    }
    7167
    7168    /**
    7169     * <p>Right pad a String with spaces (' ').</p>
    7170     *
    7171     * <p>The String is padded to the size of {@code size}.</p>
    7172     *
    7173     * <pre>
    7174     * StringUtils.rightPad(null, *)   = null
    7175     * StringUtils.rightPad("", 3)     = "   "
    7176     * StringUtils.rightPad("bat", 3)  = "bat"
    7177     * StringUtils.rightPad("bat", 5)  = "bat  "
    7178     * StringUtils.rightPad("bat", 1)  = "bat"
    7179     * StringUtils.rightPad("bat", -1) = "bat"
    7180     * </pre>
    7181     *
    7182     * @param str  the String to pad out, may be null
    7183     * @param size  the size to pad to
    7184     * @return right padded String or original String if no padding is necessary,
    7185     *  {@code null} if null String input
    7186     */
    7187    public static String rightPad(final String str, final int size) {
    7188        return rightPad(str, size, ' ');
    7189    }
    7190
    7191    /**
    7192     * <p>Right pad a String with a specified character.</p>
    7193     *
    7194     * <p>The String is padded to the size of {@code size}.</p>
    7195     *
    7196     * <pre>
    7197     * StringUtils.rightPad(null, *, *)     = null
    7198     * StringUtils.rightPad("", 3, 'z')     = "zzz"
    7199     * StringUtils.rightPad("bat", 3, 'z')  = "bat"
    7200     * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
    7201     * StringUtils.rightPad("bat", 1, 'z')  = "bat"
    7202     * StringUtils.rightPad("bat", -1, 'z') = "bat"
    7203     * </pre>
    7204     *
    7205     * @param str  the String to pad out, may be null
    7206     * @param size  the size to pad to
    7207     * @param padChar  the character to pad with
    7208     * @return right padded String or original String if no padding is necessary,
    7209     *  {@code null} if null String input
    7210     * @since 2.0
    7211     */
    7212    public static String rightPad(final String str, final int size, final char padChar) {
    7213        if (str == null) {
    7214            return null;
    7215        }
    7216        final int pads = size - str.length();
    7217        if (pads <= 0) {
    7218            return str; // returns original String when possible
    7219        }
    7220        if (pads > PAD_LIMIT) {
    7221            return rightPad(str, size, String.valueOf(padChar));
    7222        }
    7223        return str.concat(repeat(padChar, pads));
    7224    }
    7225
    7226    /**
    7227     * <p>Right pad a String with a specified String.</p>
    7228     *
    7229     * <p>The String is padded to the size of {@code size}.</p>
    7230     *
    7231     * <pre>
    7232     * StringUtils.rightPad(null, *, *)      = null
    7233     * StringUtils.rightPad("", 3, "z")      = "zzz"
    7234     * StringUtils.rightPad("bat", 3, "yz")  = "bat"
    7235     * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
    7236     * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
    7237     * StringUtils.rightPad("bat", 1, "yz")  = "bat"
    7238     * StringUtils.rightPad("bat", -1, "yz") = "bat"
    7239     * StringUtils.rightPad("bat", 5, null)  = "bat  "
    7240     * StringUtils.rightPad("bat", 5, "")    = "bat  "
    7241     * </pre>
    7242     *
    7243     * @param str  the String to pad out, may be null
    7244     * @param size  the size to pad to
    7245     * @param padStr  the String to pad with, null or empty treated as single space
    7246     * @return right padded String or original String if no padding is necessary,
    7247     *  {@code null} if null String input
    7248     */
    7249    public static String rightPad(final String str, final int size, String padStr) {
    7250        if (str == null) {
    7251            return null;
    7252        }
    7253        if (isEmpty(padStr)) {
    7254            padStr = SPACE;
    7255        }
    7256        final int padLen = padStr.length();
    7257        final int strLen = str.length();
    7258        final int pads = size - strLen;
    7259        if (pads <= 0) {
    7260            return str; // returns original String when possible
    7261        }
    7262        if (padLen == 1 && pads <= PAD_LIMIT) {
    7263            return rightPad(str, size, padStr.charAt(0));
    7264        }
    7265
    7266        if (pads == padLen) {
    7267            return str.concat(padStr);
    7268        } else if (pads < padLen) {
    7269            return str.concat(padStr.substring(0, pads));
    7270        } else {
    7271            final char[] padding = new char[pads];
    7272            final char[] padChars = padStr.toCharArray();
    7273            for (int i = 0; i < pads; i++) {
    7274                padding[i] = padChars[i % padLen];
    7275            }
    7276            return str.concat(new String(padding));
    7277        }
    7278    }
    7279
    7280    // Rotating (circular shift)
    7281    //-----------------------------------------------------------------------
    7282    /**
    7283     * <p>Rotate (circular shift) a String of {@code shift} characters.</p>
    7284     * <ul>
    7285     *  <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
    7286     *  <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
    7287     * </ul>
    7288     *
    7289     * <pre>
    7290     * StringUtils.rotate(null, *)        = null
    7291     * StringUtils.rotate("", *)          = ""
    7292     * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
    7293     * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
    7294     * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
    7295     * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
    7296     * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
    7297     * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
    7298     * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
    7299     * </pre>
    7300     *
    7301     * @param str  the String to rotate, may be null
    7302     * @param shift  number of time to shift (positive : right shift, negative : left shift)
    7303     * @return the rotated String,
    7304     *          or the original String if {@code shift == 0},
    7305     *          or {@code null} if null String input
    7306     * @since 3.5
    7307     */
    7308    public static String rotate(final String str, final int shift) {
    7309        if (str == null) {
    7310            return null;
    7311        }
    7312
    7313        final int strLen = str.length();
    7314        if (shift == 0 || strLen == 0 || shift % strLen == 0) {
    7315            return str;
    7316        }
    7317
    7318        final StringBuilder builder = new StringBuilder(strLen);
    7319        final int offset = - (shift % strLen);
    7320        builder.append(substring(str, offset));
    7321        builder.append(substring(str, 0, offset));
    7322        return builder.toString();
    7323    }
    7324
    7325    // Splitting
    7326    //-----------------------------------------------------------------------
    7327    /**
    7328     * <p>Splits the provided text into an array, using whitespace as the
    7329     * separator.
    7330     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    7331     *
    7332     * <p>The separator is not included in the returned String array.
    7333     * Adjacent separators are treated as one separator.
    7334     * For more control over the split use the StrTokenizer class.</p>
    7335     *
    7336     * <p>A {@code null} input String returns {@code null}.</p>
    7337     *
    7338     * <pre>
    7339     * StringUtils.split(null)       = null
    7340     * StringUtils.split("")         = []
    7341     * StringUtils.split("abc def")  = ["abc", "def"]
    7342     * StringUtils.split("abc  def") = ["abc", "def"]
    7343     * StringUtils.split(" abc ")    = ["abc"]
    7344     * </pre>
    7345     *
    7346     * @param str  the String to parse, may be null
    7347     * @return an array of parsed Strings, {@code null} if null String input
    7348     */
    7349    public static String[] split(final String str) {
    7350        return split(str, null, -1);
    7351    }
    7352
    7353    /**
    7354     * <p>Splits the provided text into an array, separator specified.
    7355     * This is an alternative to using StringTokenizer.</p>
    7356     *
    7357     * <p>The separator is not included in the returned String array.
    7358     * Adjacent separators are treated as one separator.
    7359     * For more control over the split use the StrTokenizer class.</p>
    7360     *
    7361     * <p>A {@code null} input String returns {@code null}.</p>
    7362     *
    7363     * <pre>
    7364     * StringUtils.split(null, *)         = null
    7365     * StringUtils.split("", *)           = []
    7366     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
    7367     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
    7368     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
    7369     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
    7370     * </pre>
    7371     *
    7372     * @param str  the String to parse, may be null
    7373     * @param separatorChar  the character used as the delimiter
    7374     * @return an array of parsed Strings, {@code null} if null String input
    7375     * @since 2.0
    7376     */
    7377    public static String[] split(final String str, final char separatorChar) {
    7378        return splitWorker(str, separatorChar, false);
    7379    }
    7380
    7381    /**
    7382     * <p>Splits the provided text into an array, separators specified.
    7383     * This is an alternative to using StringTokenizer.</p>
    7384     *
    7385     * <p>The separator is not included in the returned String array.
    7386     * Adjacent separators are treated as one separator.
    7387     * For more control over the split use the StrTokenizer class.</p>
    7388     *
    7389     * <p>A {@code null} input String returns {@code null}.
    7390     * A {@code null} separatorChars splits on whitespace.</p>
    7391     *
    7392     * <pre>
    7393     * StringUtils.split(null, *)         = null
    7394     * StringUtils.split("", *)           = []
    7395     * StringUtils.split("abc def", null) = ["abc", "def"]
    7396     * StringUtils.split("abc def", " ")  = ["abc", "def"]
    7397     * StringUtils.split("abc  def", " ") = ["abc", "def"]
    7398     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
    7399     * </pre>
    7400     *
    7401     * @param str  the String to parse, may be null
    7402     * @param separatorChars  the characters used as the delimiters,
    7403     *  {@code null} splits on whitespace
    7404     * @return an array of parsed Strings, {@code null} if null String input
    7405     */
    7406    public static String[] split(final String str, final String separatorChars) {
    7407        return splitWorker(str, separatorChars, -1, false);
    7408    }
    7409
    7410    /**
    7411     * <p>Splits the provided text into an array with a maximum length,
    7412     * separators specified.</p>
    7413     *
    7414     * <p>The separator is not included in the returned String array.
    7415     * Adjacent separators are treated as one separator.</p>
    7416     *
    7417     * <p>A {@code null} input String returns {@code null}.
    7418     * A {@code null} separatorChars splits on whitespace.</p>
    7419     *
    7420     * <p>If more than {@code max} delimited substrings are found, the last
    7421     * returned string includes all characters after the first {@code max - 1}
    7422     * returned strings (including separator characters).</p>
    7423     *
    7424     * <pre>
    7425     * StringUtils.split(null, *, *)            = null
    7426     * StringUtils.split("", *, *)              = []
    7427     * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd", "ef"]
    7428     * StringUtils.split("ab   cd ef", null, 0) = ["ab", "cd", "ef"]
    7429     * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    7430     * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    7431     * </pre>
    7432     *
    7433     * @param str  the String to parse, may be null
    7434     * @param separatorChars  the characters used as the delimiters,
    7435     *  {@code null} splits on whitespace
    7436     * @param max  the maximum number of elements to include in the
    7437     *  array. A zero or negative value implies no limit
    7438     * @return an array of parsed Strings, {@code null} if null String input
    7439     */
    7440    public static String[] split(final String str, final String separatorChars, final int max) {
    7441        return splitWorker(str, separatorChars, max, false);
    7442    }
    7443
    7444    /**
    7445     * <p>Splits a String by Character type as returned by
    7446     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7447     * characters of the same type are returned as complete tokens.
    7448     * <pre>
    7449     * StringUtils.splitByCharacterType(null)         = null
    7450     * StringUtils.splitByCharacterType("")           = []
    7451     * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    7452     * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    7453     * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    7454     * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
    7455     * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
    7456     * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
    7457     * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
    7458     * </pre>
    7459     * @param str the String to split, may be {@code null}
    7460     * @return an array of parsed Strings, {@code null} if null String input
    7461     * @since 2.4
    7462     */
    7463    public static String[] splitByCharacterType(final String str) {
    7464        return splitByCharacterType(str, false);
    7465    }
    7466
    7467    /**
    7468     * <p>Splits a String by Character type as returned by
    7469     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7470     * characters of the same type are returned as complete tokens, with the
    7471     * following exception: if {@code camelCase} is {@code true},
    7472     * the character of type {@code Character.UPPERCASE_LETTER}, if any,
    7473     * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
    7474     * will belong to the following token rather than to the preceding, if any,
    7475     * {@code Character.UPPERCASE_LETTER} token.
    7476     * @param str the String to split, may be {@code null}
    7477     * @param camelCase whether to use so-called "camel-case" for letter types
    7478     * @return an array of parsed Strings, {@code null} if null String input
    7479     * @since 2.4
    7480     */
    7481    private static String[] splitByCharacterType(final String str, final boolean camelCase) {
    7482        if (str == null) {
    7483            return null;
    7484        }
    7485        if (str.isEmpty()) {
    7486            return ArrayUtils.EMPTY_STRING_ARRAY;
    7487        }
    7488        final char[] c = str.toCharArray();
    7489        final List<String> list = new ArrayList<>();
    7490        int tokenStart = 0;
    7491        int currentType = Character.getType(c[tokenStart]);
    7492        for (int pos = tokenStart + 1; pos < c.length; pos++) {
    7493            final int type = Character.getType(c[pos]);
    7494            if (type == currentType) {
    7495                continue;
    7496            }
    7497            if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
    7498                final int newTokenStart = pos - 1;
    7499                if (newTokenStart != tokenStart) {
    7500                    list.add(new String(c, tokenStart, newTokenStart - tokenStart));
    7501                    tokenStart = newTokenStart;
    7502                }
    7503            } else {
    7504                list.add(new String(c, tokenStart, pos - tokenStart));
    7505                tokenStart = pos;
    7506            }
    7507            currentType = type;
    7508        }
    7509        list.add(new String(c, tokenStart, c.length - tokenStart));
    7510        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7511    }
    7512
    7513    /**
    7514     * <p>Splits a String by Character type as returned by
    7515     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7516     * characters of the same type are returned as complete tokens, with the
    7517     * following exception: the character of type
    7518     * {@code Character.UPPERCASE_LETTER}, if any, immediately
    7519     * preceding a token of type {@code Character.LOWERCASE_LETTER}
    7520     * will belong to the following token rather than to the preceding, if any,
    7521     * {@code Character.UPPERCASE_LETTER} token.
    7522     * <pre>
    7523     * StringUtils.splitByCharacterTypeCamelCase(null)         = null
    7524     * StringUtils.splitByCharacterTypeCamelCase("")           = []
    7525     * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    7526     * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    7527     * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    7528     * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
    7529     * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
    7530     * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
    7531     * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
    7532     * </pre>
    7533     * @param str the String to split, may be {@code null}
    7534     * @return an array of parsed Strings, {@code null} if null String input
    7535     * @since 2.4
    7536     */
    7537    public static String[] splitByCharacterTypeCamelCase(final String str) {
    7538        return splitByCharacterType(str, true);
    7539    }
    7540
    7541    /**
    7542     * <p>Splits the provided text into an array, separator string specified.</p>
    7543     *
    7544     * <p>The separator(s) will not be included in the returned String array.
    7545     * Adjacent separators are treated as one separator.</p>
    7546     *
    7547     * <p>A {@code null} input String returns {@code null}.
    7548     * A {@code null} separator splits on whitespace.</p>
    7549     *
    7550     * <pre>
    7551     * StringUtils.splitByWholeSeparator(null, *)               = null
    7552     * StringUtils.splitByWholeSeparator("", *)                 = []
    7553     * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
    7554     * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
    7555     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    7556     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    7557     * </pre>
    7558     *
    7559     * @param str  the String to parse, may be null
    7560     * @param separator  String containing the String to be used as a delimiter,
    7561     *  {@code null} splits on whitespace
    7562     * @return an array of parsed Strings, {@code null} if null String was input
    7563     */
    7564    public static String[] splitByWholeSeparator(final String str, final String separator) {
    7565        return splitByWholeSeparatorWorker(str, separator, -1, false);
    7566    }
    7567
    7568    /**
    7569     * <p>Splits the provided text into an array, separator string specified.
    7570     * Returns a maximum of {@code max} substrings.</p>
    7571     *
    7572     * <p>The separator(s) will not be included in the returned String array.
    7573     * Adjacent separators are treated as one separator.</p>
    7574     *
    7575     * <p>A {@code null} input String returns {@code null}.
    7576     * A {@code null} separator splits on whitespace.</p>
    7577     *
    7578     * <pre>
    7579     * StringUtils.splitByWholeSeparator(null, *, *)               = null
    7580     * StringUtils.splitByWholeSeparator("", *, *)                 = []
    7581     * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
    7582     * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
    7583     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    7584     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    7585     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    7586     * </pre>
    7587     *
    7588     * @param str  the String to parse, may be null
    7589     * @param separator  String containing the String to be used as a delimiter,
    7590     *  {@code null} splits on whitespace
    7591     * @param max  the maximum number of elements to include in the returned
    7592     *  array. A zero or negative value implies no limit.
    7593     * @return an array of parsed Strings, {@code null} if null String was input
    7594     */
    7595    public static String[] splitByWholeSeparator( final String str, final String separator, final int max) {
    7596        return splitByWholeSeparatorWorker(str, separator, max, false);
    7597    }
    7598
    7599    /**
    7600     * <p>Splits the provided text into an array, separator string specified. </p>
    7601     *
    7602     * <p>The separator is not included in the returned String array.
    7603     * Adjacent separators are treated as separators for empty tokens.
    7604     * For more control over the split use the StrTokenizer class.</p>
    7605     *
    7606     * <p>A {@code null} input String returns {@code null}.
    7607     * A {@code null} separator splits on whitespace.</p>
    7608     *
    7609     * <pre>
    7610     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
    7611     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
    7612     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
    7613     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
    7614     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    7615     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    7616     * </pre>
    7617     *
    7618     * @param str  the String to parse, may be null
    7619     * @param separator  String containing the String to be used as a delimiter,
    7620     *  {@code null} splits on whitespace
    7621     * @return an array of parsed Strings, {@code null} if null String was input
    7622     * @since 2.4
    7623     */
    7624    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
    7625        return splitByWholeSeparatorWorker(str, separator, -1, true);
    7626    }
    7627
    7628    /**
    7629     * <p>Splits the provided text into an array, separator string specified.
    7630     * Returns a maximum of {@code max} substrings.</p>
    7631     *
    7632     * <p>The separator is not included in the returned String array.
    7633     * Adjacent separators are treated as separators for empty tokens.
    7634     * For more control over the split use the StrTokenizer class.</p>
    7635     *
    7636     * <p>A {@code null} input String returns {@code null}.
    7637     * A {@code null} separator splits on whitespace.</p>
    7638     *
    7639     * <pre>
    7640     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
    7641     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
    7642     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
    7643     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
    7644     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    7645     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    7646     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    7647     * </pre>
    7648     *
    7649     * @param str  the String to parse, may be null
    7650     * @param separator  String containing the String to be used as a delimiter,
    7651     *  {@code null} splits on whitespace
    7652     * @param max  the maximum number of elements to include in the returned
    7653     *  array. A zero or negative value implies no limit.
    7654     * @return an array of parsed Strings, {@code null} if null String was input
    7655     * @since 2.4
    7656     */
    7657    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
    7658        return splitByWholeSeparatorWorker(str, separator, max, true);
    7659    }
    7660
    7661    /**
    7662     * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
    7663     *
    7664     * @param str  the String to parse, may be {@code null}
    7665     * @param separator  String containing the String to be used as a delimiter,
    7666     *  {@code null} splits on whitespace
    7667     * @param max  the maximum number of elements to include in the returned
    7668     *  array. A zero or negative value implies no limit.
    7669     * @param preserveAllTokens if {@code true}, adjacent separators are
    7670     * treated as empty token separators; if {@code false}, adjacent
    7671     * separators are treated as one separator.
    7672     * @return an array of parsed Strings, {@code null} if null String input
    7673     * @since 2.4
    7674     */
    7675    private static String[] splitByWholeSeparatorWorker(
    7676            final String str, final String separator, final int max, final boolean preserveAllTokens) {
    7677        if (str == null) {
    7678            return null;
    7679        }
    7680
    7681        final int len = str.length();
    7682
    7683        if (len == 0) {
    7684            return ArrayUtils.EMPTY_STRING_ARRAY;
    7685        }
    7686
    7687        if (separator == null || EMPTY.equals(separator)) {
    7688            // Split on whitespace.
    7689            return splitWorker(str, null, max, preserveAllTokens);
    7690        }
    7691
    7692        final int separatorLength = separator.length();
    7693
    7694        final ArrayList<String> substrings = new ArrayList<>();
    7695        int numberOfSubstrings = 0;
    7696        int beg = 0;
    7697        int end = 0;
    7698        while (end < len) {
    7699            end = str.indexOf(separator, beg);
    7700
    7701            if (end > -1) {
    7702                if (end > beg) {
    7703                    numberOfSubstrings += 1;
    7704
    7705                    if (numberOfSubstrings == max) {
    7706                        end = len;
    7707                        substrings.add(str.substring(beg));
    7708                    } else {
    7709                        // The following is OK, because String.substring( beg, end ) excludes
    7710                        // the character at the position 'end'.
    7711                        substrings.add(str.substring(beg, end));
    7712
    7713                        // Set the starting point for the next search.
    7714                        // The following is equivalent to beg = end + (separatorLength - 1) + 1,
    7715                        // which is the right calculation:
    7716                        beg = end + separatorLength;
    7717                    }
    7718                } else {
    7719                    // We found a consecutive occurrence of the separator, so skip it.
    7720                    if (preserveAllTokens) {
    7721                        numberOfSubstrings += 1;
    7722                        if (numberOfSubstrings == max) {
    7723                            end = len;
    7724                            substrings.add(str.substring(beg));
    7725                        } else {
    7726                            substrings.add(EMPTY);
    7727                        }
    7728                    }
    7729                    beg = end + separatorLength;
    7730                }
    7731            } else {
    7732                // String.substring( beg ) goes from 'beg' to the end of the String.
    7733                substrings.add(str.substring(beg));
    7734                end = len;
    7735            }
    7736        }
    7737
    7738        return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7739    }
    7740
    7741    // -----------------------------------------------------------------------
    7742    /**
    7743     * <p>Splits the provided text into an array, using whitespace as the
    7744     * separator, preserving all tokens, including empty tokens created by
    7745     * adjacent separators. This is an alternative to using StringTokenizer.
    7746     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    7747     *
    7748     * <p>The separator is not included in the returned String array.
    7749     * Adjacent separators are treated as separators for empty tokens.
    7750     * For more control over the split use the StrTokenizer class.</p>
    7751     *
    7752     * <p>A {@code null} input String returns {@code null}.</p>
    7753     *
    7754     * <pre>
    7755     * StringUtils.splitPreserveAllTokens(null)       = null
    7756     * StringUtils.splitPreserveAllTokens("")         = []
    7757     * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
    7758     * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
    7759     * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
    7760     * </pre>
    7761     *
    7762     * @param str  the String to parse, may be {@code null}
    7763     * @return an array of parsed Strings, {@code null} if null String input
    7764     * @since 2.1
    7765     */
    7766    public static String[] splitPreserveAllTokens(final String str) {
    7767        return splitWorker(str, null, -1, true);
    7768    }
    7769
    7770    /**
    7771     * <p>Splits the provided text into an array, separator specified,
    7772     * preserving all tokens, including empty tokens created by adjacent
    7773     * separators. This is an alternative to using StringTokenizer.</p>
    7774     *
    7775     * <p>The separator is not included in the returned String array.
    7776     * Adjacent separators are treated as separators for empty tokens.
    7777     * For more control over the split use the StrTokenizer class.</p>
    7778     *
    7779     * <p>A {@code null} input String returns {@code null}.</p>
    7780     *
    7781     * <pre>
    7782     * StringUtils.splitPreserveAllTokens(null, *)         = null
    7783     * StringUtils.splitPreserveAllTokens("", *)           = []
    7784     * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
    7785     * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
    7786     * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
    7787     * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
    7788     * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
    7789     * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
    7790     * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
    7791     * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
    7792     * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
    7793     * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
    7794     * </pre>
    7795     *
    7796     * @param str  the String to parse, may be {@code null}
    7797     * @param separatorChar  the character used as the delimiter,
    7798     *  {@code null} splits on whitespace
    7799     * @return an array of parsed Strings, {@code null} if null String input
    7800     * @since 2.1
    7801     */
    7802    public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
    7803        return splitWorker(str, separatorChar, true);
    7804    }
    7805
    7806    /**
    7807     * <p>Splits the provided text into an array, separators specified,
    7808     * preserving all tokens, including empty tokens created by adjacent
    7809     * separators. This is an alternative to using StringTokenizer.</p>
    7810     *
    7811     * <p>The separator is not included in the returned String array.
    7812     * Adjacent separators are treated as separators for empty tokens.
    7813     * For more control over the split use the StrTokenizer class.</p>
    7814     *
    7815     * <p>A {@code null} input String returns {@code null}.
    7816     * A {@code null} separatorChars splits on whitespace.</p>
    7817     *
    7818     * <pre>
    7819     * StringUtils.splitPreserveAllTokens(null, *)           = null
    7820     * StringUtils.splitPreserveAllTokens("", *)             = []
    7821     * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
    7822     * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
    7823     * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
    7824     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
    7825     * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
    7826     * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
    7827     * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
    7828     * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
    7829     * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
    7830     * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
    7831     * </pre>
    7832     *
    7833     * @param str  the String to parse, may be {@code null}
    7834     * @param separatorChars  the characters used as the delimiters,
    7835     *  {@code null} splits on whitespace
    7836     * @return an array of parsed Strings, {@code null} if null String input
    7837     * @since 2.1
    7838     */
    7839    public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
    7840        return splitWorker(str, separatorChars, -1, true);
    7841    }
    7842
    7843    /**
    7844     * <p>Splits the provided text into an array with a maximum length,
    7845     * separators specified, preserving all tokens, including empty tokens
    7846     * created by adjacent separators.</p>
    7847     *
    7848     * <p>The separator is not included in the returned String array.
    7849     * Adjacent separators are treated as separators for empty tokens.
    7850     * Adjacent separators are treated as one separator.</p>
    7851     *
    7852     * <p>A {@code null} input String returns {@code null}.
    7853     * A {@code null} separatorChars splits on whitespace.</p>
    7854     *
    7855     * <p>If more than {@code max} delimited substrings are found, the last
    7856     * returned string includes all characters after the first {@code max - 1}
    7857     * returned strings (including separator characters).</p>
    7858     *
    7859     * <pre>
    7860     * StringUtils.splitPreserveAllTokens(null, *, *)            = null
    7861     * StringUtils.splitPreserveAllTokens("", *, *)              = []
    7862     * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "de", "fg"]
    7863     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "", "", "de", "fg"]
    7864     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    7865     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    7866     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
    7867     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
    7868     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
    7869     * </pre>
    7870     *
    7871     * @param str  the String to parse, may be {@code null}
    7872     * @param separatorChars  the characters used as the delimiters,
    7873     *  {@code null} splits on whitespace
    7874     * @param max  the maximum number of elements to include in the
    7875     *  array. A zero or negative value implies no limit
    7876     * @return an array of parsed Strings, {@code null} if null String input
    7877     * @since 2.1
    7878     */
    7879    public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
    7880        return splitWorker(str, separatorChars, max, true);
    7881    }
    7882
    7883    /**
    7884     * Performs the logic for the {@code split} and
    7885     * {@code splitPreserveAllTokens} methods that do not return a
    7886     * maximum array length.
    7887     *
    7888     * @param str  the String to parse, may be {@code null}
    7889     * @param separatorChar the separate character
    7890     * @param preserveAllTokens if {@code true}, adjacent separators are
    7891     * treated as empty token separators; if {@code false}, adjacent
    7892     * separators are treated as one separator.
    7893     * @return an array of parsed Strings, {@code null} if null String input
    7894     */
    7895    private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
    7896        // Performance tuned for 2.0 (JDK1.4)
    7897
    7898        if (str == null) {
    7899            return null;
    7900        }
    7901        final int len = str.length();
    7902        if (len == 0) {
    7903            return ArrayUtils.EMPTY_STRING_ARRAY;
    7904        }
    7905        final List<String> list = new ArrayList<>();
    7906        int i = 0, start = 0;
    7907        boolean match = false;
    7908        boolean lastMatch = false;
    7909        while (i < len) {
    7910            if (str.charAt(i) == separatorChar) {
    7911                if (match || preserveAllTokens) {
    7912                    list.add(str.substring(start, i));
    7913                    match = false;
    7914                    lastMatch = true;
    7915                }
    7916                start = ++i;
    7917                continue;
    7918            }
    7919            lastMatch = false;
    7920            match = true;
    7921            i++;
    7922        }
    7923        if (match || preserveAllTokens && lastMatch) {
    7924            list.add(str.substring(start, i));
    7925        }
    7926        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7927    }
    7928
    7929    /**
    7930     * Performs the logic for the {@code split} and
    7931     * {@code splitPreserveAllTokens} methods that return a maximum array
    7932     * length.
    7933     *
    7934     * @param str  the String to parse, may be {@code null}
    7935     * @param separatorChars the separate character
    7936     * @param max  the maximum number of elements to include in the
    7937     *  array. A zero or negative value implies no limit.
    7938     * @param preserveAllTokens if {@code true}, adjacent separators are
    7939     * treated as empty token separators; if {@code false}, adjacent
    7940     * separators are treated as one separator.
    7941     * @return an array of parsed Strings, {@code null} if null String input
    7942     */
    7943    private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
    7944        // Performance tuned for 2.0 (JDK1.4)
    7945        // Direct code is quicker than StringTokenizer.
    7946        // Also, StringTokenizer uses isSpace() not isWhitespace()
    7947
    7948        if (str == null) {
    7949            return null;
    7950        }
    7951        final int len = str.length();
    7952        if (len == 0) {
    7953            return ArrayUtils.EMPTY_STRING_ARRAY;
    7954        }
    7955        final List<String> list = new ArrayList<>();
    7956        int sizePlus1 = 1;
    7957        int i = 0, start = 0;
    7958        boolean match = false;
    7959        boolean lastMatch = false;
    7960        if (separatorChars == null) {
    7961            // Null separator means use whitespace
    7962            while (i < len) {
    7963                if (Character.isWhitespace(str.charAt(i))) {
    7964                    if (match || preserveAllTokens) {
    7965                        lastMatch = true;
    7966                        if (sizePlus1++ == max) {
    7967                            i = len;
    7968                            lastMatch = false;
    7969                        }
    7970                        list.add(str.substring(start, i));
    7971                        match = false;
    7972                    }
    7973                    start = ++i;
    7974                    continue;
    7975                }
    7976                lastMatch = false;
    7977                match = true;
    7978                i++;
    7979            }
    7980        } else if (separatorChars.length() == 1) {
    7981            // Optimise 1 character case
    7982            final char sep = separatorChars.charAt(0);
    7983            while (i < len) {
    7984                if (str.charAt(i) == sep) {
    7985                    if (match || preserveAllTokens) {
    7986                        lastMatch = true;
    7987                        if (sizePlus1++ == max) {
    7988                            i = len;
    7989                            lastMatch = false;
    7990                        }
    7991                        list.add(str.substring(start, i));
    7992                        match = false;
    7993                    }
    7994                    start = ++i;
    7995                    continue;
    7996                }
    7997                lastMatch = false;
    7998                match = true;
    7999                i++;
    8000            }
    8001        } else {
    8002            // standard case
    8003            while (i < len) {
    8004                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
    8005                    if (match || preserveAllTokens) {
    8006                        lastMatch = true;
    8007                        if (sizePlus1++ == max) {
    8008                            i = len;
    8009                            lastMatch = false;
    8010                        }
    8011                        list.add(str.substring(start, i));
    8012                        match = false;
    8013                    }
    8014                    start = ++i;
    8015                    continue;
    8016                }
    8017                lastMatch = false;
    8018                match = true;
    8019                i++;
    8020            }
    8021        }
    8022        if (match || preserveAllTokens && lastMatch) {
    8023            list.add(str.substring(start, i));
    8024        }
    8025        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    8026    }
    8027
    8028    /**
    8029     * <p>Check if a CharSequence starts with a specified prefix.</p>
    8030     *
    8031     * <p>{@code null}s are handled without exceptions. Two {@code null}
    8032     * references are considered to be equal. The comparison is case sensitive.</p>
    8033     *
    8034     * <pre>
    8035     * StringUtils.startsWith(null, null)      = true
    8036     * StringUtils.startsWith(null, "abc")     = false
    8037     * StringUtils.startsWith("abcdef", null)  = false
    8038     * StringUtils.startsWith("abcdef", "abc") = true
    8039     * StringUtils.startsWith("ABCDEF", "abc") = false
    8040     * </pre>
    8041     *
    8042     * @see java.lang.String#startsWith(String)
    8043     * @param str  the CharSequence to check, may be null
    8044     * @param prefix the prefix to find, may be null
    8045     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
    8046     *  both {@code null}
    8047     * @since 2.4
    8048     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
    8049     */
    8050    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
    8051        return startsWith(str, prefix, false);
    8052    }
    8053
    8054    /**
    8055     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>
    8056     *
    8057     * @see java.lang.String#startsWith(String)
    8058     * @param str  the CharSequence to check, may be null
    8059     * @param prefix the prefix to find, may be null
    8060     * @param ignoreCase indicates whether the compare should ignore case
    8061     *  (case insensitive) or not.
    8062     * @return {@code true} if the CharSequence starts with the prefix or
    8063     *  both {@code null}
    8064     */
    8065    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
    8066        if (str == null || prefix == null) {
    8067            return str == prefix;
    8068        }
    8069        if (prefix.length() > str.length()) {
    8070            return false;
    8071        }
    8072        return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
    8073    }
    8074
    8075    /**
    8076     * <p>Check if a CharSequence starts with any of the provided case-sensitive prefixes.</p>
    8077     *
    8078     * <pre>
    8079     * StringUtils.startsWithAny(null, null)      = false
    8080     * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
    8081     * StringUtils.startsWithAny("abcxyz", null)     = false
    8082     * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
    8083     * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
    8084     * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    8085     * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
    8086     * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
    8087     * </pre>
    8088     *
    8089     * @param sequence the CharSequence to check, may be null
    8090     * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
    8091     * @see StringUtils#startsWith(CharSequence, CharSequence)
    8092     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
    8093     *   the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
    8094     * @since 2.5
    8095     * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
    8096     */
    8097    public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
    8098        if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
    8099            return false;
    8100        }
    8101        for (final CharSequence searchString : searchStrings) {
    8102            if (startsWith(sequence, searchString)) {
    8103                return true;
    8104            }
    8105        }
    8106        return false;
    8107    }
    8108
    8109    /**
    8110     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>
    8111     *
    8112     * <p>{@code null}s are handled without exceptions. Two {@code null}
    8113     * references are considered to be equal. The comparison is case insensitive.</p>
    8114     *
    8115     * <pre>
    8116     * StringUtils.startsWithIgnoreCase(null, null)      = true
    8117     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
    8118     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
    8119     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
    8120     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
    8121     * </pre>
    8122     *
    8123     * @see java.lang.String#startsWith(String)
    8124     * @param str  the CharSequence to check, may be null
    8125     * @param prefix the prefix to find, may be null
    8126     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
    8127     *  both {@code null}
    8128     * @since 2.4
    8129     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
    8130     */
    8131    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
    8132        return startsWith(str, prefix, true);
    8133    }
    8134
    8135    // Stripping
    8136    //-----------------------------------------------------------------------
    8137    /**
    8138     * <p>Strips whitespace from the start and end of a String.</p>
    8139     *
    8140     * <p>This is similar to {@link #trim(String)} but removes whitespace.
    8141     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8142     *
    8143     * <p>A {@code null} input String returns {@code null}.</p>
    8144     *
    8145     * <pre>
    8146     * StringUtils.strip(null)     = null
    8147     * StringUtils.strip("")       = ""
    8148     * StringUtils.strip("   ")    = ""
    8149     * StringUtils.strip("abc")    = "abc"
    8150     * StringUtils.strip("  abc")  = "abc"
    8151     * StringUtils.strip("abc  ")  = "abc"
    8152     * StringUtils.strip(" abc ")  = "abc"
    8153     * StringUtils.strip(" ab c ") = "ab c"
    8154     * </pre>
    8155     *
    8156     * @param str  the String to remove whitespace from, may be null
    8157     * @return the stripped String, {@code null} if null String input
    8158     */
    8159    public static String strip(final String str) {
    8160        return strip(str, null);
    8161    }
    8162
    8163    /**
    8164     * <p>Strips any of a set of characters from the start and end of a String.
    8165     * This is similar to {@link String#trim()} but allows the characters
    8166     * to be stripped to be controlled.</p>
    8167     *
    8168     * <p>A {@code null} input String returns {@code null}.
    8169     * An empty string ("") input returns the empty string.</p>
    8170     *
    8171     * <p>If the stripChars String is {@code null}, whitespace is
    8172     * stripped as defined by {@link Character#isWhitespace(char)}.
    8173     * Alternatively use {@link #strip(String)}.</p>
    8174     *
    8175     * <pre>
    8176     * StringUtils.strip(null, *)          = null
    8177     * StringUtils.strip("", *)            = ""
    8178     * StringUtils.strip("abc", null)      = "abc"
    8179     * StringUtils.strip("  abc", null)    = "abc"
    8180     * StringUtils.strip("abc  ", null)    = "abc"
    8181     * StringUtils.strip(" abc ", null)    = "abc"
    8182     * StringUtils.strip("  abcyx", "xyz") = "  abc"
    8183     * </pre>
    8184     *
    8185     * @param str  the String to remove characters from, may be null
    8186     * @param stripChars  the characters to remove, null treated as whitespace
    8187     * @return the stripped String, {@code null} if null String input
    8188     */
    8189    public static String strip(String str, final String stripChars) {
    8190        if (isEmpty(str)) {
    8191            return str;
    8192        }
    8193        str = stripStart(str, stripChars);
    8194        return stripEnd(str, stripChars);
    8195    }
    8196
    8197    /**
    8198     * <p>Removes diacritics (~= accents) from a string. The case will not be altered.</p>
    8199     * <p>For instance, '&agrave;' will be replaced by 'a'.</p>
    8200     * <p>Note that ligatures will be left as is.</p>
    8201     *
    8202     * <pre>
    8203     * StringUtils.stripAccents(null)                = null
    8204     * StringUtils.stripAccents("")                  = ""
    8205     * StringUtils.stripAccents("control")           = "control"
    8206     * StringUtils.stripAccents("&eacute;clair")     = "eclair"
    8207     * </pre>
    8208     *
    8209     * @param input String to be stripped
    8210     * @return input text with diacritics removed
    8211     *
    8212     * @since 3.0
    8213     */
    8214    // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
    8215    public static String stripAccents(final String input) {
    8216        if (input == null) {
    8217            return null;
    8218        }
    8219        final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$
    8220        final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));
    8221        convertRemainingAccentCharacters(decomposed);
    8222        // Note that this doesn't correctly remove ligatures...
    8223        return pattern.matcher(decomposed).replaceAll(EMPTY);
    8224    }
    8225
    8226    // StripAll
    8227    //-----------------------------------------------------------------------
    8228    /**
    8229     * <p>Strips whitespace from the start and end of every String in an array.
    8230     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8231     *
    8232     * <p>A new array is returned each time, except for length zero.
    8233     * A {@code null} array will return {@code null}.
    8234     * An empty array will return itself.
    8235     * A {@code null} array entry will be ignored.</p>
    8236     *
    8237     * <pre>
    8238     * StringUtils.stripAll(null)             = null
    8239     * StringUtils.stripAll([])               = []
    8240     * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
    8241     * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
    8242     * </pre>
    8243     *
    8244     * @param strs  the array to remove whitespace from, may be null
    8245     * @return the stripped Strings, {@code null} if null array input
    8246     */
    8247    public static String[] stripAll(final String... strs) {
    8248        return stripAll(strs, null);
    8249    }
    8250
    8251    /**
    8252     * <p>Strips any of a set of characters from the start and end of every
    8253     * String in an array.</p>
    8254     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8255     *
    8256     * <p>A new array is returned each time, except for length zero.
    8257     * A {@code null} array will return {@code null}.
    8258     * An empty array will return itself.
    8259     * A {@code null} array entry will be ignored.
    8260     * A {@code null} stripChars will strip whitespace as defined by
    8261     * {@link Character#isWhitespace(char)}.</p>
    8262     *
    8263     * <pre>
    8264     * StringUtils.stripAll(null, *)                = null
    8265     * StringUtils.stripAll([], *)                  = []
    8266     * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
    8267     * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
    8268     * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
    8269     * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
    8270     * </pre>
    8271     *
    8272     * @param strs  the array to remove characters from, may be null
    8273     * @param stripChars  the characters to remove, null treated as whitespace
    8274     * @return the stripped Strings, {@code null} if null array input
    8275     */
    8276    public static String[] stripAll(final String[] strs, final String stripChars) {
    8277        int strsLen;
    8278        if (strs == null || (strsLen = strs.length) == 0) {
    8279            return strs;
    8280        }
    8281        final String[] newArr = new String[strsLen];
    8282        for (int i = 0; i < strsLen; i++) {
    8283            newArr[i] = strip(strs[i], stripChars);
    8284        }
    8285        return newArr;
    8286    }
    8287
    8288    /**
    8289     * <p>Strips any of a set of characters from the end of a String.</p>
    8290     *
    8291     * <p>A {@code null} input String returns {@code null}.
    8292     * An empty string ("") input returns the empty string.</p>
    8293     *
    8294     * <p>If the stripChars String is {@code null}, whitespace is
    8295     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    8296     *
    8297     * <pre>
    8298     * StringUtils.stripEnd(null, *)          = null
    8299     * StringUtils.stripEnd("", *)            = ""
    8300     * StringUtils.stripEnd("abc", "")        = "abc"
    8301     * StringUtils.stripEnd("abc", null)      = "abc"
    8302     * StringUtils.stripEnd("  abc", null)    = "  abc"
    8303     * StringUtils.stripEnd("abc  ", null)    = "abc"
    8304     * StringUtils.stripEnd(" abc ", null)    = " abc"
    8305     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
    8306     * StringUtils.stripEnd("120.00", ".0")   = "12"
    8307     * </pre>
    8308     *
    8309     * @param str  the String to remove characters from, may be null
    8310     * @param stripChars  the set of characters to remove, null treated as whitespace
    8311     * @return the stripped String, {@code null} if null String input
    8312     */
    8313    public static String stripEnd(final String str, final String stripChars) {
    8314        int end = length(str);
    8315        if (end == 0) {
    8316            return str;
    8317        }
    8318
    8319        if (stripChars == null) {
    8320            while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
    8321                end--;
    8322            }
    8323        } else if (stripChars.isEmpty()) {
    8324            return str;
    8325        } else {
    8326            while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
    8327                end--;
    8328            }
    8329        }
    8330        return str.substring(0, end);
    8331    }
    8332
    8333    /**
    8334     * <p>Strips any of a set of characters from the start of a String.</p>
    8335     *
    8336     * <p>A {@code null} input String returns {@code null}.
    8337     * An empty string ("") input returns the empty string.</p>
    8338     *
    8339     * <p>If the stripChars String is {@code null}, whitespace is
    8340     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    8341     *
    8342     * <pre>
    8343     * StringUtils.stripStart(null, *)          = null
    8344     * StringUtils.stripStart("", *)            = ""
    8345     * StringUtils.stripStart("abc", "")        = "abc"
    8346     * StringUtils.stripStart("abc", null)      = "abc"
    8347     * StringUtils.stripStart("  abc", null)    = "abc"
    8348     * StringUtils.stripStart("abc  ", null)    = "abc  "
    8349     * StringUtils.stripStart(" abc ", null)    = "abc "
    8350     * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
    8351     * </pre>
    8352     *
    8353     * @param str  the String to remove characters from, may be null
    8354     * @param stripChars  the characters to remove, null treated as whitespace
    8355     * @return the stripped String, {@code null} if null String input
    8356     */
    8357    public static String stripStart(final String str, final String stripChars) {
    8358        final int strLen = length(str);
    8359        if (strLen == 0) {
    8360            return str;
    8361        }
    8362        int start = 0;
    8363        if (stripChars == null) {
    8364            while (start != strLen && Character.isWhitespace(str.charAt(start))) {
    8365                start++;
    8366            }
    8367        } else if (stripChars.isEmpty()) {
    8368            return str;
    8369        } else {
    8370            while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
    8371                start++;
    8372            }
    8373        }
    8374        return str.substring(start);
    8375    }
    8376
    8377    /**
    8378     * <p>Strips whitespace from the start and end of a String  returning
    8379     * an empty String if {@code null} input.</p>
    8380     *
    8381     * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
    8382     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8383     *
    8384     * <pre>
    8385     * StringUtils.stripToEmpty(null)     = ""
    8386     * StringUtils.stripToEmpty("")       = ""
    8387     * StringUtils.stripToEmpty("   ")    = ""
    8388     * StringUtils.stripToEmpty("abc")    = "abc"
    8389     * StringUtils.stripToEmpty("  abc")  = "abc"
    8390     * StringUtils.stripToEmpty("abc  ")  = "abc"
    8391     * StringUtils.stripToEmpty(" abc ")  = "abc"
    8392     * StringUtils.stripToEmpty(" ab c ") = "ab c"
    8393     * </pre>
    8394     *
    8395     * @param str  the String to be stripped, may be null
    8396     * @return the trimmed String, or an empty String if {@code null} input
    8397     * @since 2.0
    8398     */
    8399    public static String stripToEmpty(final String str) {
    8400        return str == null ? EMPTY : strip(str, null);
    8401    }
    8402
    8403    /**
    8404     * <p>Strips whitespace from the start and end of a String  returning
    8405     * {@code null} if the String is empty ("") after the strip.</p>
    8406     *
    8407     * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
    8408     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8409     *
    8410     * <pre>
    8411     * StringUtils.stripToNull(null)     = null
    8412     * StringUtils.stripToNull("")       = null
    8413     * StringUtils.stripToNull("   ")    = null
    8414     * StringUtils.stripToNull("abc")    = "abc"
    8415     * StringUtils.stripToNull("  abc")  = "abc"
    8416     * StringUtils.stripToNull("abc  ")  = "abc"
    8417     * StringUtils.stripToNull(" abc ")  = "abc"
    8418     * StringUtils.stripToNull(" ab c ") = "ab c"
    8419     * </pre>
    8420     *
    8421     * @param str  the String to be stripped, may be null
    8422     * @return the stripped String,
    8423     *  {@code null} if whitespace, empty or null String input
    8424     * @since 2.0
    8425     */
    8426    public static String stripToNull(String str) {
    8427        if (str == null) {
    8428            return null;
    8429        }
    8430        str = strip(str, null);
    8431        return str.isEmpty() ? null : str;
    8432    }
    8433
    8434    // Substring
    8435    //-----------------------------------------------------------------------
    8436    /**
    8437     * <p>Gets a substring from the specified String avoiding exceptions.</p>
    8438     *
    8439     * <p>A negative start position can be used to start {@code n}
    8440     * characters from the end of the String.</p>
    8441     *
    8442     * <p>A {@code null} String will return {@code null}.
    8443     * An empty ("") String will return "".</p>
    8444     *
    8445     * <pre>
    8446     * StringUtils.substring(null, *)   = null
    8447     * StringUtils.substring("", *)     = ""
    8448     * StringUtils.substring("abc", 0)  = "abc"
    8449     * StringUtils.substring("abc", 2)  = "c"
    8450     * StringUtils.substring("abc", 4)  = ""
    8451     * StringUtils.substring("abc", -2) = "bc"
    8452     * StringUtils.substring("abc", -4) = "abc"
    8453     * </pre>
    8454     *
    8455     * @param str  the String to get the substring from, may be null
    8456     * @param start  the position to start from, negative means
    8457     *  count back from the end of the String by this many characters
    8458     * @return substring from start position, {@code null} if null String input
    8459     */
    8460    public static String substring(final String str, int start) {
    8461        if (str == null) {
    8462            return null;
    8463        }
    8464
    8465        // handle negatives, which means last n characters
    8466        if (start < 0) {
    8467            start = str.length() + start; // remember start is negative
    8468        }
    8469
    8470        if (start < 0) {
    8471            start = 0;
    8472        }
    8473        if (start > str.length()) {
    8474            return EMPTY;
    8475        }
    8476
    8477        return str.substring(start);
    8478    }
    8479
    8480    /**
    8481     * <p>Gets a substring from the specified String avoiding exceptions.</p>
    8482     *
    8483     * <p>A negative start position can be used to start/end {@code n}
    8484     * characters from the end of the String.</p>
    8485     *
    8486     * <p>The returned substring starts with the character in the {@code start}
    8487     * position and ends before the {@code end} position. All position counting is
    8488     * zero-based -- i.e., to start at the beginning of the string use
    8489     * {@code start = 0}. Negative start and end positions can be used to
    8490     * specify offsets relative to the end of the String.</p>
    8491     *
    8492     * <p>If {@code start} is not strictly to the left of {@code end}, ""
    8493     * is returned.</p>
    8494     *
    8495     * <pre>
    8496     * StringUtils.substring(null, *, *)    = null
    8497     * StringUtils.substring("", * ,  *)    = "";
    8498     * StringUtils.substring("abc", 0, 2)   = "ab"
    8499     * StringUtils.substring("abc", 2, 0)   = ""
    8500     * StringUtils.substring("abc", 2, 4)   = "c"
    8501     * StringUtils.substring("abc", 4, 6)   = ""
    8502     * StringUtils.substring("abc", 2, 2)   = ""
    8503     * StringUtils.substring("abc", -2, -1) = "b"
    8504     * StringUtils.substring("abc", -4, 2)  = "ab"
    8505     * </pre>
    8506     *
    8507     * @param str  the String to get the substring from, may be null
    8508     * @param start  the position to start from, negative means
    8509     *  count back from the end of the String by this many characters
    8510     * @param end  the position to end at (exclusive), negative means
    8511     *  count back from the end of the String by this many characters
    8512     * @return substring from start position to end position,
    8513     *  {@code null} if null String input
    8514     */
    8515    public static String substring(final String str, int start, int end) {
    8516        if (str == null) {
    8517            return null;
    8518        }
    8519
    8520        // handle negatives
    8521        if (end < 0) {
    8522            end = str.length() + end; // remember end is negative
    8523        }
    8524        if (start < 0) {
    8525            start = str.length() + start; // remember start is negative
    8526        }
    8527
    8528        // check length next
    8529        if (end > str.length()) {
    8530            end = str.length();
    8531        }
    8532
    8533        // if start is greater than end, return ""
    8534        if (start > end) {
    8535            return EMPTY;
    8536        }
    8537
    8538        if (start < 0) {
    8539            start = 0;
    8540        }
    8541        if (end < 0) {
    8542            end = 0;
    8543        }
    8544
    8545        return str.substring(start, end);
    8546    }
    8547
    8548    /**
    8549     * <p>Gets the substring after the first occurrence of a separator.
    8550     * The separator is not returned.</p>
    8551     *
    8552     * <p>A {@code null} string input will return {@code null}.
    8553     * An empty ("") string input will return the empty string.
    8554     * A {@code null} separator will return the empty string if the
    8555     * input string is not {@code null}.</p>
    8556     *
    8557     * <p>If nothing is found, the empty string is returned.</p>
    8558     *
    8559     * <pre>
    8560     * StringUtils.substringAfter(null, *)      = null
    8561     * StringUtils.substringAfter("", *)        = ""
    8562     * StringUtils.substringAfter(*, null)      = ""
    8563     * StringUtils.substringAfter("abc", "a")   = "bc"
    8564     * StringUtils.substringAfter("abcba", "b") = "cba"
    8565     * StringUtils.substringAfter("abc", "c")   = ""
    8566     * StringUtils.substringAfter("abc", "d")   = ""
    8567     * StringUtils.substringAfter("abc", "")    = "abc"
    8568     * </pre>
    8569     *
    8570     * @param str  the String to get a substring from, may be null
    8571     * @param separator  the String to search for, may be null
    8572     * @return the substring after the first occurrence of the separator,
    8573     *  {@code null} if null String input
    8574     * @since 2.0
    8575     */
    8576    public static String substringAfter(final String str, final String separator) {
    8577        if (isEmpty(str)) {
    8578            return str;
    8579        }
    8580        if (separator == null) {
    8581            return EMPTY;
    8582        }
    8583        final int pos = str.indexOf(separator);
    8584        if (pos == INDEX_NOT_FOUND) {
    8585            return EMPTY;
    8586        }
    8587        return str.substring(pos + separator.length());
    8588    }
    8589
    8590    // startsWith
    8591    //-----------------------------------------------------------------------
    8592
    8593    /**
    8594     * <p>Gets the substring after the last occurrence of a separator.
    8595     * The separator is not returned.</p>
    8596     *
    8597     * <p>A {@code null} string input will return {@code null}.
    8598     * An empty ("") string input will return the empty string.
    8599     * An empty or {@code null} separator will return the empty string if
    8600     * the input string is not {@code null}.</p>
    8601     *
    8602     * <p>If nothing is found, the empty string is returned.</p>
    8603     *
    8604     * <pre>
    8605     * StringUtils.substringAfterLast(null, *)      = null
    8606     * StringUtils.substringAfterLast("", *)        = ""
    8607     * StringUtils.substringAfterLast(*, "")        = ""
    8608     * StringUtils.substringAfterLast(*, null)      = ""
    8609     * StringUtils.substringAfterLast("abc", "a")   = "bc"
    8610     * StringUtils.substringAfterLast("abcba", "b") = "a"
    8611     * StringUtils.substringAfterLast("abc", "c")   = ""
    8612     * StringUtils.substringAfterLast("a", "a")     = ""
    8613     * StringUtils.substringAfterLast("a", "z")     = ""
    8614     * </pre>
    8615     *
    8616     * @param str  the String to get a substring from, may be null
    8617     * @param separator  the String to search for, may be null
    8618     * @return the substring after the last occurrence of the separator,
    8619     *  {@code null} if null String input
    8620     * @since 2.0
    8621     */
    8622    public static String substringAfterLast(final String str, final String separator) {
    8623        if (isEmpty(str)) {
    8624            return str;
    8625        }
    8626        if (isEmpty(separator)) {
    8627            return EMPTY;
    8628        }
    8629        final int pos = str.lastIndexOf(separator);
    8630        if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
    8631            return EMPTY;
    8632        }
    8633        return str.substring(pos + separator.length());
    8634    }
    8635
    8636    // SubStringAfter/SubStringBefore
    8637    //-----------------------------------------------------------------------
    8638    /**
    8639     * <p>Gets the substring before the first occurrence of a separator.
    8640     * The separator is not returned.</p>
    8641     *
    8642     * <p>A {@code null} string input will return {@code null}.
    8643     * An empty ("") string input will return the empty string.
    8644     * A {@code null} separator will return the input string.</p>
    8645     *
    8646     * <p>If nothing is found, the string input is returned.</p>
    8647     *
    8648     * <pre>
    8649     * StringUtils.substringBefore(null, *)      = null
    8650     * StringUtils.substringBefore("", *)        = ""
    8651     * StringUtils.substringBefore("abc", "a")   = ""
    8652     * StringUtils.substringBefore("abcba", "b") = "a"
    8653     * StringUtils.substringBefore("abc", "c")   = "ab"
    8654     * StringUtils.substringBefore("abc", "d")   = "abc"
    8655     * StringUtils.substringBefore("abc", "")    = ""
    8656     * StringUtils.substringBefore("abc", null)  = "abc"
    8657     * </pre>
    8658     *
    8659     * @param str  the String to get a substring from, may be null
    8660     * @param separator  the String to search for, may be null
    8661     * @return the substring before the first occurrence of the separator,
    8662     *  {@code null} if null String input
    8663     * @since 2.0
    8664     */
    8665    public static String substringBefore(final String str, final String separator) {
    8666        if (isEmpty(str) || separator == null) {
    8667            return str;
    8668        }
    8669        if (separator.isEmpty()) {
    8670            return EMPTY;
    8671        }
    8672        final int pos = str.indexOf(separator);
    8673        if (pos == INDEX_NOT_FOUND) {
    8674            return str;
    8675        }
    8676        return str.substring(0, pos);
    8677    }
    8678
    8679    /**
    8680     * <p>Gets the substring before the last occurrence of a separator.
    8681     * The separator is not returned.</p>
    8682     *
    8683     * <p>A {@code null} string input will return {@code null}.
    8684     * An empty ("") string input will return the empty string.
    8685     * An empty or {@code null} separator will return the input string.</p>
    8686     *
    8687     * <p>If nothing is found, the string input is returned.</p>
    8688     *
    8689     * <pre>
    8690     * StringUtils.substringBeforeLast(null, *)      = null
    8691     * StringUtils.substringBeforeLast("", *)        = ""
    8692     * StringUtils.substringBeforeLast("abcba", "b") = "abc"
    8693     * StringUtils.substringBeforeLast("abc", "c")   = "ab"
    8694     * StringUtils.substringBeforeLast("a", "a")     = ""
    8695     * StringUtils.substringBeforeLast("a", "z")     = "a"
    8696     * StringUtils.substringBeforeLast("a", null)    = "a"
    8697     * StringUtils.substringBeforeLast("a", "")      = "a"
    8698     * </pre>
    8699     *
    8700     * @param str  the String to get a substring from, may be null
    8701     * @param separator  the String to search for, may be null
    8702     * @return the substring before the last occurrence of the separator,
    8703     *  {@code null} if null String input
    8704     * @since 2.0
    8705     */
    8706    public static String substringBeforeLast(final String str, final String separator) {
    8707        if (isEmpty(str) || isEmpty(separator)) {
    8708            return str;
    8709        }
    8710        final int pos = str.lastIndexOf(separator);
    8711        if (pos == INDEX_NOT_FOUND) {
    8712            return str;
    8713        }
    8714        return str.substring(0, pos);
    8715    }
    8716
    8717    // Substring between
    8718    //-----------------------------------------------------------------------
    8719    /**
    8720     * <p>Gets the String that is nested in between two instances of the
    8721     * same String.</p>
    8722     *
    8723     * <p>A {@code null} input String returns {@code null}.
    8724     * A {@code null} tag returns {@code null}.</p>
    8725     *
    8726     * <pre>
    8727     * StringUtils.substringBetween(null, *)            = null
    8728     * StringUtils.substringBetween("", "")             = ""
    8729     * StringUtils.substringBetween("", "tag")          = null
    8730     * StringUtils.substringBetween("tagabctag", null)  = null
    8731     * StringUtils.substringBetween("tagabctag", "")    = ""
    8732     * StringUtils.substringBetween("tagabctag", "tag") = "abc"
    8733     * </pre>
    8734     *
    8735     * @param str  the String containing the substring, may be null
    8736     * @param tag  the String before and after the substring, may be null
    8737     * @return the substring, {@code null} if no match
    8738     * @since 2.0
    8739     */
    8740    public static String substringBetween(final String str, final String tag) {
    8741        return substringBetween(str, tag, tag);
    8742    }
    8743
    8744    // endsWith
    8745    //-----------------------------------------------------------------------
    8746
    8747    /**
    8748     * <p>Gets the String that is nested in between two Strings.
    8749     * Only the first match is returned.</p>
    8750     *
    8751     * <p>A {@code null} input String returns {@code null}.
    8752     * A {@code null} open/close returns {@code null} (no match).
    8753     * An empty ("") open and close returns an empty string.</p>
    8754     *
    8755     * <pre>
    8756     * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
    8757     * StringUtils.substringBetween(null, *, *)          = null
    8758     * StringUtils.substringBetween(*, null, *)          = null
    8759     * StringUtils.substringBetween(*, *, null)          = null
    8760     * StringUtils.substringBetween("", "", "")          = ""
    8761     * StringUtils.substringBetween("", "", "]")         = null
    8762     * StringUtils.substringBetween("", "[", "]")        = null
    8763     * StringUtils.substringBetween("yabcz", "", "")     = ""
    8764     * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
    8765     * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
    8766     * </pre>
    8767     *
    8768     * @param str  the String containing the substring, may be null
    8769     * @param open  the String before the substring, may be null
    8770     * @param close  the String after the substring, may be null
    8771     * @return the substring, {@code null} if no match
    8772     * @since 2.0
    8773     */
    8774    public static String substringBetween(final String str, final String open, final String close) {
    8775        if (str == null || open == null || close == null) {
    8776            return null;
    8777        }
    8778        final int start = str.indexOf(open);
    8779        if (start != INDEX_NOT_FOUND) {
    8780            final int end = str.indexOf(close, start + open.length());
    8781            if (end != INDEX_NOT_FOUND) {
    8782                return str.substring(start + open.length(), end);
    8783            }
    8784        }
    8785        return null;
    8786    }
    8787
    8788    /**
    8789     * <p>Searches a String for substrings delimited by a start and end tag,
    8790     * returning all matching substrings in an array.</p>
    8791     *
    8792     * <p>A {@code null} input String returns {@code null}.
    8793     * A {@code null} open/close returns {@code null} (no match).
    8794     * An empty ("") open/close returns {@code null} (no match).</p>
    8795     *
    8796     * <pre>
    8797     * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
    8798     * StringUtils.substringsBetween(null, *, *)            = null
    8799     * StringUtils.substringsBetween(*, null, *)            = null
    8800     * StringUtils.substringsBetween(*, *, null)            = null
    8801     * StringUtils.substringsBetween("", "[", "]")          = []
    8802     * </pre>
    8803     *
    8804     * @param str  the String containing the substrings, null returns null, empty returns empty
    8805     * @param open  the String identifying the start of the substring, empty returns null
    8806     * @param close  the String identifying the end of the substring, empty returns null
    8807     * @return a String Array of substrings, or {@code null} if no match
    8808     * @since 2.3
    8809     */
    8810    public static String[] substringsBetween(final String str, final String open, final String close) {
    8811        if (str == null || isEmpty(open) || isEmpty(close)) {
    8812            return null;
    8813        }
    8814        final int strLen = str.length();
    8815        if (strLen == 0) {
    8816            return ArrayUtils.EMPTY_STRING_ARRAY;
    8817        }
    8818        final int closeLen = close.length();
    8819        final int openLen = open.length();
    8820        final List<String> list = new ArrayList<>();
    8821        int pos = 0;
    8822        while (pos < strLen - closeLen) {
    8823            int start = str.indexOf(open, pos);
    8824            if (start < 0) {
    8825                break;
    8826            }
    8827            start += openLen;
    8828            final int end = str.indexOf(close, start);
    8829            if (end < 0) {
    8830                break;
    8831            }
    8832            list.add(str.substring(start, end));
    8833            pos = end + closeLen;
    8834        }
    8835        if (list.isEmpty()) {
    8836            return null;
    8837        }
    8838        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    8839    }
    8840
    8841    /**
    8842     * <p>Swaps the case of a String changing upper and title case to
    8843     * lower case, and lower case to upper case.</p>
    8844     *
    8845     * <ul>
    8846     *  <li>Upper case character converts to Lower case</li>
    8847     *  <li>Title case character converts to Lower case</li>
    8848     *  <li>Lower case character converts to Upper case</li>
    8849     * </ul>
    8850     *
    8851     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}.
    8852     * A {@code null} input String returns {@code null}.</p>
    8853     *
    8854     * <pre>
    8855     * StringUtils.swapCase(null)                 = null
    8856     * StringUtils.swapCase("")                   = ""
    8857     * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
    8858     * </pre>
    8859     *
    8860     * <p>NOTE: This method changed in Lang version 2.0.
    8861     * It no longer performs a word based algorithm.
    8862     * If you only use ASCII, you will notice no change.
    8863     * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p>
    8864     *
    8865     * @param str  the String to swap case, may be null
    8866     * @return the changed String, {@code null} if null String input
    8867     */
    8868    public static String swapCase(final String str) {
    8869        if (isEmpty(str)) {
    8870            return str;
    8871        }
    8872
    8873        final int strLen = str.length();
    8874        final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
    8875        int outOffset = 0;
    8876        for (int i = 0; i < strLen; ) {
    8877            final int oldCodepoint = str.codePointAt(i);
    8878            final int newCodePoint;
    8879            if (Character.isUpperCase(oldCodepoint)) {
    8880                newCodePoint = Character.toLowerCase(oldCodepoint);
    8881            } else if (Character.isTitleCase(oldCodepoint)) {
    8882                newCodePoint = Character.toLowerCase(oldCodepoint);
    8883            } else if (Character.isLowerCase(oldCodepoint)) {
    8884                newCodePoint = Character.toUpperCase(oldCodepoint);
    8885            } else {
    8886                newCodePoint = oldCodepoint;
    8887            }
    8888            newCodePoints[outOffset++] = newCodePoint;
    8889            i += Character.charCount(newCodePoint);
    8890         }
    8891        return new String(newCodePoints, 0, outOffset);
    8892    }
    8893
    8894    /**
    8895     * <p>Converts a {@code CharSequence} into an array of code points.</p>
    8896     *
    8897     * <p>Valid pairs of surrogate code units will be converted into a single supplementary
    8898     * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or
    8899     * a low surrogate not preceded by a high surrogate) will be returned as-is.</p>
    8900     *
    8901     * <pre>
    8902     * StringUtils.toCodePoints(null)   =  null
    8903     * StringUtils.toCodePoints("")     =  []  // empty array
    8904     * </pre>
    8905     *
    8906     * @param str the character sequence to convert
    8907     * @return an array of code points
    8908     * @since 3.6
    8909     */
    8910    public static int[] toCodePoints(final CharSequence str) {
    8911        if (str == null) {
    8912            return null;
    8913        }
    8914        if (str.length() == 0) {
    8915            return ArrayUtils.EMPTY_INT_ARRAY;
    8916        }
    8917
    8918        final String s = str.toString();
    8919        final int[] result = new int[s.codePointCount(0, s.length())];
    8920        int index = 0;
    8921        for (int i = 0; i < result.length; i++) {
    8922            result[i] = s.codePointAt(index);
    8923            index += Character.charCount(result[i]);
    8924        }
    8925        return result;
    8926    }
    8927
    8928    /**
    8929     * Converts a {@code byte[]} to a String using the specified character encoding.
    8930     *
    8931     * @param bytes
    8932     *            the byte array to read from
    8933     * @param charset
    8934     *            the encoding to use, if null then use the platform default
    8935     * @return a new String
    8936     * @throws NullPointerException
    8937     *             if {@code bytes} is null
    8938     * @since 3.2
    8939     * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
    8940     */
    8941    public static String toEncodedString(final byte[] bytes, final Charset charset) {
    8942        return new String(bytes, Charsets.toCharset(charset));
    8943    }
    8944
    8945    /**
    8946     * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
    8947     *
    8948     * @param source A source String or null.
    8949     * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null.
    8950     * @since 3.10
    8951     */
    8952    public static String toRootLowerCase(final String source) {
    8953        return source == null ? null : source.toLowerCase(Locale.ROOT);
    8954    }
    8955
    8956    /**
    8957     * Converts the given source String as a upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
    8958     *
    8959     * @param source A source String or null.
    8960     * @return the given source String as a upper-case using the {@link Locale#ROOT} locale or null.
    8961     * @since 3.10
    8962     */
    8963    public static String toRootUpperCase(final String source) {
    8964        return source == null ? null : source.toUpperCase(Locale.ROOT);
    8965    }
    8966
    8967    /**
    8968     * Converts a {@code byte[]} to a String using the specified character encoding.
    8969     *
    8970     * @param bytes
    8971     *            the byte array to read from
    8972     * @param charsetName
    8973     *            the encoding to use, if null then use the platform default
    8974     * @return a new String
    8975     * @throws UnsupportedEncodingException
    8976     *             If the named charset is not supported
    8977     * @throws NullPointerException
    8978     *             if the input is null
    8979     * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
    8980     * @since 3.1
    8981     */
    8982    @Deprecated
    8983    public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException {
    8984        return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset());
    8985    }
    8986
    8987    // Trim
    8988    //-----------------------------------------------------------------------
    8989    /**
    8990     * <p>Removes control characters (char &lt;= 32) from both
    8991     * ends of this String, handling {@code null} by returning
    8992     * {@code null}.</p>
    8993     *
    8994     * <p>The String is trimmed using {@link String#trim()}.
    8995     * Trim removes start and end characters &lt;= 32.
    8996     * To strip whitespace use {@link #strip(String)}.</p>
    8997     *
    8998     * <p>To trim your choice of characters, use the
    8999     * {@link #strip(String, String)} methods.</p>
    9000     *
    9001     * <pre>
    9002     * StringUtils.trim(null)          = null
    9003     * StringUtils.trim("")            = ""
    9004     * StringUtils.trim("     ")       = ""
    9005     * StringUtils.trim("abc")         = "abc"
    9006     * StringUtils.trim("    abc    ") = "abc"
    9007     * </pre>
    9008     *
    9009     * @param str  the String to be trimmed, may be null
    9010     * @return the trimmed string, {@code null} if null String input
    9011     */
    9012    public static String trim(final String str) {
    9013        return str == null ? null : str.trim();
    9014    }
    9015
    9016    /**
    9017     * <p>Removes control characters (char &lt;= 32) from both
    9018     * ends of this String returning an empty String ("") if the String
    9019     * is empty ("") after the trim or if it is {@code null}.
    9020     *
    9021     * <p>The String is trimmed using {@link String#trim()}.
    9022     * Trim removes start and end characters &lt;= 32.
    9023     * To strip whitespace use {@link #stripToEmpty(String)}.</p>
    9024     *
    9025     * <pre>
    9026     * StringUtils.trimToEmpty(null)          = ""
    9027     * StringUtils.trimToEmpty("")            = ""
    9028     * StringUtils.trimToEmpty("     ")       = ""
    9029     * StringUtils.trimToEmpty("abc")         = "abc"
    9030     * StringUtils.trimToEmpty("    abc    ") = "abc"
    9031     * </pre>
    9032     *
    9033     * @param str  the String to be trimmed, may be null
    9034     * @return the trimmed String, or an empty String if {@code null} input
    9035     * @since 2.0
    9036     */
    9037    public static String trimToEmpty(final String str) {
    9038        return str == null ? EMPTY : str.trim();
    9039    }
    9040
    9041    /**
    9042     * <p>Removes control characters (char &lt;= 32) from both
    9043     * ends of this String returning {@code null} if the String is
    9044     * empty ("") after the trim or if it is {@code null}.
    9045     *
    9046     * <p>The String is trimmed using {@link String#trim()}.
    9047     * Trim removes start and end characters &lt;= 32.
    9048     * To strip whitespace use {@link #stripToNull(String)}.</p>
    9049     *
    9050     * <pre>
    9051     * StringUtils.trimToNull(null)          = null
    9052     * StringUtils.trimToNull("")            = null
    9053     * StringUtils.trimToNull("     ")       = null
    9054     * StringUtils.trimToNull("abc")         = "abc"
    9055     * StringUtils.trimToNull("    abc    ") = "abc"
    9056     * </pre>
    9057     *
    9058     * @param str  the String to be trimmed, may be null
    9059     * @return the trimmed String,
    9060     *  {@code null} if only chars &lt;= 32, empty or null String input
    9061     * @since 2.0
    9062     */
    9063    public static String trimToNull(final String str) {
    9064        final String ts = trim(str);
    9065        return isEmpty(ts) ? null : ts;
    9066    }
    9067
    9068    /**
    9069     * <p>Truncates a String. This will turn
    9070     * "Now is the time for all good men" into "Now is the time for".</p>
    9071     *
    9072     * <p>Specifically:</p>
    9073     * <ul>
    9074     *   <li>If {@code str} is less than {@code maxWidth} characters
    9075     *       long, return it.</li>
    9076     *   <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
    9077     *   <li>If {@code maxWidth} is less than {@code 0}, throw an
    9078     *       {@code IllegalArgumentException}.</li>
    9079     *   <li>In no case will it return a String of length greater than
    9080     *       {@code maxWidth}.</li>
    9081     * </ul>
    9082     *
    9083     * <pre>
    9084     * StringUtils.truncate(null, 0)       = null
    9085     * StringUtils.truncate(null, 2)       = null
    9086     * StringUtils.truncate("", 4)         = ""
    9087     * StringUtils.truncate("abcdefg", 4)  = "abcd"
    9088     * StringUtils.truncate("abcdefg", 6)  = "abcdef"
    9089     * StringUtils.truncate("abcdefg", 7)  = "abcdefg"
    9090     * StringUtils.truncate("abcdefg", 8)  = "abcdefg"
    9091     * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
    9092     * </pre>
    9093     *
    9094     * @param str  the String to truncate, may be null
    9095     * @param maxWidth  maximum length of result String, must be positive
    9096     * @return truncated String, {@code null} if null String input
    9097     * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}
    9098     * @since 3.5
    9099     */
    9100    public static String truncate(final String str, final int maxWidth) {
    9101        return truncate(str, 0, maxWidth);
    9102    }
    9103
    9104    /**
    9105     * <p>Truncates a String. This will turn
    9106     * "Now is the time for all good men" into "is the time for all".</p>
    9107     *
    9108     * <p>Works like {@code truncate(String, int)}, but allows you to specify
    9109     * a "left edge" offset.
    9110     *
    9111     * <p>Specifically:</p>
    9112     * <ul>
    9113     *   <li>If {@code str} is less than {@code maxWidth} characters
    9114     *       long, return it.</li>
    9115     *   <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
    9116     *   <li>If {@code maxWidth} is less than {@code 0}, throw an
    9117     *       {@code IllegalArgumentException}.</li>
    9118     *   <li>If {@code offset} is less than {@code 0}, throw an
    9119     *       {@code IllegalArgumentException}.</li>
    9120     *   <li>In no case will it return a String of length greater than
    9121     *       {@code maxWidth}.</li>
    9122     * </ul>
    9123     *
    9124     * <pre>
    9125     * StringUtils.truncate(null, 0, 0) = null
    9126     * StringUtils.truncate(null, 2, 4) = null
    9127     * StringUtils.truncate("", 0, 10) = ""
    9128     * StringUtils.truncate("", 2, 10) = ""
    9129     * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
    9130     * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
    9131     * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
    9132     * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
    9133     * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
    9134     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
    9135     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
    9136     * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
    9137     * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
    9138     * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
    9139     * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
    9140     * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
    9141     * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
    9142     * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
    9143     * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
    9144     * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
    9145     * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
    9146     * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
    9147     * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
    9148     * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
    9149     * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
    9150     * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
    9151     * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
    9152     * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
    9153     * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
    9154     * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
    9155     * </pre>
    9156     *
    9157     * @param str  the String to truncate, may be null
    9158     * @param offset  left edge of source String
    9159     * @param maxWidth  maximum length of result String, must be positive
    9160     * @return truncated String, {@code null} if null String input
    9161     * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}
    9162     * @since 3.5
    9163     */
    9164    public static String truncate(final String str, final int offset, final int maxWidth) {
    9165        if (offset < 0) {
    9166            throw new IllegalArgumentException("offset cannot be negative");
    9167        }
    9168        if (maxWidth < 0) {
    9169            throw new IllegalArgumentException("maxWith cannot be negative");
    9170        }
    9171        if (str == null) {
    9172            return null;
    9173        }
    9174        if (offset > str.length()) {
    9175            return EMPTY;
    9176        }
    9177        if (str.length() > maxWidth) {
    9178            final int ix = offset + maxWidth > str.length() ? str.length() : offset + maxWidth;
    9179            return str.substring(offset, ix);
    9180        }
    9181        return str.substring(offset);
    9182    }
    9183
    9184    /**
    9185     * <p>Uncapitalizes a String, changing the first character to lower case as
    9186     * per {@link Character#toLowerCase(int)}. No other characters are changed.</p>
    9187     *
    9188     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}.
    9189     * A {@code null} input String returns {@code null}.</p>
    9190     *
    9191     * <pre>
    9192     * StringUtils.uncapitalize(null)  = null
    9193     * StringUtils.uncapitalize("")    = ""
    9194     * StringUtils.uncapitalize("cat") = "cat"
    9195     * StringUtils.uncapitalize("Cat") = "cat"
    9196     * StringUtils.uncapitalize("CAT") = "cAT"
    9197     * </pre>
    9198     *
    9199     * @param str the String to uncapitalize, may be null
    9200     * @return the uncapitalized String, {@code null} if null String input
    9201     * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String)
    9202     * @see #capitalize(String)
    9203     * @since 2.0
    9204     */
    9205    public static String uncapitalize(final String str) {
    9206        final int strLen = length(str);
    9207        if (strLen == 0) {
    9208            return str;
    9209        }
    9210
    9211        final int firstCodepoint = str.codePointAt(0);
    9212        final int newCodePoint = Character.toLowerCase(firstCodepoint);
    9213        if (firstCodepoint == newCodePoint) {
    9214            // already capitalized
    9215            return str;
    9216        }
    9217
    9218        final int newCodePoints[] = new int[strLen]; // cannot be longer than the char array
    9219        int outOffset = 0;
    9220        newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
    9221        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
    9222            final int codepoint = str.codePointAt(inOffset);
    9223            newCodePoints[outOffset++] = codepoint; // copy the remaining ones
    9224            inOffset += Character.charCount(codepoint);
    9225         }
    9226        return new String(newCodePoints, 0, outOffset);
    9227    }
    9228
    9229    /**
    9230     * <p>
    9231     * Unwraps a given string from a character.
    9232     * </p>
    9233     *
    9234     * <pre>
    9235     * StringUtils.unwrap(null, null)         = null
    9236     * StringUtils.unwrap(null, '\0')         = null
    9237     * StringUtils.unwrap(null, '1')          = null
    9238     * StringUtils.unwrap("a", 'a')           = "a"
    9239     * StringUtils.unwrap("aa", 'a')           = ""
    9240     * StringUtils.unwrap("\'abc\'", '\'')    = "abc"
    9241     * StringUtils.unwrap("AABabcBAA", 'A')   = "ABabcBA"
    9242     * StringUtils.unwrap("A", '#')           = "A"
    9243     * StringUtils.unwrap("#A", '#')          = "#A"
    9244     * StringUtils.unwrap("A#", '#')          = "A#"
    9245     * </pre>
    9246     *
    9247     * @param str
    9248     *          the String to be unwrapped, can be null
    9249     * @param wrapChar
    9250     *          the character used to unwrap
    9251     * @return unwrapped String or the original string
    9252     *          if it is not quoted properly with the wrapChar
    9253     * @since 3.6
    9254     */
    9255    public static String unwrap(final String str, final char wrapChar) {
    9256        if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
    9257            return str;
    9258        }
    9259
    9260        if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
    9261            final int startIndex = 0;
    9262            final int endIndex = str.length() - 1;
    9263
    9264            return str.substring(startIndex + 1, endIndex);
    9265        }
    9266
    9267        return str;
    9268    }
    9269
    9270    /**
    9271     * <p>
    9272     * Unwraps a given string from anther string.
    9273     * </p>
    9274     *
    9275     * <pre>
    9276     * StringUtils.unwrap(null, null)         = null
    9277     * StringUtils.unwrap(null, "")           = null
    9278     * StringUtils.unwrap(null, "1")          = null
    9279     * StringUtils.unwrap("a", "a")           = "a"
    9280     * StringUtils.unwrap("aa", "a")          = ""
    9281     * StringUtils.unwrap("\'abc\'", "\'")    = "abc"
    9282     * StringUtils.unwrap("\"abc\"", "\"")    = "abc"
    9283     * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"
    9284     * StringUtils.unwrap("A", "#")           = "A"
    9285     * StringUtils.unwrap("#A", "#")          = "#A"
    9286     * StringUtils.unwrap("A#", "#")          = "A#"
    9287     * </pre>
    9288     *
    9289     * @param str
    9290     *          the String to be unwrapped, can be null
    9291     * @param wrapToken
    9292     *          the String used to unwrap
    9293     * @return unwrapped String or the original string
    9294     *          if it is not quoted properly with the wrapToken
    9295     * @since 3.6
    9296     */
    9297    public static String unwrap(final String str, final String wrapToken) {
    9298        if (isEmpty(str) || isEmpty(wrapToken) || str.length() == 1) {
    9299            return str;
    9300        }
    9301
    9302        if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) {
    9303            final int startIndex = str.indexOf(wrapToken);
    9304            final int endIndex = str.lastIndexOf(wrapToken);
    9305            final int wrapLength = wrapToken.length();
    9306
    9307            if (startIndex != -1 && endIndex != -1) {
    9308                return str.substring(startIndex + wrapLength, endIndex);
    9309            }
    9310        }
    9311
    9312        return str;
    9313    }
    9314
    9315    // Case conversion
    9316    //-----------------------------------------------------------------------
    9317    /**
    9318     * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
    9319     *
    9320     * <p>A {@code null} input String returns {@code null}.</p>
    9321     *
    9322     * <pre>
    9323     * StringUtils.upperCase(null)  = null
    9324     * StringUtils.upperCase("")    = ""
    9325     * StringUtils.upperCase("aBc") = "ABC"
    9326     * </pre>
    9327     *
    9328     * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
    9329     * the result of this method is affected by the current locale.
    9330     * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    9331     * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    9332     *
    9333     * @param str  the String to upper case, may be null
    9334     * @return the upper cased String, {@code null} if null String input
    9335     */
    9336    public static String upperCase(final String str) {
    9337        if (str == null) {
    9338            return null;
    9339        }
    9340        return str.toUpperCase();
    9341    }
    9342
    9343    /**
    9344     * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
    9345     *
    9346     * <p>A {@code null} input String returns {@code null}.</p>
    9347     *
    9348     * <pre>
    9349     * StringUtils.upperCase(null, Locale.ENGLISH)  = null
    9350     * StringUtils.upperCase("", Locale.ENGLISH)    = ""
    9351     * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
    9352     * </pre>
    9353     *
    9354     * @param str  the String to upper case, may be null
    9355     * @param locale  the locale that defines the case transformation rules, must not be null
    9356     * @return the upper cased String, {@code null} if null String input
    9357     * @since 2.5
    9358     */
    9359    public static String upperCase(final String str, final Locale locale) {
    9360        if (str == null) {
    9361            return null;
    9362        }
    9363        return str.toUpperCase(locale);
    9364    }
    9365
    9366    /**
    9367     * Returns the string representation of the {@code char} array or null.
    9368     *
    9369     * @param value the character array.
    9370     * @return a String or null
    9371     * @see String#valueOf(char[])
    9372     * @since 3.9
    9373     */
    9374    public static String valueOf(final char[] value) {
    9375        return value == null ? null : String.valueOf(value);
    9376    }
    9377
    9378    /**
    9379     * <p>
    9380     * Wraps a string with a char.
    9381     * </p>
    9382     *
    9383     * <pre>
    9384     * StringUtils.wrap(null, *)        = null
    9385     * StringUtils.wrap("", *)          = ""
    9386     * StringUtils.wrap("ab", '\0')     = "ab"
    9387     * StringUtils.wrap("ab", 'x')      = "xabx"
    9388     * StringUtils.wrap("ab", '\'')     = "'ab'"
    9389     * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
    9390     * </pre>
    9391     *
    9392     * @param str
    9393     *            the string to be wrapped, may be {@code null}
    9394     * @param wrapWith
    9395     *            the char that will wrap {@code str}
    9396     * @return the wrapped string, or {@code null} if {@code str==null}
    9397     * @since 3.4
    9398     */
    9399    public static String wrap(final String str, final char wrapWith) {
    9400
    9401        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
    9402            return str;
    9403        }
    9404
    9405        return wrapWith + str + wrapWith;
    9406    }
    9407
    9408    /**
    9409     * <p>
    9410     * Wraps a String with another String.
    9411     * </p>
    9412     *
    9413     * <p>
    9414     * A {@code null} input String returns {@code null}.
    9415     * </p>
    9416     *
    9417     * <pre>
    9418     * StringUtils.wrap(null, *)         = null
    9419     * StringUtils.wrap("", *)           = ""
    9420     * StringUtils.wrap("ab", null)      = "ab"
    9421     * StringUtils.wrap("ab", "x")       = "xabx"
    9422     * StringUtils.wrap("ab", "\"")      = "\"ab\""
    9423     * StringUtils.wrap("\"ab\"", "\"")  = "\"\"ab\"\""
    9424     * StringUtils.wrap("ab", "'")       = "'ab'"
    9425     * StringUtils.wrap("'abcd'", "'")   = "''abcd''"
    9426     * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
    9427     * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""
    9428     * </pre>
    9429     *
    9430     * @param str
    9431     *            the String to be wrapper, may be null
    9432     * @param wrapWith
    9433     *            the String that will wrap str
    9434     * @return wrapped String, {@code null} if null String input
    9435     * @since 3.4
    9436     */
    9437    public static String wrap(final String str, final String wrapWith) {
    9438
    9439        if (isEmpty(str) || isEmpty(wrapWith)) {
    9440            return str;
    9441        }
    9442
    9443        return wrapWith.concat(str).concat(wrapWith);
    9444    }
    9445
    9446    /**
    9447     * <p>
    9448     * Wraps a string with a char if that char is missing from the start or end of the given string.
    9449     * </p>
    9450     *
    9451     * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p>
    9452     *
    9453     * <pre>
    9454     * StringUtils.wrapIfMissing(null, *)        = null
    9455     * StringUtils.wrapIfMissing("", *)          = ""
    9456     * StringUtils.wrapIfMissing("ab", '\0')     = "ab"
    9457     * StringUtils.wrapIfMissing("ab", 'x')      = "xabx"
    9458     * StringUtils.wrapIfMissing("ab", '\'')     = "'ab'"
    9459     * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
    9460     * StringUtils.wrapIfMissing("/", '/')  = "/"
    9461     * StringUtils.wrapIfMissing("a/b/c", '/')  = "/a/b/c/"
    9462     * StringUtils.wrapIfMissing("/a/b/c", '/')  = "/a/b/c/"
    9463     * StringUtils.wrapIfMissing("a/b/c/", '/')  = "/a/b/c/"
    9464     * </pre>
    9465     *
    9466     * @param str
    9467     *            the string to be wrapped, may be {@code null}
    9468     * @param wrapWith
    9469     *            the char that will wrap {@code str}
    9470     * @return the wrapped string, or {@code null} if {@code str==null}
    9471     * @since 3.5
    9472     */
    9473    public static String wrapIfMissing(final String str, final char wrapWith) {
    9474        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
    9475            return str;
    9476        }
    9477        final boolean wrapStart = str.charAt(0) != wrapWith;
    9478        final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
    9479        if (!wrapStart && !wrapEnd) {
    9480            return str;
    9481        }
    9482
    9483        final StringBuilder builder = new StringBuilder(str.length() + 2);
    9484        if (wrapStart) {
    9485            builder.append(wrapWith);
    9486        }
    9487        builder.append(str);
    9488        if (wrapEnd) {
    9489            builder.append(wrapWith);
    9490        }
    9491        return builder.toString();
    9492    }
    9493
    9494    /**
    9495     * <p>
    9496     * Wraps a string with a string if that string is missing from the start or end of the given string.
    9497     * </p>
    9498     *
    9499     * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p>
    9500     *
    9501     * <pre>
    9502     * StringUtils.wrapIfMissing(null, *)         = null
    9503     * StringUtils.wrapIfMissing("", *)           = ""
    9504     * StringUtils.wrapIfMissing("ab", null)      = "ab"
    9505     * StringUtils.wrapIfMissing("ab", "x")       = "xabx"
    9506     * StringUtils.wrapIfMissing("ab", "\"")      = "\"ab\""
    9507     * StringUtils.wrapIfMissing("\"ab\"", "\"")  = "\"ab\""
    9508     * StringUtils.wrapIfMissing("ab", "'")       = "'ab'"
    9509     * StringUtils.wrapIfMissing("'abcd'", "'")   = "'abcd'"
    9510     * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
    9511     * StringUtils.wrapIfMissing("'abcd'", "\"")  = "\"'abcd'\""
    9512     * StringUtils.wrapIfMissing("/", "/")  = "/"
    9513     * StringUtils.wrapIfMissing("a/b/c", "/")  = "/a/b/c/"
    9514     * StringUtils.wrapIfMissing("/a/b/c", "/")  = "/a/b/c/"
    9515     * StringUtils.wrapIfMissing("a/b/c/", "/")  = "/a/b/c/"
    9516     * </pre>
    9517     *
    9518     * @param str
    9519     *            the string to be wrapped, may be {@code null}
    9520     * @param wrapWith
    9521     *            the string that will wrap {@code str}
    9522     * @return the wrapped string, or {@code null} if {@code str==null}
    9523     * @since 3.5
    9524     */
    9525    public static String wrapIfMissing(final String str, final String wrapWith) {
    9526        if (isEmpty(str) || isEmpty(wrapWith)) {
    9527            return str;
    9528        }
    9529
    9530        final boolean wrapStart = !str.startsWith(wrapWith);
    9531        final boolean wrapEnd = !str.endsWith(wrapWith);
    9532        if (!wrapStart && !wrapEnd) {
    9533            return str;
    9534        }
    9535
    9536        final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
    9537        if (wrapStart) {
    9538            builder.append(wrapWith);
    9539        }
    9540        builder.append(str);
    9541        if (wrapEnd) {
    9542            builder.append(wrapWith);
    9543        }
    9544        return builder.toString();
    9545    }
    9546
    9547    /**
    9548     * <p>{@code StringUtils} instances should NOT be constructed in
    9549     * standard programming. Instead, the class should be used as
    9550     * {@code StringUtils.trim(" foo ");}.</p>
    9551     *
    9552     * <p>This constructor is public to permit tools that require a JavaBean
    9553     * instance to operate.</p>
    9554     */
    9555    public StringUtils() {
    9556        super();
    9557    }
    9558
    9559}