    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.HashSet;
    025import java.util.Iterator;
    026import java.util.List;
    027import java.util.Locale;
    028import java.util.Objects;
    029import java.util.Set;
    030import java.util.function.Supplier;
    031import java.util.regex.Pattern;
    032
    033/**
    034 * <p>Operations on {@link java.lang.String} that are
    035 * {@code null} safe.</p>
    036 *
    037 * <ul>
    038 *  <li><b>IsEmpty/IsBlank</b>
    039 *      - checks if a String contains text</li>
    040 *  <li><b>Trim/Strip</b>
    041 *      - removes leading and trailing whitespace</li>
    042 *  <li><b>Equals/Compare</b>
    043 *      - compares two strings in a null-safe manner</li>
    044 *  <li><b>startsWith</b>
    045 *      - check if a String starts with a prefix in a null-safe manner</li>
    046 *  <li><b>endsWith</b>
    047 *      - check if a String ends with a suffix in a null-safe manner</li>
    048 *  <li><b>IndexOf/LastIndexOf/Contains</b>
    049 *      - null-safe index-of checks
    050 *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
    051 *      - index-of any of a set of Strings</li>
    052 *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
    053 *      - checks if String contains only/none/any of these characters</li>
    054 *  <li><b>Substring/Left/Right/Mid</b>
    055 *      - null-safe substring extractions</li>
    056 *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
    057 *      - substring extraction relative to other strings</li>
    058 *  <li><b>Split/Join</b>
    059 *      - splits a String into an array of substrings and vice versa</li>
    060 *  <li><b>Remove/Delete</b>
    061 *      - removes part of a String</li>
    062 *  <li><b>Replace/Overlay</b>
    063 *      - Searches a String and replaces one String with another</li>
    064 *  <li><b>Chomp/Chop</b>
    065 *      - removes the last part of a String</li>
    066 *  <li><b>AppendIfMissing</b>
    067 *      - appends a suffix to the end of the String if not present</li>
    068 *  <li><b>PrependIfMissing</b>
    069 *      - prepends a prefix to the start of the String if not present</li>
    070 *  <li><b>LeftPad/RightPad/Center/Repeat</b>
    071 *      - pads a String</li>
    072 *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
    073 *      - changes the case of a String</li>
    074 *  <li><b>CountMatches</b>
    075 *      - counts the number of occurrences of one String in another</li>
    076 *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
    077 *      - checks the characters in a String</li>
    078 *  <li><b>DefaultString</b>
    079 *      - protects against a null input String</li>
    080 *  <li><b>Rotate</b>
    081 *      - rotate (circular shift) a String</li>
    082 *  <li><b>Reverse/ReverseDelimited</b>
    083 *      - reverses a String</li>
    084 *  <li><b>Abbreviate</b>
    085 *      - abbreviates a string using ellipses or another given String</li>
    086 *  <li><b>Difference</b>
    087 *      - compares Strings and reports on their differences</li>
    088 *  <li><b>LevenshteinDistance</b>
    089 *      - the number of changes needed to change one String into another</li>
    090 * </ul>
    091 *
    092 * <p>The {@code StringUtils} class defines certain words related to
    093 * String handling.</p>
    094 *
    095 * <ul>
    096 *  <li>null - {@code null}</li>
    097 *  <li>empty - a zero-length string ({@code ""})</li>
    098 *  <li>space - the space character ({@code ' '}, char 32)</li>
    099 *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
    100 *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
    101 * </ul>
    102 *
    103 * <p>{@code StringUtils} handles {@code null} input Strings quietly.
    104 * That is to say that a {@code null} input will return {@code null}.
    105 * Where a {@code boolean} or {@code int} is being returned
    106 * details vary by method.</p>
    107 *
    108 * <p>A side effect of the {@code null} handling is that a
    109 * {@code NullPointerException} should be considered a bug in
    110 * {@code StringUtils}.</p>
    111 *
    112 * <p>Methods in this class include sample code in their Javadoc comments to explain their operation.
    113 * The symbol {@code *} is used to indicate any input including {@code null}.</p>
    114 *
    115 * <p>#ThreadSafe#</p>
    116 * @see java.lang.String
    117 * @since 1.0
    118 */
    119//@Immutable
    120public class StringUtils {
    121
    122    private static final int STRING_BUILDER_SIZE = 256;
    123
    124    // Performance testing notes (JDK 1.4, Jul03, scolebourne)
    125    // Whitespace:
    126    // Character.isWhitespace() is faster than WHITESPACE.indexOf()
    127    // where WHITESPACE is a string of all whitespace characters
    128    //
    129    // Character access:
    130    // String.charAt(n) versus toCharArray(), then array[n]
    131    // String.charAt(n) is about 15% worse for a 10K string
    132    // They are about equal for a length 50 string
    133    // String.charAt(n) is about 4 times better for a length 3 string
    134    // String.charAt(n) is best bet overall
    135    //
    136    // Append:
    137    // String.concat about twice as fast as StringBuffer.append
    138    // (not sure who tested this)
    139
    140    /**
    141     * A String for a space character.
    142     *
    143     * @since 3.2
    144     */
    145    public static final String SPACE = " ";
    146
    147    /**
    148     * The empty String {@code ""}.
    149     * @since 2.0
    150     */
    151    public static final String EMPTY = "";
    152
    153    /**
    154     * A String for linefeed LF ("\n").
    155     *
    156     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    157     *      for Character and String Literals</a>
    158     * @since 3.2
    159     */
    160    public static final String LF = "\n";
    161
    162    /**
    163     * A String for carriage return CR ("\r").
    164     *
    165     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    166     *      for Character and String Literals</a>
    167     * @since 3.2
    168     */
    169    public static final String CR = "\r";
    170
    171    /**
    172     * Represents a failed index search.
    173     * @since 2.1
    174     */
    175    public static final int INDEX_NOT_FOUND = -1;
    176
    177    /**
    178     * <p>The maximum size to which the padding constant(s) can expand.</p>
    179     */
    180    private static final int PAD_LIMIT = 8192;
    181
    182    /**
    183     * Pattern used in {@link #stripAccents(String)}.
    184     */
    185    private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$
    186
    187    // Abbreviating
    188    //-----------------------------------------------------------------------
    189    /**
    190     * <p>Abbreviates a String using ellipses. This will turn
    191     * "Now is the time for all good men" into "Now is the time for..."</p>
    192     *
    193     * <p>Specifically:</p>
    194     * <ul>
    195     *   <li>If the number of characters in {@code str} is less than or equal to
    196     *       {@code maxWidth}, return {@code str}.</li>
    197     *   <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li>
    198     *   <li>If {@code maxWidth} is less than {@code 4}, throw an
    199     *       {@code IllegalArgumentException}.</li>
    200     *   <li>In no case will it return a String of length greater than
    201     *       {@code maxWidth}.</li>
    202     * </ul>
    203     *
    204     * <pre>
    205     * StringUtils.abbreviate(null, *)      = null
    206     * StringUtils.abbreviate("", 4)        = ""
    207     * StringUtils.abbreviate("abcdefg", 6) = "abc..."
    208     * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
    209     * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
    210     * StringUtils.abbreviate("abcdefg", 4) = "a..."
    211     * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
    212     * </pre>
    213     *
    214     * @param str  the String to check, may be null
    215     * @param maxWidth  maximum length of result String, must be at least 4
    216     * @return abbreviated String, {@code null} if null String input
    217     * @throws IllegalArgumentException if the width is too small
    218     * @since 2.0
    219     */
    220    public static String abbreviate(final String str, final int maxWidth) {
    221        return abbreviate(str, "...", 0, maxWidth);
    222    }
    223
    224    /**
    225     * <p>Abbreviates a String using ellipses. This will turn
    226     * "Now is the time for all good men" into "...is the time for..."</p>
    227     *
    228     * <p>Works like {@code abbreviate(String, int)}, but allows you to specify
    229     * a "left edge" offset.  Note that this left edge is not necessarily going to
    230     * be the leftmost character in the result, or the first character following the
    231     * ellipses, but it will appear somewhere in the result.
    232     *
    233     * <p>In no case will it return a String of length greater than
    234     * {@code maxWidth}.</p>
    235     *
    236     * <pre>
    237     * StringUtils.abbreviate(null, *, *)                = null
    238     * StringUtils.abbreviate("", 0, 4)                  = ""
    239     * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
    240     * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
    241     * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
    242     * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
    243     * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
    244     * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
    245     * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
    246     * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
    247     * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
    248     * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
    249     * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
    250     * </pre>
    251     *
    252     * @param str  the String to check, may be null
    253     * @param offset  left edge of source String
    254     * @param maxWidth  maximum length of result String, must be at least 4
    255     * @return abbreviated String, {@code null} if null String input
    256     * @throws IllegalArgumentException if the width is too small
    257     * @since 2.0
    258     */
    259    public static String abbreviate(final String str, final int offset, final int maxWidth) {
    260        return abbreviate(str, "...", offset, maxWidth);
    261    }
    262
    263    /**
    264     * <p>Abbreviates a String using another given String as replacement marker. This will turn
    265     * "Now is the time for all good men" into "Now is the time for..." if "..." was defined
    266     * as the replacement marker.</p>
    267     *
    268     * <p>Specifically:</p>
    269     * <ul>
    270     *   <li>If the number of characters in {@code str} is less than or equal to
    271     *       {@code maxWidth}, return {@code str}.</li>
    272     *   <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li>
    273     *   <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an
    274     *       {@code IllegalArgumentException}.</li>
    275     *   <li>In no case will it return a String of length greater than
    276     *       {@code maxWidth}.</li>
    277     * </ul>
    278     *
    279     * <pre>
    280     * StringUtils.abbreviate(null, "...", *)      = null
    281     * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"
    282     * StringUtils.abbreviate("", "...", 4)        = ""
    283     * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."
    284     * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"
    285     * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"
    286     * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."
    287     * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."
    288     * StringUtils.abbreviate("abcdefg", "..", 2)  = IllegalArgumentException
    289     * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException
    290     * </pre>
    291     *
    292     * @param str  the String to check, may be null
    293     * @param abbrevMarker  the String used as replacement marker
    294     * @param maxWidth  maximum length of result String, must be at least {@code abbrevMarker.length + 1}
    295     * @return abbreviated String, {@code null} if null String input
    296     * @throws IllegalArgumentException if the width is too small
    297     * @since 3.6
    298     */
    299    public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
    300        return abbreviate(str, abbrevMarker, 0, maxWidth);
    301    }
    302    /**
    303     * <p>Abbreviates a String using a given replacement marker. This will turn
    304     * "Now is the time for all good men" into "...is the time for..." if "..." was defined
    305     * as the replacement marker.</p>
    306     *
    307     * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify
    308     * a "left edge" offset.  Note that this left edge is not necessarily going to
    309     * be the leftmost character in the result, or the first character following the
    310     * replacement marker, but it will appear somewhere in the result.
    311     *
    312     * <p>In no case will it return a String of length greater than {@code maxWidth}.</p>
    313     *
    314     * <pre>
    315     * StringUtils.abbreviate(null, null, *, *)                 = null
    316     * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"
    317     * StringUtils.abbreviate("", "...", 0, 4)                  = ""
    318     * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
    319     * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10)    = "abcdefghi,"
    320     * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10)    = "abcdefghi,"
    321     * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10)    = "abcdefghi,"
    322     * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10)   = "::efghij::"
    323     * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10)  = "...ghij..."
    324     * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10)    = "*ghijklmno"
    325     * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10)   = "'ghijklmno"
    326     * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10)   = "!ghijklmno"
    327     * StringUtils.abbreviate("abcdefghij", "abra", 0, 4)       = IllegalArgumentException
    328     * StringUtils.abbreviate("abcdefghij", "...", 5, 6)        = IllegalArgumentException
    329     * </pre>
    330     *
    331     * @param str  the String to check, may be null
    332     * @param abbrevMarker  the String used as replacement marker
    333     * @param offset  left edge of source String
    334     * @param maxWidth  maximum length of result String, must be at least 4
    335     * @return abbreviated String, {@code null} if null String input
    336     * @throws IllegalArgumentException if the width is too small
    337     * @since 3.6
    338     */
    339    public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) {
    340        if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) {
    341            return substring(str, 0, maxWidth);
    342        } else if (isAnyEmpty(str, abbrevMarker)) {
    343            return str;
    344        }
    345        final int abbrevMarkerLength = abbrevMarker.length();
    346        final int minAbbrevWidth = abbrevMarkerLength + 1;
    347        final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;
    348
    349        if (maxWidth < minAbbrevWidth) {
    350            throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
    351        }
    352        if (str.length() <= maxWidth) {
    353            return str;
    354        }
    355        if (offset > str.length()) {
    356            offset = str.length();
    357        }
    358        if (str.length() - offset < maxWidth - abbrevMarkerLength) {
    359            offset = str.length() - (maxWidth - abbrevMarkerLength);
    360        }
    361        if (offset <= abbrevMarkerLength+1) {
    362            return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
    363        }
    364        if (maxWidth < minAbbrevWidthOffset) {
    365            throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
    366        }
    367        if (offset + maxWidth - abbrevMarkerLength < str.length()) {
    368            return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
    369        }
    370        return abbrevMarker + str.substring(str.length() - (maxWidth - abbrevMarkerLength));
    371    }
    372
    373    /**
    374     * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied
    375     * replacement String.</p>
    376     *
    377     * <p>This abbreviation only occurs if the following criteria is met:</p>
    378     * <ul>
    379     * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
    380     * <li>The length to truncate to is less than the length of the supplied String</li>
    381     * <li>The length to truncate to is greater than 0</li>
    382     * <li>The abbreviated String will have enough room for the length supplied replacement String
    383     * and the first and last characters of the supplied String for abbreviation</li>
    384     * </ul>
    385     * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation.
    386     * </p>
    387     *
    388     * <pre>
    389     * StringUtils.abbreviateMiddle(null, null, 0)      = null
    390     * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"
    391     * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"
    392     * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"
    393     * StringUtils.abbreviateMiddle("abcdef", ".", 4)     = "ab.f"
    394     * </pre>
    395     *
    396     * @param str  the String to abbreviate, may be null
    397     * @param middle the String to replace the middle characters with, may be null
    398     * @param length the length to abbreviate {@code str} to.
    399     * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
    400     * @since 2.5
    401     */
    402    public static String abbreviateMiddle(final String str, final String middle, final int length) {
    403        if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length()+2) {
    404            return str;
    405        }
    406
    407        final int targetSting = length-middle.length();
    408        final int startOffset = targetSting/2+targetSting%2;
    409        final int endOffset = str.length()-targetSting/2;
    410
    411        return str.substring(0, startOffset) +
    412            middle +
    413            str.substring(endOffset);
    414    }
    415
    416    /**
    417     * Appends the suffix to the end of the string if the string does not
    418     * already end with the suffix.
    419     *
    420     * @param str The string.
    421     * @param suffix The suffix to append to the end of the string.
    422     * @param ignoreCase Indicates whether the compare should ignore case.
    423     * @param suffixes Additional suffixes that are valid terminators (optional).
    424     *
    425     * @return A new String if suffix was appended, the same string otherwise.
    426     */
    427    private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
    428        if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) {
    429            return str;
    430        }
    431        if (ArrayUtils.isNotEmpty(suffixes)) {
    432            for (final CharSequence s : suffixes) {
    433                if (endsWith(str, s, ignoreCase)) {
    434                    return str;
    435                }
    436            }
    437        }
    438        return str + suffix.toString();
    439    }
    440
    441    /**
    442     * Appends the suffix to the end of the string if the string does not
    443     * already end with any of the suffixes.
    444     *
    445     * <pre>
    446     * StringUtils.appendIfMissing(null, null) = null
    447     * StringUtils.appendIfMissing("abc", null) = "abc"
    448     * StringUtils.appendIfMissing("", "xyz") = "xyz"
    449     * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz"
    450     * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
    451     * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
    452     * </pre>
    453     * <p>With additional suffixes,</p>
    454     * <pre>
    455     * StringUtils.appendIfMissing(null, null, null) = null
    456     * StringUtils.appendIfMissing("abc", null, null) = "abc"
    457     * StringUtils.appendIfMissing("", "xyz", null) = "xyz"
    458     * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
    459     * StringUtils.appendIfMissing("abc", "xyz", "") = "abc"
    460     * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz"
    461     * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
    462     * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
    463     * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
    464     * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
    465     * </pre>
    466     *
    467     * @param str The string.
    468     * @param suffix The suffix to append to the end of the string.
    469     * @param suffixes Additional suffixes that are valid terminators.
    470     *
    471     * @return A new String if suffix was appended, the same string otherwise.
    472     *
    473     * @since 3.2
    474     */
    475    public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
    476        return appendIfMissing(str, suffix, false, suffixes);
    477    }
    478
    479    /**
    480     * Appends the suffix to the end of the string if the string does not
    481     * already end, case insensitive, with any of the suffixes.
    482     *
    483     * <pre>
    484     * StringUtils.appendIfMissingIgnoreCase(null, null) = null
    485     * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc"
    486     * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz"
    487     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz"
    488     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
    489     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
    490     * </pre>
    491     * <p>With additional suffixes,</p>
    492     * <pre>
    493     * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null
    494     * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc"
    495     * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz"
    496     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
    497     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc"
    498     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz"
    499     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
    500     * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
    501     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
    502     * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
    503     * </pre>
    504     *
    505     * @param str The string.
    506     * @param suffix The suffix to append to the end of the string.
    507     * @param suffixes Additional suffixes that are valid terminators.
    508     *
    509     * @return A new String if suffix was appended, the same string otherwise.
    510     *
    511     * @since 3.2
    512     */
    513    public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
    514        return appendIfMissing(str, suffix, true, suffixes);
    515    }
    516
    517    /**
    518     * <p>Capitalizes a String changing the first character to title case as
    519     * per {@link Character#toTitleCase(int)}. No other characters are changed.</p>
    520     *
    521     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}.
    522     * A {@code null} input String returns {@code null}.</p>
    523     *
    524     * <pre>
    525     * StringUtils.capitalize(null)  = null
    526     * StringUtils.capitalize("")    = ""
    527     * StringUtils.capitalize("cat") = "Cat"
    528     * StringUtils.capitalize("cAt") = "CAt"
    529     * StringUtils.capitalize("'cat'") = "'cat'"
    530     * </pre>
    531     *
    532     * @param str the String to capitalize, may be null
    533     * @return the capitalized String, {@code null} if null String input
    534     * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)
    535     * @see #uncapitalize(String)
    536     * @since 2.0
    537     */
    538    public static String capitalize(final String str) {
    539        final int strLen = length(str);
    540        if (strLen == 0) {
    541            return str;
    542        }
    543
    544        final int firstCodepoint = str.codePointAt(0);
    545        final int newCodePoint = Character.toTitleCase(firstCodepoint);
    546        if (firstCodepoint == newCodePoint) {
    547            // already capitalized
    548            return str;
    549        }
    550
    551        final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
    552        int outOffset = 0;
    553        newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
    554        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
    555            final int codepoint = str.codePointAt(inOffset);
    556            newCodePoints[outOffset++] = codepoint; // copy the remaining ones
    557            inOffset += Character.charCount(codepoint);
    558         }
    559        return new String(newCodePoints, 0, outOffset);
    560    }
    561
    562    // Centering
    563    //-----------------------------------------------------------------------
    564    /**
    565     * <p>Centers a String in a larger String of size {@code size}
    566     * using the space character (' ').</p>
    567     *
    568     * <p>If the size is less than the String length, the original String is returned.
    569     * A {@code null} String returns {@code null}.
    570     * A negative size is treated as zero.</p>
    571     *
    572     * <p>Equivalent to {@code center(str, size, " ")}.</p>
    573     *
    574     * <pre>
    575     * StringUtils.center(null, *)   = null
    576     * StringUtils.center("", 4)     = "    "
    577     * StringUtils.center("ab", -1)  = "ab"
    578     * StringUtils.center("ab", 4)   = " ab "
    579     * StringUtils.center("abcd", 2) = "abcd"
    580     * StringUtils.center("a", 4)    = " a  "
    581     * </pre>
    582     *
    583     * @param str  the String to center, may be null
    584     * @param size  the int size of new String, negative treated as zero
    585     * @return centered String, {@code null} if null String input
    586     */
    587    public static String center(final String str, final int size) {
    588        return center(str, size, ' ');
    589    }
    590
    591    /**
    592     * <p>Centers a String in a larger String of size {@code size}.
    593     * Uses a supplied character as the value to pad the String with.</p>
    594     *
    595     * <p>If the size is less than the String length, the String is returned.
    596     * A {@code null} String returns {@code null}.
    597     * A negative size is treated as zero.</p>
    598     *
    599     * <pre>
    600     * StringUtils.center(null, *, *)     = null
    601     * StringUtils.center("", 4, ' ')     = "    "
    602     * StringUtils.center("ab", -1, ' ')  = "ab"
    603     * StringUtils.center("ab", 4, ' ')   = " ab "
    604     * StringUtils.center("abcd", 2, ' ') = "abcd"
    605     * StringUtils.center("a", 4, ' ')    = " a  "
    606     * StringUtils.center("a", 4, 'y')    = "yayy"
    607     * </pre>
    608     *
    609     * @param str  the String to center, may be null
    610     * @param size  the int size of new String, negative treated as zero
    611     * @param padChar  the character to pad the new String with
    612     * @return centered String, {@code null} if null String input
    613     * @since 2.0
    614     */
    615    public static String center(String str, final int size, final char padChar) {
    616        if (str == null || size <= 0) {
    617            return str;
    618        }
    619        final int strLen = str.length();
    620        final int pads = size - strLen;
    621        if (pads <= 0) {
    622            return str;
    623        }
    624        str = leftPad(str, strLen + pads / 2, padChar);
    625        str = rightPad(str, size, padChar);
    626        return str;
    627    }
    628
    629    /**
    630     * <p>Centers a String in a larger String of size {@code size}.
    631     * Uses a supplied String as the value to pad the String with.</p>
    632     *
    633     * <p>If the size is less than the String length, the String is returned.
    634     * A {@code null} String returns {@code null}.
    635     * A negative size is treated as zero.</p>
    636     *
    637     * <pre>
    638     * StringUtils.center(null, *, *)     = null
    639     * StringUtils.center("", 4, " ")     = "    "
    640     * StringUtils.center("ab", -1, " ")  = "ab"
    641     * StringUtils.center("ab", 4, " ")   = " ab "
    642     * StringUtils.center("abcd", 2, " ") = "abcd"
    643     * StringUtils.center("a", 4, " ")    = " a  "
    644     * StringUtils.center("a", 4, "yz")   = "yayz"
    645     * StringUtils.center("abc", 7, null) = "  abc  "
    646     * StringUtils.center("abc", 7, "")   = "  abc  "
    647     * </pre>
    648     *
    649     * @param str  the String to center, may be null
    650     * @param size  the int size of new String, negative treated as zero
    651     * @param padStr  the String to pad the new String with, must not be null or empty
    652     * @return centered String, {@code null} if null String input
    653     * @throws IllegalArgumentException if padStr is {@code null} or empty
    654     */
    655    public static String center(String str, final int size, String padStr) {
    656        if (str == null || size <= 0) {
    657            return str;
    658        }
    659        if (isEmpty(padStr)) {
    660            padStr = SPACE;
    661        }
    662        final int strLen = str.length();
    663        final int pads = size - strLen;
    664        if (pads <= 0) {
    665            return str;
    666        }
    667        str = leftPad(str, strLen + pads / 2, padStr);
    668        str = rightPad(str, size, padStr);
    669        return str;
    670    }
    671
    672    // Chomping
    673    //-----------------------------------------------------------------------
    674    /**
    675     * <p>Removes one newline from end of a String if it's there,
    676     * otherwise leave it alone.  A newline is &quot;{@code \n}&quot;,
    677     * &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.</p>
    678     *
    679     * <p>NOTE: This method changed in 2.0.
    680     * It now more closely matches Perl chomp.</p>
    681     *
    682     * <pre>
    683     * StringUtils.chomp(null)          = null
    684     * StringUtils.chomp("")            = ""
    685     * StringUtils.chomp("abc \r")      = "abc "
    686     * StringUtils.chomp("abc\n")       = "abc"
    687     * StringUtils.chomp("abc\r\n")     = "abc"
    688     * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
    689     * StringUtils.chomp("abc\n\r")     = "abc\n"
    690     * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
    691     * StringUtils.chomp("\r")          = ""
    692     * StringUtils.chomp("\n")          = ""
    693     * StringUtils.chomp("\r\n")        = ""
    694     * </pre>
    695     *
    696     * @param str  the String to chomp a newline from, may be null
    697     * @return String without newline, {@code null} if null String input
    698     */
    699    public static String chomp(final String str) {
    700        if (isEmpty(str)) {
    701            return str;
    702        }
    703
    704        if (str.length() == 1) {
    705            final char ch = str.charAt(0);
    706            if (ch == CharUtils.CR || ch == CharUtils.LF) {
    707                return EMPTY;
    708            }
    709            return str;
    710        }
    711
    712        int lastIdx = str.length() - 1;
    713        final char last = str.charAt(lastIdx);
    714
    715        if (last == CharUtils.LF) {
    716            if (str.charAt(lastIdx - 1) == CharUtils.CR) {
    717                lastIdx--;
    718            }
    719        } else if (last != CharUtils.CR) {
    720            lastIdx++;
    721        }
    722        return str.substring(0, lastIdx);
    723    }
    724
    725    /**
    726     * <p>Removes {@code separator} from the end of
    727     * {@code str} if it's there, otherwise leave it alone.</p>
    728     *
    729     * <p>NOTE: This method changed in version 2.0.
    730     * It now more closely matches Perl chomp.
    731     * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
    732     * This method uses {@link String#endsWith(String)}.</p>
    733     *
    734     * <pre>
    735     * StringUtils.chomp(null, *)         = null
    736     * StringUtils.chomp("", *)           = ""
    737     * StringUtils.chomp("foobar", "bar") = "foo"
    738     * StringUtils.chomp("foobar", "baz") = "foobar"
    739     * StringUtils.chomp("foo", "foo")    = ""
    740     * StringUtils.chomp("foo ", "foo")   = "foo "
    741     * StringUtils.chomp(" foo", "foo")   = " "
    742     * StringUtils.chomp("foo", "foooo")  = "foo"
    743     * StringUtils.chomp("foo", "")       = "foo"
    744     * StringUtils.chomp("foo", null)     = "foo"
    745     * </pre>
    746     *
    747     * @param str  the String to chomp from, may be null
    748     * @param separator  separator String, may be null
    749     * @return String without trailing separator, {@code null} if null String input
    750     * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead
    751     */
    752    @Deprecated
    753    public static String chomp(final String str, final String separator) {
    754        return removeEnd(str, separator);
    755    }
    756
    757    // Chopping
    758    //-----------------------------------------------------------------------
    759    /**
    760     * <p>Remove the last character from a String.</p>
    761     *
    762     * <p>If the String ends in {@code \r\n}, then remove both
    763     * of them.</p>
    764     *
    765     * <pre>
    766     * StringUtils.chop(null)          = null
    767     * StringUtils.chop("")            = ""
    768     * StringUtils.chop("abc \r")      = "abc "
    769     * StringUtils.chop("abc\n")       = "abc"
    770     * StringUtils.chop("abc\r\n")     = "abc"
    771     * StringUtils.chop("abc")         = "ab"
    772     * StringUtils.chop("abc\nabc")    = "abc\nab"
    773     * StringUtils.chop("a")           = ""
    774     * StringUtils.chop("\r")          = ""
    775     * StringUtils.chop("\n")          = ""
    776     * StringUtils.chop("\r\n")        = ""
    777     * </pre>
    778     *
    779     * @param str  the String to chop last character from, may be null
    780     * @return String without last character, {@code null} if null String input
    781     */
    782    public static String chop(final String str) {
    783        if (str == null) {
    784            return null;
    785        }
    786        final int strLen = str.length();
    787        if (strLen < 2) {
    788            return EMPTY;
    789        }
    790        final int lastIdx = strLen - 1;
    791        final String ret = str.substring(0, lastIdx);
    792        final char last = str.charAt(lastIdx);
    793        if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
    794            return ret.substring(0, lastIdx - 1);
    795        }
    796        return ret;
    797    }
    798
    799    // Compare
    800    //-----------------------------------------------------------------------
    801    /**
    802     * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p>
    803     * <ul>
    804     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    805     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    806     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    807     * </ul>
    808     *
    809     * <p>This is a {@code null} safe version of :</p>
    810     * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
    811     *
    812     * <p>{@code null} value is considered less than non-{@code null} value.
    813     * Two {@code null} references are considered equal.</p>
    814     *
    815     * <pre>
    816     * StringUtils.compare(null, null)   = 0
    817     * StringUtils.compare(null , "a")   &lt; 0
    818     * StringUtils.compare("a", null)    &gt; 0
    819     * StringUtils.compare("abc", "abc") = 0
    820     * StringUtils.compare("a", "b")     &lt; 0
    821     * StringUtils.compare("b", "a")     &gt; 0
    822     * StringUtils.compare("a", "B")     &gt; 0
    823     * StringUtils.compare("ab", "abc")  &lt; 0
    824     * </pre>
    825     *
    826     * @see #compare(String, String, boolean)
    827     * @see String#compareTo(String)
    828     * @param str1  the String to compare from
    829     * @param str2  the String to compare to
    830     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal or greater than {@code str2}
    831     * @since 3.5
    832     */
    833    public static int compare(final String str1, final String str2) {
    834        return compare(str1, str2, true);
    835    }
    836
    837    /**
    838     * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p>
    839     * <ul>
    840     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    841     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    842     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    843     * </ul>
    844     *
    845     * <p>This is a {@code null} safe version of :</p>
    846     * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
    847     *
    848     * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
    849     * Two {@code null} references are considered equal.</p>
    850     *
    851     * <pre>
    852     * StringUtils.compare(null, null, *)     = 0
    853     * StringUtils.compare(null , "a", true)  &lt; 0
    854     * StringUtils.compare(null , "a", false) &gt; 0
    855     * StringUtils.compare("a", null, true)   &gt; 0
    856     * StringUtils.compare("a", null, false)  &lt; 0
    857     * StringUtils.compare("abc", "abc", *)   = 0
    858     * StringUtils.compare("a", "b", *)       &lt; 0
    859     * StringUtils.compare("b", "a", *)       &gt; 0
    860     * StringUtils.compare("a", "B", *)       &gt; 0
    861     * StringUtils.compare("ab", "abc", *)    &lt; 0
    862     * </pre>
    863     *
    864     * @see String#compareTo(String)
    865     * @param str1  the String to compare from
    866     * @param str2  the String to compare to
    867     * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
    868     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
    869     * @since 3.5
    870     */
    871    public static int compare(final String str1, final String str2, final boolean nullIsLess) {
    872        if (str1 == str2) {
    873            return 0;
    874        }
    875        if (str1 == null) {
    876            return nullIsLess ? -1 : 1;
    877        }
    878        if (str2 == null) {
    879            return nullIsLess ? 1 : - 1;
    880        }
    881        return str1.compareTo(str2);
    882    }
    883
    884    /**
    885     * <p>Compare two Strings lexicographically, ignoring case differences,
    886     * as per {@link String#compareToIgnoreCase(String)}, returning :</p>
    887     * <ul>
    888     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    889     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    890     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    891     * </ul>
    892     *
    893     * <p>This is a {@code null} safe version of :</p>
    894     * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
    895     *
    896     * <p>{@code null} value is considered less than non-{@code null} value.
    897     * Two {@code null} references are considered equal.
    898     * Comparison is case insensitive.</p>
    899     *
    900     * <pre>
    901     * StringUtils.compareIgnoreCase(null, null)   = 0
    902     * StringUtils.compareIgnoreCase(null , "a")   &lt; 0
    903     * StringUtils.compareIgnoreCase("a", null)    &gt; 0
    904     * StringUtils.compareIgnoreCase("abc", "abc") = 0
    905     * StringUtils.compareIgnoreCase("abc", "ABC") = 0
    906     * StringUtils.compareIgnoreCase("a", "b")     &lt; 0
    907     * StringUtils.compareIgnoreCase("b", "a")     &gt; 0
    908     * StringUtils.compareIgnoreCase("a", "B")     &lt; 0
    909     * StringUtils.compareIgnoreCase("A", "b")     &lt; 0
    910     * StringUtils.compareIgnoreCase("ab", "ABC")  &lt; 0
    911     * </pre>
    912     *
    913     * @see #compareIgnoreCase(String, String, boolean)
    914     * @see String#compareToIgnoreCase(String)
    915     * @param str1  the String to compare from
    916     * @param str2  the String to compare to
    917     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
    918     *          ignoring case differences.
    919     * @since 3.5
    920     */
    921    public static int compareIgnoreCase(final String str1, final String str2) {
    922        return compareIgnoreCase(str1, str2, true);
    923    }
    924
    925    /**
    926     * <p>Compare two Strings lexicographically, ignoring case differences,
    927     * as per {@link String#compareToIgnoreCase(String)}, returning :</p>
    928     * <ul>
    929     *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
    930     *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
    931     *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
    932     * </ul>
    933     *
    934     * <p>This is a {@code null} safe version of :</p>
    935     * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
    936     *
    937     * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
    938     * Two {@code null} references are considered equal.
    939     * Comparison is case insensitive.</p>
    940     *
    941     * <pre>
    942     * StringUtils.compareIgnoreCase(null, null, *)     = 0
    943     * StringUtils.compareIgnoreCase(null , "a", true)  &lt; 0
    944     * StringUtils.compareIgnoreCase(null , "a", false) &gt; 0
    945     * StringUtils.compareIgnoreCase("a", null, true)   &gt; 0
    946     * StringUtils.compareIgnoreCase("a", null, false)  &lt; 0
    947     * StringUtils.compareIgnoreCase("abc", "abc", *)   = 0
    948     * StringUtils.compareIgnoreCase("abc", "ABC", *)   = 0
    949     * StringUtils.compareIgnoreCase("a", "b", *)       &lt; 0
    950     * StringUtils.compareIgnoreCase("b", "a", *)       &gt; 0
    951     * StringUtils.compareIgnoreCase("a", "B", *)       &lt; 0
    952     * StringUtils.compareIgnoreCase("A", "b", *)       &lt; 0
    953     * StringUtils.compareIgnoreCase("ab", "abc", *)    &lt; 0
    954     * </pre>
    955     *
    956     * @see String#compareToIgnoreCase(String)
    957     * @param str1  the String to compare from
    958     * @param str2  the String to compare to
    959     * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
    960     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
    961     *          ignoring case differences.
    962     * @since 3.5
    963     */
    964    public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
    965        if (str1 == str2) {
    966            return 0;
    967        }
    968        if (str1 == null) {
    969            return nullIsLess ? -1 : 1;
    970        }
    971        if (str2 == null) {
    972            return nullIsLess ? 1 : - 1;
    973        }
    974        return str1.compareToIgnoreCase(str2);
    975    }
    976
    977    /**
    978     * <p>Checks if CharSequence contains a search CharSequence, handling {@code null}.
    979     * This method uses {@link String#indexOf(String)} if possible.</p>
    980     *
    981     * <p>A {@code null} CharSequence will return {@code false}.</p>
    982     *
    983     * <pre>
    984     * StringUtils.contains(null, *)     = false
    985     * StringUtils.contains(*, null)     = false
    986     * StringUtils.contains("", "")      = true
    987     * StringUtils.contains("abc", "")   = true
    988     * StringUtils.contains("abc", "a")  = true
    989     * StringUtils.contains("abc", "z")  = false
    990     * </pre>
    991     *
    992     * @param seq  the CharSequence to check, may be null
    993     * @param searchSeq  the CharSequence to find, may be null
    994     * @return true if the CharSequence contains the search CharSequence,
    995     *  false if not or {@code null} string input
    996     * @since 2.0
    997     * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
    998     */
    999    public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
    1000        if (seq == null || searchSeq == null) {
    1001            return false;
    1002        }
    1003        return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;
    1004    }
    1005
    1006    // Contains
    1007    //-----------------------------------------------------------------------
    1008    /**
    1009     * <p>Checks if CharSequence contains a search character, handling {@code null}.
    1010     * This method uses {@link String#indexOf(int)} if possible.</p>
    1011     *
    1012     * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p>
    1013     *
    1014     * <pre>
    1015     * StringUtils.contains(null, *)    = false
    1016     * StringUtils.contains("", *)      = false
    1017     * StringUtils.contains("abc", 'a') = true
    1018     * StringUtils.contains("abc", 'z') = false
    1019     * </pre>
    1020     *
    1021     * @param seq  the CharSequence to check, may be null
    1022     * @param searchChar  the character to find
    1023     * @return true if the CharSequence contains the search character,
    1024     *  false if not or {@code null} string input
    1025     * @since 2.0
    1026     * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
    1027     */
    1028    public static boolean contains(final CharSequence seq, final int searchChar) {
    1029        if (isEmpty(seq)) {
    1030            return false;
    1031        }
    1032        return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
    1033    }
    1034
    1035    // ContainsAny
    1036    //-----------------------------------------------------------------------
    1037    /**
    1038     * <p>Checks if the CharSequence contains any character in the given
    1039     * set of characters.</p>
    1040     *
    1041     * <p>A {@code null} CharSequence will return {@code false}.
    1042     * A {@code null} or zero length search array will return {@code false}.</p>
    1043     *
    1044     * <pre>
    1045     * StringUtils.containsAny(null, *)                  = false
    1046     * StringUtils.containsAny("", *)                    = false
    1047     * StringUtils.containsAny(*, null)                  = false
    1048     * StringUtils.containsAny(*, [])                    = false
    1049     * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true
    1050     * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true
    1051     * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true
    1052     * StringUtils.containsAny("aba", ['z'])             = false
    1053     * </pre>
    1054     *
    1055     * @param cs  the CharSequence to check, may be null
    1056     * @param searchChars  the chars to search for, may be null
    1057     * @return the {@code true} if any of the chars are found,
    1058     * {@code false} if no match or null input
    1059     * @since 2.4
    1060     * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
    1061     */
    1062    public static boolean containsAny(final CharSequence cs, final char... searchChars) {
    1063        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    1064            return false;
    1065        }
    1066        final int csLength = cs.length();
    1067        final int searchLength = searchChars.length;
    1068        final int csLast = csLength - 1;
    1069        final int searchLast = searchLength - 1;
    1070        for (int i = 0; i < csLength; i++) {
    1071            final char ch = cs.charAt(i);
    1072            for (int j = 0; j < searchLength; j++) {
    1073                if (searchChars[j] == ch) {
    1074                    if (Character.isHighSurrogate(ch)) {
    1075                        if (j == searchLast) {
    1076                            // missing low surrogate, fine, like String.indexOf(String)
    1077                            return true;
    1078                        }
    1079                        if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
    1080                            return true;
    1081                        }
    1082                    } else {
    1083                        // ch is in the Basic Multilingual Plane
    1084                        return true;
    1085                    }
    1086                }
    1087            }
    1088        }
    1089        return false;
    1090    }
    1091
    1092    /**
    1093     * <p>
    1094     * Checks if the CharSequence contains any character in the given set of characters.
    1095     * </p>
    1096     *
    1097     * <p>
    1098     * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
    1099     * {@code false}.
    1100     * </p>
    1101     *
    1102     * <pre>
    1103     * StringUtils.containsAny(null, *)               = false
    1104     * StringUtils.containsAny("", *)                 = false
    1105     * StringUtils.containsAny(*, null)               = false
    1106     * StringUtils.containsAny(*, "")                 = false
    1107     * StringUtils.containsAny("zzabyycdxx", "za")    = true
    1108     * StringUtils.containsAny("zzabyycdxx", "by")    = true
    1109     * StringUtils.containsAny("zzabyycdxx", "zy")    = true
    1110     * StringUtils.containsAny("zzabyycdxx", "\tx")   = true
    1111     * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
    1112     * StringUtils.containsAny("aba", "z")            = false
    1113     * </pre>
    1114     *
    1115     * @param cs
    1116     *            the CharSequence to check, may be null
    1117     * @param searchChars
    1118     *            the chars to search for, may be null
    1119     * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
    1120     * @since 2.4
    1121     * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
    1122     */
    1123    public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
    1124        if (searchChars == null) {
    1125            return false;
    1126        }
    1127        return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
    1128    }
    1129
    1130    /**
    1131     * <p>Checks if the CharSequence contains any of the CharSequences in the given array.</p>
    1132     *
    1133     * <p>
    1134     * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero
    1135     * length search array will return {@code false}.
    1136     * </p>
    1137     *
    1138     * <pre>
    1139     * StringUtils.containsAny(null, *)            = false
    1140     * StringUtils.containsAny("", *)              = false
    1141     * StringUtils.containsAny(*, null)            = false
    1142     * StringUtils.containsAny(*, [])              = false
    1143     * StringUtils.containsAny("abcd", "ab", null) = true
    1144     * StringUtils.containsAny("abcd", "ab", "cd") = true
    1145     * StringUtils.containsAny("abc", "d", "abc")  = true
    1146     * </pre>
    1147     *
    1148     *
    1149     * @param cs The CharSequence to check, may be null
    1150     * @param searchCharSequences The array of CharSequences to search for, may be null.
    1151     * Individual CharSequences may be null as well.
    1152     * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
    1153     * @since 3.4
    1154     */
    1155    public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
    1156        if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {
    1157            return false;
    1158        }
    1159        for (final CharSequence searchCharSequence : searchCharSequences) {
    1160            if (contains(cs, searchCharSequence)) {
    1161                return true;
    1162            }
    1163        }
    1164        return false;
    1165    }
    1166
    1167    /**
    1168     * <p>Checks if CharSequence contains a search CharSequence irrespective of case,
    1169     * handling {@code null}. Case-insensitivity is defined as by
    1170     * {@link String#equalsIgnoreCase(String)}.
    1171     *
    1172     * <p>A {@code null} CharSequence will return {@code false}.</p>
    1173     *
    1174     * <pre>
    1175     * StringUtils.containsIgnoreCase(null, *) = false
    1176     * StringUtils.containsIgnoreCase(*, null) = false
    1177     * StringUtils.containsIgnoreCase("", "") = true
    1178     * StringUtils.containsIgnoreCase("abc", "") = true
    1179     * StringUtils.containsIgnoreCase("abc", "a") = true
    1180     * StringUtils.containsIgnoreCase("abc", "z") = false
    1181     * StringUtils.containsIgnoreCase("abc", "A") = true
    1182     * StringUtils.containsIgnoreCase("abc", "Z") = false
    1183     * </pre>
    1184     *
    1185     * @param str  the CharSequence to check, may be null
    1186     * @param searchStr  the CharSequence to find, may be null
    1187     * @return true if the CharSequence contains the search CharSequence irrespective of
    1188     * case or false if not or {@code null} string input
    1189     * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
    1190     */
    1191    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    1192        if (str == null || searchStr == null) {
    1193            return false;
    1194        }
    1195        final int len = searchStr.length();
    1196        final int max = str.length() - len;
    1197        for (int i = 0; i <= max; i++) {
    1198            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
    1199                return true;
    1200            }
    1201        }
    1202        return false;
    1203    }
    1204
    1205    // ContainsNone
    1206    //-----------------------------------------------------------------------
    1207    /**
    1208     * <p>Checks that the CharSequence does not contain certain characters.</p>
    1209     *
    1210     * <p>A {@code null} CharSequence will return {@code true}.
    1211     * A {@code null} invalid character array will return {@code true}.
    1212     * An empty CharSequence (length()=0) always returns true.</p>
    1213     *
    1214     * <pre>
    1215     * StringUtils.containsNone(null, *)       = true
    1216     * StringUtils.containsNone(*, null)       = true
    1217     * StringUtils.containsNone("", *)         = true
    1218     * StringUtils.containsNone("ab", '')      = true
    1219     * StringUtils.containsNone("abab", 'xyz') = true
    1220     * StringUtils.containsNone("ab1", 'xyz')  = true
    1221     * StringUtils.containsNone("abz", 'xyz')  = false
    1222     * </pre>
    1223     *
    1224     * @param cs  the CharSequence to check, may be null
    1225     * @param searchChars  an array of invalid chars, may be null
    1226     * @return true if it contains none of the invalid chars, or is null
    1227     * @since 2.0
    1228     * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
    1229     */
    1230    public static boolean containsNone(final CharSequence cs, final char... searchChars) {
    1231        if (cs == null || searchChars == null) {
    1232            return true;
    1233        }
    1234        final int csLen = cs.length();
    1235        final int csLast = csLen - 1;
    1236        final int searchLen = searchChars.length;
    1237        final int searchLast = searchLen - 1;
    1238        for (int i = 0; i < csLen; i++) {
    1239            final char ch = cs.charAt(i);
    1240            for (int j = 0; j < searchLen; j++) {
    1241                if (searchChars[j] == ch) {
    1242                    if (Character.isHighSurrogate(ch)) {
    1243                        if (j == searchLast) {
    1244                            // missing low surrogate, fine, like String.indexOf(String)
    1245                            return false;
    1246                        }
    1247                        if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
    1248                            return false;
    1249                        }
    1250                    } else {
    1251                        // ch is in the Basic Multilingual Plane
    1252                        return false;
    1253                    }
    1254                }
    1255            }
    1256        }
    1257        return true;
    1258    }
    1259
    1260    /**
    1261     * <p>Checks that the CharSequence does not contain certain characters.</p>
    1262     *
    1263     * <p>A {@code null} CharSequence will return {@code true}.
    1264     * A {@code null} invalid character array will return {@code true}.
    1265     * An empty String ("") always returns true.</p>
    1266     *
    1267     * <pre>
    1268     * StringUtils.containsNone(null, *)       = true
    1269     * StringUtils.containsNone(*, null)       = true
    1270     * StringUtils.containsNone("", *)         = true
    1271     * StringUtils.containsNone("ab", "")      = true
    1272     * StringUtils.containsNone("abab", "xyz") = true
    1273     * StringUtils.containsNone("ab1", "xyz")  = true
    1274     * StringUtils.containsNone("abz", "xyz")  = false
    1275     * </pre>
    1276     *
    1277     * @param cs  the CharSequence to check, may be null
    1278     * @param invalidChars  a String of invalid chars, may be null
    1279     * @return true if it contains none of the invalid chars, or is null
    1280     * @since 2.0
    1281     * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
    1282     */
    1283    public static boolean containsNone(final CharSequence cs, final String invalidChars) {
    1284        if (cs == null || invalidChars == null) {
    1285            return true;
    1286        }
    1287        return containsNone(cs, invalidChars.toCharArray());
    1288    }
    1289
    1290    // ContainsOnly
    1291    //-----------------------------------------------------------------------
    1292    /**
    1293     * <p>Checks if the CharSequence contains only certain characters.</p>
    1294     *
    1295     * <p>A {@code null} CharSequence will return {@code false}.
    1296     * A {@code null} valid character array will return {@code false}.
    1297     * An empty CharSequence (length()=0) always returns {@code true}.</p>
    1298     *
    1299     * <pre>
    1300     * StringUtils.containsOnly(null, *)       = false
    1301     * StringUtils.containsOnly(*, null)       = false
    1302     * StringUtils.containsOnly("", *)         = true
    1303     * StringUtils.containsOnly("ab", '')      = false
    1304     * StringUtils.containsOnly("abab", 'abc') = true
    1305     * StringUtils.containsOnly("ab1", 'abc')  = false
    1306     * StringUtils.containsOnly("abz", 'abc')  = false
    1307     * </pre>
    1308     *
    1309     * @param cs  the String to check, may be null
    1310     * @param valid  an array of valid chars, may be null
    1311     * @return true if it only contains valid chars and is non-null
    1312     * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
    1313     */
    1314    public static boolean containsOnly(final CharSequence cs, final char... valid) {
    1315        // All these pre-checks are to maintain API with an older version
    1316        if (valid == null || cs == null) {
    1317            return false;
    1318        }
    1319        if (cs.length() == 0) {
    1320            return true;
    1321        }
    1322        if (valid.length == 0) {
    1323            return false;
    1324        }
    1325        return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
    1326    }
    1327
    1328    /**
    1329     * <p>Checks if the CharSequence contains only certain characters.</p>
    1330     *
    1331     * <p>A {@code null} CharSequence will return {@code false}.
    1332     * A {@code null} valid character String will return {@code false}.
    1333     * An empty String (length()=0) always returns {@code true}.</p>
    1334     *
    1335     * <pre>
    1336     * StringUtils.containsOnly(null, *)       = false
    1337     * StringUtils.containsOnly(*, null)       = false
    1338     * StringUtils.containsOnly("", *)         = true
    1339     * StringUtils.containsOnly("ab", "")      = false
    1340     * StringUtils.containsOnly("abab", "abc") = true
    1341     * StringUtils.containsOnly("ab1", "abc")  = false
    1342     * StringUtils.containsOnly("abz", "abc")  = false
    1343     * </pre>
    1344     *
    1345     * @param cs  the CharSequence to check, may be null
    1346     * @param validChars  a String of valid chars, may be null
    1347     * @return true if it only contains valid chars and is non-null
    1348     * @since 2.0
    1349     * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
    1350     */
    1351    public static boolean containsOnly(final CharSequence cs, final String validChars) {
    1352        if (cs == null || validChars == null) {
    1353            return false;
    1354        }
    1355        return containsOnly(cs, validChars.toCharArray());
    1356    }
    1357
    1358    /**
    1359     * <p>Check whether the given CharSequence contains any whitespace characters.</p>
    1360     *
    1361     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1362     *
    1363     * @param seq the CharSequence to check (may be {@code null})
    1364     * @return {@code true} if the CharSequence is not empty and
    1365     * contains at least 1 (breaking) whitespace character
    1366     * @since 3.0
    1367     */
    1368    // From org.springframework.util.StringUtils, under Apache License 2.0
    1369    public static boolean containsWhitespace(final CharSequence seq) {
    1370        if (isEmpty(seq)) {
    1371            return false;
    1372        }
    1373        final int strLen = seq.length();
    1374        for (int i = 0; i < strLen; i++) {
    1375            if (Character.isWhitespace(seq.charAt(i))) {
    1376                return true;
    1377            }
    1378        }
    1379        return false;
    1380    }
    1381
    1382    private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
    1383        for (int i = 0; i < decomposed.length(); i++) {
    1384            if (decomposed.charAt(i) == '\u0141') {
    1385                decomposed.deleteCharAt(i);
    1386                decomposed.insert(i, 'L');
    1387            } else if (decomposed.charAt(i) == '\u0142') {
    1388                decomposed.deleteCharAt(i);
    1389                decomposed.insert(i, 'l');
    1390            }
    1391        }
    1392    }
    1393
    1394    /**
    1395     * <p>Counts how many times the char appears in the given string.</p>
    1396     *
    1397     * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
    1398     *
    1399     * <pre>
    1400     * StringUtils.countMatches(null, *)       = 0
    1401     * StringUtils.countMatches("", *)         = 0
    1402     * StringUtils.countMatches("abba", 0)  = 0
    1403     * StringUtils.countMatches("abba", 'a')   = 2
    1404     * StringUtils.countMatches("abba", 'b')  = 2
    1405     * StringUtils.countMatches("abba", 'x') = 0
    1406     * </pre>
    1407     *
    1408     * @param str  the CharSequence to check, may be null
    1409     * @param ch  the char to count
    1410     * @return the number of occurrences, 0 if the CharSequence is {@code null}
    1411     * @since 3.4
    1412     */
    1413    public static int countMatches(final CharSequence str, final char ch) {
    1414        if (isEmpty(str)) {
    1415            return 0;
    1416        }
    1417        int count = 0;
    1418        // We could also call str.toCharArray() for faster look ups but that would generate more garbage.
    1419        for (int i = 0; i < str.length(); i++) {
    1420            if (ch == str.charAt(i)) {
    1421                count++;
    1422            }
    1423        }
    1424        return count;
    1425    }
    1426
    1427    // Count matches
    1428    //-----------------------------------------------------------------------
    1429    /**
    1430     * <p>Counts how many times the substring appears in the larger string.</p>
    1431     *
    1432     * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
    1433     *
    1434     * <pre>
    1435     * StringUtils.countMatches(null, *)       = 0
    1436     * StringUtils.countMatches("", *)         = 0
    1437     * StringUtils.countMatches("abba", null)  = 0
    1438     * StringUtils.countMatches("abba", "")    = 0
    1439     * StringUtils.countMatches("abba", "a")   = 2
    1440     * StringUtils.countMatches("abba", "ab")  = 1
    1441     * StringUtils.countMatches("abba", "xxx") = 0
    1442     * </pre>
    1443     *
    1444     * @param str  the CharSequence to check, may be null
    1445     * @param sub  the substring to count, may be null
    1446     * @return the number of occurrences, 0 if either CharSequence is {@code null}
    1447     * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
    1448     */
    1449    public static int countMatches(final CharSequence str, final CharSequence sub) {
    1450        if (isEmpty(str) || isEmpty(sub)) {
    1451            return 0;
    1452        }
    1453        int count = 0;
    1454        int idx = 0;
    1455        while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
    1456            count++;
    1457            idx += sub.length();
    1458        }
    1459        return count;
    1460    }
    1461
    1462    /**
    1463     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    1464     * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p>
    1465     *
    1466     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1467     *
    1468     * <pre>
    1469     * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
    1470     * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
    1471     * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
    1472     * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
    1473     * StringUtils.defaultIfBlank("", null)      = null
    1474     * </pre>
    1475     * @param <T> the specific kind of CharSequence
    1476     * @param str the CharSequence to check, may be null
    1477     * @param defaultStr  the default CharSequence to return
    1478     *  if the input is whitespace, empty ("") or {@code null}, may be null
    1479     * @return the passed in CharSequence, or the default
    1480     * @see StringUtils#defaultString(String, String)
    1481     */
    1482    public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
    1483        return isBlank(str) ? defaultStr : str;
    1484    }
    1485
    1486    /**
    1487     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    1488     * empty or {@code null}, the value of {@code defaultStr}.</p>
    1489     *
    1490     * <pre>
    1491     * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
    1492     * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
    1493     * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
    1494     * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
    1495     * StringUtils.defaultIfEmpty("", null)      = null
    1496     * </pre>
    1497     * @param <T> the specific kind of CharSequence
    1498     * @param str  the CharSequence to check, may be null
    1499     * @param defaultStr  the default CharSequence to return
    1500     *  if the input is empty ("") or {@code null}, may be null
    1501     * @return the passed in CharSequence, or the default
    1502     * @see StringUtils#defaultString(String, String)
    1503     */
    1504    public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
    1505        return isEmpty(str) ? defaultStr : str;
    1506    }
    1507
    1508    /**
    1509     * <p>Returns either the passed in String,
    1510     * or if the String is {@code null}, an empty String ("").</p>
    1511     *
    1512     * <pre>
    1513     * StringUtils.defaultString(null)  = ""
    1514     * StringUtils.defaultString("")    = ""
    1515     * StringUtils.defaultString("bat") = "bat"
    1516     * </pre>
    1517     *
    1518     * @see ObjectUtils#toString(Object)
    1519     * @see String#valueOf(Object)
    1520     * @param str  the String to check, may be null
    1521     * @return the passed in String, or the empty String if it
    1522     *  was {@code null}
    1523     */
    1524    public static String defaultString(final String str) {
    1525        return defaultString(str, EMPTY);
    1526    }
    1527
    1528    /**
    1529     * <p>Returns either the passed in String, or if the String is
    1530     * {@code null}, the value of {@code defaultStr}.</p>
    1531     *
    1532     * <pre>
    1533     * StringUtils.defaultString(null, "NULL")  = "NULL"
    1534     * StringUtils.defaultString("", "NULL")    = ""
    1535     * StringUtils.defaultString("bat", "NULL") = "bat"
    1536     * </pre>
    1537     *
    1538     * @see ObjectUtils#toString(Object,String)
    1539     * @see String#valueOf(Object)
    1540     * @param str  the String to check, may be null
    1541     * @param defaultStr  the default String to return
    1542     *  if the input is {@code null}, may be null
    1543     * @return the passed in String, or the default if it was {@code null}
    1544     */
    1545    public static String defaultString(final String str, final String defaultStr) {
    1546        return str == null ? defaultStr : str;
    1547    }
    1548
    1549    // Delete
    1550    //-----------------------------------------------------------------------
    1551    /**
    1552     * <p>Deletes all whitespaces from a String as defined by
    1553     * {@link Character#isWhitespace(char)}.</p>
    1554     *
    1555     * <pre>
    1556     * StringUtils.deleteWhitespace(null)         = null
    1557     * StringUtils.deleteWhitespace("")           = ""
    1558     * StringUtils.deleteWhitespace("abc")        = "abc"
    1559     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
    1560     * </pre>
    1561     *
    1562     * @param str  the String to delete whitespace from, may be null
    1563     * @return the String without whitespaces, {@code null} if null String input
    1564     */
    1565    public static String deleteWhitespace(final String str) {
    1566        if (isEmpty(str)) {
    1567            return str;
    1568        }
    1569        final int sz = str.length();
    1570        final char[] chs = new char[sz];
    1571        int count = 0;
    1572        for (int i = 0; i < sz; i++) {
    1573            if (!Character.isWhitespace(str.charAt(i))) {
    1574                chs[count++] = str.charAt(i);
    1575            }
    1576        }
    1577        if (count == sz) {
    1578            return str;
    1579        }
    1580        return new String(chs, 0, count);
    1581    }
    1582
    1583    // Difference
    1584    //-----------------------------------------------------------------------
    1585    /**
    1586     * <p>Compares two Strings, and returns the portion where they differ.
    1587     * More precisely, return the remainder of the second String,
    1588     * starting from where it's different from the first. This means that
    1589     * the difference between "abc" and "ab" is the empty String and not "c". </p>
    1590     *
    1591     * <p>For example,
    1592     * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p>
    1593     *
    1594     * <pre>
    1595     * StringUtils.difference(null, null) = null
    1596     * StringUtils.difference("", "") = ""
    1597     * StringUtils.difference("", "abc") = "abc"
    1598     * StringUtils.difference("abc", "") = ""
    1599     * StringUtils.difference("abc", "abc") = ""
    1600     * StringUtils.difference("abc", "ab") = ""
    1601     * StringUtils.difference("ab", "abxyz") = "xyz"
    1602     * StringUtils.difference("abcde", "abxyz") = "xyz"
    1603     * StringUtils.difference("abcde", "xyz") = "xyz"
    1604     * </pre>
    1605     *
    1606     * @param str1  the first String, may be null
    1607     * @param str2  the second String, may be null
    1608     * @return the portion of str2 where it differs from str1; returns the
    1609     * empty String if they are equal
    1610     * @see #indexOfDifference(CharSequence,CharSequence)
    1611     * @since 2.0
    1612     */
    1613    public static String difference(final String str1, final String str2) {
    1614        if (str1 == null) {
    1615            return str2;
    1616        }
    1617        if (str2 == null) {
    1618            return str1;
    1619        }
    1620        final int at = indexOfDifference(str1, str2);
    1621        if (at == INDEX_NOT_FOUND) {
    1622            return EMPTY;
    1623        }
    1624        return str2.substring(at);
    1625    }
    1626
    1627    /**
    1628     * <p>Check if a CharSequence ends with a specified suffix.</p>
    1629     *
    1630     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1631     * references are considered to be equal. The comparison is case sensitive.</p>
    1632     *
    1633     * <pre>
    1634     * StringUtils.endsWith(null, null)      = true
    1635     * StringUtils.endsWith(null, "def")     = false
    1636     * StringUtils.endsWith("abcdef", null)  = false
    1637     * StringUtils.endsWith("abcdef", "def") = true
    1638     * StringUtils.endsWith("ABCDEF", "def") = false
    1639     * StringUtils.endsWith("ABCDEF", "cde") = false
    1640     * StringUtils.endsWith("ABCDEF", "")    = true
    1641     * </pre>
    1642     *
    1643     * @see java.lang.String#endsWith(String)
    1644     * @param str  the CharSequence to check, may be null
    1645     * @param suffix the suffix to find, may be null
    1646     * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or
    1647     *  both {@code null}
    1648     * @since 2.4
    1649     * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
    1650     */
    1651    public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
    1652        return endsWith(str, suffix, false);
    1653    }
    1654
    1655    /**
    1656     * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p>
    1657     *
    1658     * @see java.lang.String#endsWith(String)
    1659     * @param str  the CharSequence to check, may be null
    1660     * @param suffix the suffix to find, may be null
    1661     * @param ignoreCase indicates whether the compare should ignore case
    1662     *  (case insensitive) or not.
    1663     * @return {@code true} if the CharSequence starts with the prefix or
    1664     *  both {@code null}
    1665     */
    1666    private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
    1667        if (str == null || suffix == null) {
    1668            return str == suffix;
    1669        }
    1670        if (suffix.length() > str.length()) {
    1671            return false;
    1672        }
    1673        final int strOffset = str.length() - suffix.length();
    1674        return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length());
    1675    }
    1676
    1677    /**
    1678     * <p>Check if a CharSequence ends with any of the provided case-sensitive suffixes.</p>
    1679     *
    1680     * <pre>
    1681     * StringUtils.endsWithAny(null, null)      = false
    1682     * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
    1683     * StringUtils.endsWithAny("abcxyz", null)     = false
    1684     * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
    1685     * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
    1686     * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    1687     * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
    1688     * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
    1689     * </pre>
    1690     *
    1691     * @param sequence  the CharSequence to check, may be null
    1692     * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
    1693     * @see StringUtils#endsWith(CharSequence, CharSequence)
    1694     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
    1695     *   the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
    1696     * @since 3.0
    1697     */
    1698    public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
    1699        if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
    1700            return false;
    1701        }
    1702        for (final CharSequence searchString : searchStrings) {
    1703            if (endsWith(sequence, searchString)) {
    1704                return true;
    1705            }
    1706        }
    1707        return false;
    1708    }
    1709
    1710    /**
    1711     * <p>Case insensitive check if a CharSequence ends with a specified suffix.</p>
    1712     *
    1713     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1714     * references are considered to be equal. The comparison is case insensitive.</p>
    1715     *
    1716     * <pre>
    1717     * StringUtils.endsWithIgnoreCase(null, null)      = true
    1718     * StringUtils.endsWithIgnoreCase(null, "def")     = false
    1719     * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
    1720     * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
    1721     * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
    1722     * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
    1723     * </pre>
    1724     *
    1725     * @see java.lang.String#endsWith(String)
    1726     * @param str  the CharSequence to check, may be null
    1727     * @param suffix the suffix to find, may be null
    1728     * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or
    1729     *  both {@code null}
    1730     * @since 2.4
    1731     * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
    1732     */
    1733    public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
    1734        return endsWith(str, suffix, true);
    1735    }
    1736
    1737    // Equals
    1738    //-----------------------------------------------------------------------
    1739    /**
    1740     * <p>Compares two CharSequences, returning {@code true} if they represent
    1741     * equal sequences of characters.</p>
    1742     *
    1743     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1744     * references are considered to be equal. The comparison is <strong>case sensitive</strong>.</p>
    1745     *
    1746     * <pre>
    1747     * StringUtils.equals(null, null)   = true
    1748     * StringUtils.equals(null, "abc")  = false
    1749     * StringUtils.equals("abc", null)  = false
    1750     * StringUtils.equals("abc", "abc") = true
    1751     * StringUtils.equals("abc", "ABC") = false
    1752     * </pre>
    1753     *
    1754     * @param cs1  the first CharSequence, may be {@code null}
    1755     * @param cs2  the second CharSequence, may be {@code null}
    1756     * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
    1757     * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
    1758     * @see Object#equals(Object)
    1759     * @see #equalsIgnoreCase(CharSequence, CharSequence)
    1760     */
    1761    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
    1762        if (cs1 == cs2) {
    1763            return true;
    1764        }
    1765        if (cs1 == null || cs2 == null) {
    1766            return false;
    1767        }
    1768        if (cs1.length() != cs2.length()) {
    1769            return false;
    1770        }
    1771        if (cs1 instanceof String && cs2 instanceof String) {
    1772            return cs1.equals(cs2);
    1773        }
    1774        // Step-wise comparison
    1775        final int length = cs1.length();
    1776        for (int i = 0; i < length; i++) {
    1777            if (cs1.charAt(i) != cs2.charAt(i)) {
    1778                return false;
    1779            }
    1780        }
    1781        return true;
    1782    }
    1783
    1784    /**
    1785     * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
    1786     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.</p>
    1787     *
    1788     * <pre>
    1789     * StringUtils.equalsAny(null, (CharSequence[]) null) = false
    1790     * StringUtils.equalsAny(null, null, null)    = true
    1791     * StringUtils.equalsAny(null, "abc", "def")  = false
    1792     * StringUtils.equalsAny("abc", null, "def")  = false
    1793     * StringUtils.equalsAny("abc", "abc", "def") = true
    1794     * StringUtils.equalsAny("abc", "ABC", "DEF") = false
    1795     * </pre>
    1796     *
    1797     * @param string to compare, may be {@code null}.
    1798     * @param searchStrings a vararg of strings, may be {@code null}.
    1799     * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings};
    1800     * {@code false} if {@code searchStrings} is null or contains no matches.
    1801     * @since 3.5
    1802     */
    1803    public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
    1804        if (ArrayUtils.isNotEmpty(searchStrings)) {
    1805            for (final CharSequence next : searchStrings) {
    1806                if (equals(string, next)) {
    1807                    return true;
    1808                }
    1809            }
    1810        }
    1811        return false;
    1812    }
    1813
    1814    /**
    1815     * <p>Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
    1816     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.</p>
    1817     *
    1818     * <pre>
    1819     * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
    1820     * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
    1821     * StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
    1822     * StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
    1823     * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
    1824     * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
    1825     * </pre>
    1826     *
    1827     * @param string to compare, may be {@code null}.
    1828     * @param searchStrings a vararg of strings, may be {@code null}.
    1829     * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
    1830     * {@code false} if {@code searchStrings} is null or contains no matches.
    1831     * @since 3.5
    1832     */
    1833    public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) {
    1834        if (ArrayUtils.isNotEmpty(searchStrings)) {
    1835            for (final CharSequence next : searchStrings) {
    1836                if (equalsIgnoreCase(string, next)) {
    1837                    return true;
    1838                }
    1839            }
    1840        }
    1841        return false;
    1842    }
    1843
    1844    /**
    1845     * <p>Compares two CharSequences, returning {@code true} if they represent
    1846     * equal sequences of characters, ignoring case.</p>
    1847     *
    1848     * <p>{@code null}s are handled without exceptions. Two {@code null}
    1849     * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
    1850     *
    1851     * <pre>
    1852     * StringUtils.equalsIgnoreCase(null, null)   = true
    1853     * StringUtils.equalsIgnoreCase(null, "abc")  = false
    1854     * StringUtils.equalsIgnoreCase("abc", null)  = false
    1855     * StringUtils.equalsIgnoreCase("abc", "abc") = true
    1856     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
    1857     * </pre>
    1858     *
    1859     * @param cs1  the first CharSequence, may be {@code null}
    1860     * @param cs2  the second CharSequence, may be {@code null}
    1861     * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
    1862     * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
    1863     * @see #equals(CharSequence, CharSequence)
    1864     */
    1865    public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
    1866        if (cs1 == cs2) {
    1867            return true;
    1868        }
    1869        if (cs1 == null || cs2 == null) {
    1870            return false;
    1871        }
    1872        if (cs1.length() != cs2.length()) {
    1873            return false;
    1874        }
    1875        return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length());
    1876    }
    1877
    1878    /**
    1879     * <p>Returns the first value in the array which is not empty (""),
    1880     * {@code null} or whitespace only.</p>
    1881     *
    1882     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    1883     *
    1884     * <p>If all values are blank or the array is {@code null}
    1885     * or empty then {@code null} is returned.</p>
    1886     *
    1887     * <pre>
    1888     * StringUtils.firstNonBlank(null, null, null)     = null
    1889     * StringUtils.firstNonBlank(null, "", " ")        = null
    1890     * StringUtils.firstNonBlank("abc")                = "abc"
    1891     * StringUtils.firstNonBlank(null, "xyz")          = "xyz"
    1892     * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
    1893     * StringUtils.firstNonBlank(null, "xyz", "abc")   = "xyz"
    1894     * StringUtils.firstNonBlank()                     = null
    1895     * </pre>
    1896     *
    1897     * @param <T> the specific kind of CharSequence
    1898     * @param values  the values to test, may be {@code null} or empty
    1899     * @return the first value from {@code values} which is not blank,
    1900     *  or {@code null} if there are no non-blank values
    1901     * @since 3.8
    1902     */
    1903    @SafeVarargs
    1904    public static <T extends CharSequence> T firstNonBlank(final T... values) {
    1905        if (values != null) {
    1906            for (final T val : values) {
    1907                if (isNotBlank(val)) {
    1908                    return val;
    1909                }
    1910            }
    1911        }
    1912        return null;
    1913    }
    1914
    1915    /**
    1916     * <p>Returns the first value in the array which is not empty.</p>
    1917     *
    1918     * <p>If all values are empty or the array is {@code null}
    1919     * or empty then {@code null} is returned.</p>
    1920     *
    1921     * <pre>
    1922     * StringUtils.firstNonEmpty(null, null, null)   = null
    1923     * StringUtils.firstNonEmpty(null, null, "")     = null
    1924     * StringUtils.firstNonEmpty(null, "", " ")      = " "
    1925     * StringUtils.firstNonEmpty("abc")              = "abc"
    1926     * StringUtils.firstNonEmpty(null, "xyz")        = "xyz"
    1927     * StringUtils.firstNonEmpty("", "xyz")          = "xyz"
    1928     * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
    1929     * StringUtils.firstNonEmpty()                   = null
    1930     * </pre>
    1931     *
    1932     * @param <T> the specific kind of CharSequence
    1933     * @param values  the values to test, may be {@code null} or empty
    1934     * @return the first value from {@code values} which is not empty,
    1935     *  or {@code null} if there are no non-empty values
    1936     * @since 3.8
    1937     */
    1938    @SafeVarargs
    1939    public static <T extends CharSequence> T firstNonEmpty(final T... values) {
    1940        if (values != null) {
    1941            for (final T val : values) {
    1942                if (isNotEmpty(val)) {
    1943                    return val;
    1944                }
    1945            }
    1946        }
    1947        return null;
    1948    }
    1949
    1950    /**
    1951     * Calls {@link String#getBytes(Charset)} in a null-safe manner.
    1952     *
    1953     * @param string input string
    1954     * @param charset The {@link Charset} to encode the {@code String}. If null, then use the default Charset.
    1955     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
    1956     * @see String#getBytes(Charset)
    1957     * @since 3.10
    1958     */
    1959    public static byte[] getBytes(final String string, final Charset charset) {
    1960        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
    1961    }
    1962
    1963    /**
    1964     * Calls {@link String#getBytes(String)} in a null-safe manner.
    1965     *
    1966     * @param string input string
    1967     * @param charset The {@link Charset} name to encode the {@code String}. If null, then use the default Charset.
    1968     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
    1969     * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
    1970     * @see String#getBytes(String)
    1971     * @since 3.10
    1972     */
    1973    public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
    1974        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
    1975    }
    1976
    1977    /**
    1978     * <p>Compares all Strings in an array and returns the initial sequence of
    1979     * characters that is common to all of them.</p>
    1980     *
    1981     * <p>For example,
    1982     * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -&gt; "i am a "}</p>
    1983     *
    1984     * <pre>
    1985     * StringUtils.getCommonPrefix(null) = ""
    1986     * StringUtils.getCommonPrefix(new String[] {}) = ""
    1987     * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
    1988     * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
    1989     * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
    1990     * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
    1991     * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
    1992     * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
    1993     * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
    1994     * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
    1995     * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
    1996     * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
    1997     * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
    1998     * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
    1999     * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
    2000     * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
    2001     * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
    2002     * </pre>
    2003     *
    2004     * @param strs  array of String objects, entries may be null
    2005     * @return the initial sequence of characters that are common to all Strings
    2006     * in the array; empty String if the array is null, the elements are all null
    2007     * or if there is no common prefix.
    2008     * @since 2.4
    2009     */
    2010    public static String getCommonPrefix(final String... strs) {
    2011        if (ArrayUtils.isEmpty(strs)) {
    2012            return EMPTY;
    2013        }
    2014        final int smallestIndexOfDiff = indexOfDifference(strs);
    2015        if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
    2016            // all strings were identical
    2017            if (strs[0] == null) {
    2018                return EMPTY;
    2019            }
    2020            return strs[0];
    2021        } else if (smallestIndexOfDiff == 0) {
    2022            // there were no common initial characters
    2023            return EMPTY;
    2024        } else {
    2025            // we found a common initial character sequence
    2026            return strs[0].substring(0, smallestIndexOfDiff);
    2027        }
    2028    }
    2029
    2030    /**
    2031     * <p>Checks if a String {@code str} contains Unicode digits,
    2032     * if yes then concatenate all the digits in {@code str} and return it as a String.</p>
    2033     *
    2034     * <p>An empty ("") String will be returned if no digits found in {@code str}.</p>
    2035     *
    2036     * <pre>
    2037     * StringUtils.getDigits(null)  = null
    2038     * StringUtils.getDigits("")    = ""
    2039     * StringUtils.getDigits("abc") = ""
    2040     * StringUtils.getDigits("1000$") = "1000"
    2041     * StringUtils.getDigits("1123~45") = "112345"
    2042     * StringUtils.getDigits("(541) 754-3010") = "5417543010"
    2043     * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
    2044     * </pre>
    2045     *
    2046     * @param str the String to extract digits from, may be null
    2047     * @return String with only digits,
    2048     *           or an empty ("") String if no digits found,
    2049     *           or {@code null} String if {@code str} is null
    2050     * @since 3.6
    2051     */
    2052    public static String getDigits(final String str) {
    2053        if (isEmpty(str)) {
    2054            return str;
    2055        }
    2056        final int sz = str.length();
    2057        final StringBuilder strDigits = new StringBuilder(sz);
    2058        for (int i = 0; i < sz; i++) {
    2059            final char tempChar = str.charAt(i);
    2060            if (Character.isDigit(tempChar)) {
    2061                strDigits.append(tempChar);
    2062            }
    2063        }
    2064        return strDigits.toString();
    2065    }
    2066
    2067    /**
    2068     * <p>Find the Fuzzy Distance which indicates the similarity score between two Strings.</p>
    2069     *
    2070     * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
    2071     * TextMate, Atom and others. One point is given for every matched character. Subsequent
    2072     * matches yield two bonus points. A higher score indicates a higher similarity.</p>
    2073     *
    2074     * <pre>
    2075     * StringUtils.getFuzzyDistance(null, null, null)                                    = IllegalArgumentException
    2076     * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH)                              = 0
    2077     * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH)                     = 0
    2078     * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH)                         = 1
    2079     * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH)                     = 1
    2080     * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH)                    = 2
    2081     * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH)                    = 4
    2082     * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
    2083     * </pre>
    2084     *
    2085     * @param term a full term that should be matched against, must not be null
    2086     * @param query the query that will be matched against a term, must not be null
    2087     * @param locale This string matching logic is case insensitive. A locale is necessary to normalize
    2088     *  both Strings to lower case.
    2089     * @return result score
    2090     * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
    2091     * @since 3.4
    2092     * @deprecated as of 3.6, use commons-text
    2093     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
    2094     * FuzzyScore</a> instead
    2095     */
    2096    @Deprecated
    2097    public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
    2098        if (term == null || query == null) {
    2099            throw new IllegalArgumentException("Strings must not be null");
    2100        } else if (locale == null) {
    2101            throw new IllegalArgumentException("Locale must not be null");
    2102        }
    2103
    2104        // fuzzy logic is case insensitive. We normalize the Strings to lower
    2105        // case right from the start. Turning characters to lower case
    2106        // via Character.toLowerCase(char) is unfortunately insufficient
    2107        // as it does not accept a locale.
    2108        final String termLowerCase = term.toString().toLowerCase(locale);
    2109        final String queryLowerCase = query.toString().toLowerCase(locale);
    2110
    2111        // the resulting score
    2112        int score = 0;
    2113
    2114        // the position in the term which will be scanned next for potential
    2115        // query character matches
    2116        int termIndex = 0;
    2117
    2118        // index of the previously matched character in the term
    2119        int previousMatchingCharacterIndex = Integer.MIN_VALUE;
    2120
    2121        for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
    2122            final char queryChar = queryLowerCase.charAt(queryIndex);
    2123
    2124            boolean termCharacterMatchFound = false;
    2125            for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
    2126                final char termChar = termLowerCase.charAt(termIndex);
    2127
    2128                if (queryChar == termChar) {
    2129                    // simple character matches result in one point
    2130                    score++;
    2131
    2132                    // subsequent character matches further improve
    2133                    // the score.
    2134                    if (previousMatchingCharacterIndex + 1 == termIndex) {
    2135                        score += 2;
    2136                    }
    2137
    2138                    previousMatchingCharacterIndex = termIndex;
    2139
    2140                    // we can leave the nested loop. Every character in the
    2141                    // query can match at most one character in the term.
    2142                    termCharacterMatchFound = true;
    2143                }
    2144            }
    2145        }
    2146
    2147        return score;
    2148    }
    2149
    2150    /**
    2151     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    2152     * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.</p>
    2153     *
    2154     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    2155     *
    2156     * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
    2157     *
    2158     * <pre>
    2159     * {@code
    2160     * StringUtils.getIfBlank(null, () -> "NULL")   = "NULL"
    2161     * StringUtils.getIfBlank("", () -> "NULL")     = "NULL"
    2162     * StringUtils.getIfBlank(" ", () -> "NULL")    = "NULL"
    2163     * StringUtils.getIfBlank("bat", () -> "NULL")  = "bat"
    2164     * StringUtils.getIfBlank("", () -> null)       = null
    2165     * StringUtils.getIfBlank("", null)             = null
    2166     * }</pre>
    2167     * @param <T> the specific kind of CharSequence
    2168     * @param str the CharSequence to check, may be null
    2169     * @param defaultSupplier the supplier of default CharSequence to return
    2170     *  if the input is whitespace, empty ("") or {@code null}, may be null
    2171     * @return the passed in CharSequence, or the default
    2172     * @see StringUtils#defaultString(String, String)
    2173     * @since 3.10
    2174     */
    2175    public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
    2176        return isBlank(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str;
    2177    }
    2178
    2179    /**
    2180     * <p>Returns either the passed in CharSequence, or if the CharSequence is
    2181     * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.</p>
    2182     *
    2183     * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
    2184     *
    2185     * <pre>
    2186     * {@code
    2187     * StringUtils.getIfEmpty(null, () -> "NULL")    = "NULL"
    2188     * StringUtils.getIfEmpty("", () -> "NULL")      = "NULL"
    2189     * StringUtils.getIfEmpty(" ", () -> "NULL")     = " "
    2190     * StringUtils.getIfEmpty("bat", () -> "NULL")   = "bat"
    2191     * StringUtils.getIfEmpty("", () -> null)        = null
    2192     * StringUtils.getIfEmpty("", null)              = null
    2193     * }
    2194     * </pre>
    2195     * @param <T> the specific kind of CharSequence
    2196     * @param str  the CharSequence to check, may be null
    2197     * @param defaultSupplier  the supplier of default CharSequence to return
    2198     *  if the input is empty ("") or {@code null}, may be null
    2199     * @return the passed in CharSequence, or the default
    2200     * @see StringUtils#defaultString(String, String)
    2201     * @since 3.10
    2202     */
    2203    public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
    2204        return isEmpty(str) ? defaultSupplier == null ? null : defaultSupplier.get() : str;
    2205    }
    2206
    2207    /**
    2208     * <p>Find the Jaro Winkler Distance which indicates the similarity score between two Strings.</p>
    2209     *
    2210     * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
    2211     * Winkler increased this measure for matching initial characters.</p>
    2212     *
    2213     * <p>This implementation is based on the Jaro Winkler similarity algorithm
    2214     * 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>
    2215     *
    2216     * <pre>
    2217     * StringUtils.getJaroWinklerDistance(null, null)          = IllegalArgumentException
    2218     * StringUtils.getJaroWinklerDistance("", "")              = 0.0
    2219     * StringUtils.getJaroWinklerDistance("", "a")             = 0.0
    2220     * StringUtils.getJaroWinklerDistance("aaapppp", "")       = 0.0
    2221     * StringUtils.getJaroWinklerDistance("frog", "fog")       = 0.93
    2222     * StringUtils.getJaroWinklerDistance("fly", "ant")        = 0.0
    2223     * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
    2224     * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
    2225     * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
    2226     * StringUtils.getJaroWinklerDistance("hello", "hallo")    = 0.88
    2227     * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
    2228     * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D &amp; H Enterprises, Inc.") = 0.95
    2229     * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
    2230     * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
    2231     * </pre>
    2232     *
    2233     * @param first the first String, must not be null
    2234     * @param second the second String, must not be null
    2235     * @return result distance
    2236     * @throws IllegalArgumentException if either String input {@code null}
    2237     * @since 3.3
    2238     * @deprecated as of 3.6, use commons-text
    2239     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
    2240     * JaroWinklerDistance</a> instead
    2241     */
    2242    @Deprecated
    2243    public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
    2244        final double DEFAULT_SCALING_FACTOR = 0.1;
    2245
    2246        if (first == null || second == null) {
    2247            throw new IllegalArgumentException("Strings must not be null");
    2248        }
    2249
    2250        final int[] mtp = matches(first, second);
    2251        final double m = mtp[0];
    2252        if (m == 0) {
    2253            return 0D;
    2254        }
    2255        final double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3;
    2256        final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
    2257        return Math.round(jw * 100.0D) / 100.0D;
    2258    }
    2259
    2260    // Misc
    2261    //-----------------------------------------------------------------------
    2262    /**
    2263     * <p>Find the Levenshtein distance between two Strings.</p>
    2264     *
    2265     * <p>This is the number of changes needed to change one String into
    2266     * another, where each change is a single character modification (deletion,
    2267     * insertion or substitution).</p>
    2268     *
    2269     * <p>The implementation uses a single-dimensional array of length s.length() + 1. See
    2270     * <a href="http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
    2271     * http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p>
    2272     *
    2273     * <pre>
    2274     * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
    2275     * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
    2276     * StringUtils.getLevenshteinDistance("", "")              = 0
    2277     * StringUtils.getLevenshteinDistance("", "a")             = 1
    2278     * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
    2279     * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
    2280     * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
    2281     * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
    2282     * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
    2283     * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
    2284     * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
    2285     * </pre>
    2286     *
    2287     * @param s  the first String, must not be null
    2288     * @param t  the second String, must not be null
    2289     * @return result distance
    2290     * @throws IllegalArgumentException if either String input {@code null}
    2291     * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
    2292     * getLevenshteinDistance(CharSequence, CharSequence)
    2293     * @deprecated as of 3.6, use commons-text
    2294     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
    2295     * LevenshteinDistance</a> instead
    2296     */
    2297    @Deprecated
    2298    public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
    2299        if (s == null || t == null) {
    2300            throw new IllegalArgumentException("Strings must not be null");
    2301        }
    2302
    2303        int n = s.length();
    2304        int m = t.length();
    2305
    2306        if (n == 0) {
    2307            return m;
    2308        } else if (m == 0) {
    2309            return n;
    2310        }
    2311
    2312        if (n > m) {
    2313            // swap the input strings to consume less memory
    2314            final CharSequence tmp = s;
    2315            s = t;
    2316            t = tmp;
    2317            n = m;
    2318            m = t.length();
    2319        }
    2320
    2321        final int[] p = new int[n + 1];
    2322        // indexes into strings s and t
    2323        int i; // iterates through s
    2324        int j; // iterates through t
    2325        int upper_left;
    2326        int upper;
    2327
    2328        char t_j; // jth character of t
    2329        int cost;
    2330
    2331        for (i = 0; i <= n; i++) {
    2332            p[i] = i;
    2333        }
    2334
    2335        for (j = 1; j <= m; j++) {
    2336            upper_left = p[0];
    2337            t_j = t.charAt(j - 1);
    2338            p[0] = j;
    2339
    2340            for (i = 1; i <= n; i++) {
    2341                upper = p[i];
    2342                cost = s.charAt(i - 1) == t_j ? 0 : 1;
    2343                // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
    2344                p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upper_left + cost);
    2345                upper_left = upper;
    2346            }
    2347        }
    2348
    2349        return p[n];
    2350    }
    2351
    2352    /**
    2353     * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given
    2354     * threshold.</p>
    2355     *
    2356     * <p>This is the number of changes needed to change one String into
    2357     * another, where each change is a single character modification (deletion,
    2358     * insertion or substitution).</p>
    2359     *
    2360     * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
    2361     * and Chas Emerick's implementation of the Levenshtein distance algorithm from
    2362     * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
    2363     *
    2364     * <pre>
    2365     * StringUtils.getLevenshteinDistance(null, *, *)             = IllegalArgumentException
    2366     * StringUtils.getLevenshteinDistance(*, null, *)             = IllegalArgumentException
    2367     * StringUtils.getLevenshteinDistance(*, *, -1)               = IllegalArgumentException
    2368     * StringUtils.getLevenshteinDistance("", "", 0)              = 0
    2369     * StringUtils.getLevenshteinDistance("aaapppp", "", 8)       = 7
    2370     * StringUtils.getLevenshteinDistance("aaapppp", "", 7)       = 7
    2371     * StringUtils.getLevenshteinDistance("aaapppp", "", 6))      = -1
    2372     * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
    2373     * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
    2374     * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
    2375     * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
    2376     * </pre>
    2377     *
    2378     * @param s  the first String, must not be null
    2379     * @param t  the second String, must not be null
    2380     * @param threshold the target threshold, must not be negative
    2381     * @return result distance, or {@code -1} if the distance would be greater than the threshold
    2382     * @throws IllegalArgumentException if either String input {@code null} or negative threshold
    2383     * @deprecated as of 3.6, use commons-text
    2384     * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
    2385     * LevenshteinDistance</a> instead
    2386     */
    2387    @Deprecated
    2388    public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
    2389        if (s == null || t == null) {
    2390            throw new IllegalArgumentException("Strings must not be null");
    2391        }
    2392        if (threshold < 0) {
    2393            throw new IllegalArgumentException("Threshold must not be negative");
    2394        }
    2395
    2396        /*
    2397        This implementation only computes the distance if it's less than or equal to the
    2398        threshold value, returning -1 if it's greater.  The advantage is performance: unbounded
    2399        distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
    2400        computing a diagonal stripe of width 2k + 1 of the cost table.
    2401        It is also possible to use this to compute the unbounded Levenshtein distance by starting
    2402        the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
    2403        d is the distance.
    2404
    2405        One subtlety comes from needing to ignore entries on the border of our stripe
    2406        eg.
    2407        p[] = |#|#|#|*
    2408        d[] =  *|#|#|#|
    2409        We must ignore the entry to the left of the leftmost member
    2410        We must ignore the entry above the rightmost member
    2411
    2412        Another subtlety comes from our stripe running off the matrix if the strings aren't
    2413        of the same size.  Since string s is always swapped to be the shorter of the two,
    2414        the stripe will always run off to the upper right instead of the lower left of the matrix.
    2415
    2416        As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
    2417        In this case we're going to walk a stripe of length 3.  The matrix would look like so:
    2418
    2419           1 2 3 4 5
    2420        1 |#|#| | | |
    2421        2 |#|#|#| | |
    2422        3 | |#|#|#| |
    2423        4 | | |#|#|#|
    2424        5 | | | |#|#|
    2425        6 | | | | |#|
    2426        7 | | | | | |
    2427
    2428        Note how the stripe leads off the table as there is no possible way to turn a string of length 5
    2429        into one of length 7 in edit distance of 1.
    2430
    2431        Additionally, this implementation decreases memory usage by using two
    2432        single-dimensional arrays and swapping them back and forth instead of allocating
    2433        an entire n by m matrix.  This requires a few minor changes, such as immediately returning
    2434        when it's detected that the stripe has run off the matrix and initially filling the arrays with
    2435        large values so that entries we don't compute are ignored.
    2436
    2437        See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
    2438         */
    2439
    2440        int n = s.length(); // length of s
    2441        int m = t.length(); // length of t
    2442
    2443        // if one string is empty, the edit distance is necessarily the length of the other
    2444        if (n == 0) {
    2445            return m <= threshold ? m : -1;
    2446        } else if (m == 0) {
    2447            return n <= threshold ? n : -1;
    2448        } else if (Math.abs(n - m) > threshold) {
    2449            // no need to calculate the distance if the length difference is greater than the threshold
    2450            return -1;
    2451        }
    2452
    2453        if (n > m) {
    2454            // swap the two strings to consume less memory
    2455            final CharSequence tmp = s;
    2456            s = t;
    2457            t = tmp;
    2458            n = m;
    2459            m = t.length();
    2460        }
    2461
    2462        int[] p = new int[n + 1]; // 'previous' cost array, horizontally
    2463        int[] d = new int[n + 1]; // cost array, horizontally
    2464        int[] _d; // placeholder to assist in swapping p and d
    2465
    2466        // fill in starting table values
    2467        final int boundary = Math.min(n, threshold) + 1;
    2468        for (int i = 0; i < boundary; i++) {
    2469            p[i] = i;
    2470        }
    2471        // these fills ensure that the value above the rightmost entry of our
    2472        // stripe will be ignored in following loop iterations
    2473        Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
    2474        Arrays.fill(d, Integer.MAX_VALUE);
    2475
    2476        // iterates through t
    2477        for (int j = 1; j <= m; j++) {
    2478            final char t_j = t.charAt(j - 1); // jth character of t
    2479            d[0] = j;
    2480
    2481            // compute stripe indices, constrain to array size
    2482            final int min = Math.max(1, j - threshold);
    2483            final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
    2484
    2485            // the stripe may lead off of the table if s and t are of different sizes
    2486            if (min > max) {
    2487                return -1;
    2488            }
    2489
    2490            // ignore entry left of leftmost
    2491            if (min > 1) {
    2492                d[min - 1] = Integer.MAX_VALUE;
    2493            }
    2494
    2495            // iterates through [min, max] in s
    2496            for (int i = min; i <= max; i++) {
    2497                if (s.charAt(i - 1) == t_j) {
    2498                    // diagonally left and up
    2499                    d[i] = p[i - 1];
    2500                } else {
    2501                    // 1 + minimum of cell to the left, to the top, diagonally left and up
    2502                    d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
    2503                }
    2504            }
    2505
    2506            // copy current distance counts to 'previous row' distance counts
    2507            _d = p;
    2508            p = d;
    2509            d = _d;
    2510        }
    2511
    2512        // if p[n] is greater than the threshold, there's no guarantee on it being the correct
    2513        // distance
    2514        if (p[n] <= threshold) {
    2515            return p[n];
    2516        }
    2517        return -1;
    2518    }
    2519
    2520    /**
    2521     * <p>Finds the first index within a CharSequence, handling {@code null}.
    2522     * This method uses {@link String#indexOf(String, int)} if possible.</p>
    2523     *
    2524     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    2525     *
    2526     * <pre>
    2527     * StringUtils.indexOf(null, *)          = -1
    2528     * StringUtils.indexOf(*, null)          = -1
    2529     * StringUtils.indexOf("", "")           = 0
    2530     * StringUtils.indexOf("", *)            = -1 (except when * = "")
    2531     * StringUtils.indexOf("aabaabaa", "a")  = 0
    2532     * StringUtils.indexOf("aabaabaa", "b")  = 2
    2533     * StringUtils.indexOf("aabaabaa", "ab") = 1
    2534     * StringUtils.indexOf("aabaabaa", "")   = 0
    2535     * </pre>
    2536     *
    2537     * @param seq  the CharSequence to check, may be null
    2538     * @param searchSeq  the CharSequence to find, may be null
    2539     * @return the first index of the search CharSequence,
    2540     *  -1 if no match or {@code null} string input
    2541     * @since 2.0
    2542     * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
    2543     */
    2544    public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
    2545        if (seq == null || searchSeq == null) {
    2546            return INDEX_NOT_FOUND;
    2547        }
    2548        return CharSequenceUtils.indexOf(seq, searchSeq, 0);
    2549    }
    2550
    2551    /**
    2552     * <p>Finds the first index within a CharSequence, handling {@code null}.
    2553     * This method uses {@link String#indexOf(String, int)} if possible.</p>
    2554     *
    2555     * <p>A {@code null} CharSequence will return {@code -1}.
    2556     * A negative start position is treated as zero.
    2557     * An empty ("") search CharSequence always matches.
    2558     * A start position greater than the string length only matches
    2559     * an empty search CharSequence.</p>
    2560     *
    2561     * <pre>
    2562     * StringUtils.indexOf(null, *, *)          = -1
    2563     * StringUtils.indexOf(*, null, *)          = -1
    2564     * StringUtils.indexOf("", "", 0)           = 0
    2565     * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
    2566     * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
    2567     * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
    2568     * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
    2569     * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
    2570     * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
    2571     * StringUtils.indexOf("aabaabaa", "b", -1) = 2
    2572     * StringUtils.indexOf("aabaabaa", "", 2)   = 2
    2573     * StringUtils.indexOf("abc", "", 9)        = 3
    2574     * </pre>
    2575     *
    2576     * @param seq  the CharSequence to check, may be null
    2577     * @param searchSeq  the CharSequence to find, may be null
    2578     * @param startPos  the start position, negative treated as zero
    2579     * @return the first index of the search CharSequence (always &ge; startPos),
    2580     *  -1 if no match or {@code null} string input
    2581     * @since 2.0
    2582     * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
    2583     */
    2584    public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
    2585        if (seq == null || searchSeq == null) {
    2586            return INDEX_NOT_FOUND;
    2587        }
    2588        return CharSequenceUtils.indexOf(seq, searchSeq, startPos);
    2589    }
    2590
    2591    // IndexOf
    2592    //-----------------------------------------------------------------------
    2593    /**
    2594     * Returns the index within {@code seq} of the first occurrence of
    2595     * the specified character. If a character with value
    2596     * {@code searchChar} occurs in the character sequence represented by
    2597     * {@code seq} {@code CharSequence} object, then the index (in Unicode
    2598     * code units) of the first such occurrence is returned. For
    2599     * values of {@code searchChar} in the range from 0 to 0xFFFF
    2600     * (inclusive), this is the smallest value <i>k</i> such that:
    2601     * <blockquote><pre>
    2602     * this.charAt(<i>k</i>) == searchChar
    2603     * </pre></blockquote>
    2604     * is true. For other values of {@code searchChar}, it is the
    2605     * smallest value <i>k</i> such that:
    2606     * <blockquote><pre>
    2607     * this.codePointAt(<i>k</i>) == searchChar
    2608     * </pre></blockquote>
    2609     * is true. In either case, if no such character occurs in {@code seq},
    2610     * then {@code INDEX_NOT_FOUND (-1)} is returned.
    2611     *
    2612     * <p>Furthermore, a {@code null} or empty ("") CharSequence will
    2613     * return {@code INDEX_NOT_FOUND (-1)}.</p>
    2614     *
    2615     * <pre>
    2616     * StringUtils.indexOf(null, *)         = -1
    2617     * StringUtils.indexOf("", *)           = -1
    2618     * StringUtils.indexOf("aabaabaa", 'a') = 0
    2619     * StringUtils.indexOf("aabaabaa", 'b') = 2
    2620     * </pre>
    2621     *
    2622     * @param seq  the CharSequence to check, may be null
    2623     * @param searchChar  the character to find
    2624     * @return the first index of the search character,
    2625     *  -1 if no match or {@code null} string input
    2626     * @since 2.0
    2627     * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
    2628     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    2629     */
    2630    public static int indexOf(final CharSequence seq, final int searchChar) {
    2631        if (isEmpty(seq)) {
    2632            return INDEX_NOT_FOUND;
    2633        }
    2634        return CharSequenceUtils.indexOf(seq, searchChar, 0);
    2635    }
    2636
    2637    /**
    2638     *
    2639     * Returns the index within {@code seq} of the first occurrence of the
    2640     * specified character, starting the search at the specified index.
    2641     * <p>
    2642     * If a character with value {@code searchChar} occurs in the
    2643     * character sequence represented by the {@code seq} {@code CharSequence}
    2644     * object at an index no smaller than {@code startPos}, then
    2645     * the index of the first such occurrence is returned. For values
    2646     * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive),
    2647     * this is the smallest value <i>k</i> such that:
    2648     * <blockquote><pre>
    2649     * (this.charAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &gt;= startPos)
    2650     * </pre></blockquote>
    2651     * is true. For other values of {@code searchChar}, it is the
    2652     * smallest value <i>k</i> such that:
    2653     * <blockquote><pre>
    2654     * (this.codePointAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &gt;= startPos)
    2655     * </pre></blockquote>
    2656     * is true. In either case, if no such character occurs in {@code seq}
    2657     * at or after position {@code startPos}, then
    2658     * {@code -1} is returned.
    2659     *
    2660     * <p>
    2661     * There is no restriction on the value of {@code startPos}. If it
    2662     * is negative, it has the same effect as if it were zero: this entire
    2663     * string may be searched. If it is greater than the length of this
    2664     * string, it has the same effect as if it were equal to the length of
    2665     * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a
    2666     * {@code null} or empty ("") CharSequence will
    2667     * return {@code (INDEX_NOT_FOUND) -1}.
    2668     *
    2669     * <p>All indices are specified in {@code char} values
    2670     * (Unicode code units).
    2671     *
    2672     * <pre>
    2673     * StringUtils.indexOf(null, *, *)          = -1
    2674     * StringUtils.indexOf("", *, *)            = -1
    2675     * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
    2676     * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
    2677     * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
    2678     * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
    2679     * </pre>
    2680     *
    2681     * @param seq  the CharSequence to check, may be null
    2682     * @param searchChar  the character to find
    2683     * @param startPos  the start position, negative treated as zero
    2684     * @return the first index of the search character (always &ge; startPos),
    2685     *  -1 if no match or {@code null} string input
    2686     * @since 2.0
    2687     * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
    2688     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    2689     */
    2690    public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
    2691        if (isEmpty(seq)) {
    2692            return INDEX_NOT_FOUND;
    2693        }
    2694        return CharSequenceUtils.indexOf(seq, searchChar, startPos);
    2695    }
    2696
    2697    // IndexOfAny chars
    2698    //-----------------------------------------------------------------------
    2699    /**
    2700     * <p>Search a CharSequence to find the first index of any
    2701     * character in the given set of characters.</p>
    2702     *
    2703     * <p>A {@code null} String will return {@code -1}.
    2704     * A {@code null} or zero length search array will return {@code -1}.</p>
    2705     *
    2706     * <pre>
    2707     * StringUtils.indexOfAny(null, *)                  = -1
    2708     * StringUtils.indexOfAny("", *)                    = -1
    2709     * StringUtils.indexOfAny(*, null)                  = -1
    2710     * StringUtils.indexOfAny(*, [])                    = -1
    2711     * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0
    2712     * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3
    2713     * StringUtils.indexOfAny("aba", ['z'])             = -1
    2714     * </pre>
    2715     *
    2716     * @param cs  the CharSequence to check, may be null
    2717     * @param searchChars  the chars to search for, may be null
    2718     * @return the index of any of the chars, -1 if no match or null input
    2719     * @since 2.0
    2720     * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
    2721     */
    2722    public static int indexOfAny(final CharSequence cs, final char... searchChars) {
    2723        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    2724            return INDEX_NOT_FOUND;
    2725        }
    2726        final int csLen = cs.length();
    2727        final int csLast = csLen - 1;
    2728        final int searchLen = searchChars.length;
    2729        final int searchLast = searchLen - 1;
    2730        for (int i = 0; i < csLen; i++) {
    2731            final char ch = cs.charAt(i);
    2732            for (int j = 0; j < searchLen; j++) {
    2733                if (searchChars[j] == ch) {
    2734                    if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
    2735                        // ch is a supplementary character
    2736                        if (searchChars[j + 1] == cs.charAt(i + 1)) {
    2737                            return i;
    2738                        }
    2739                    } else {
    2740                        return i;
    2741                    }
    2742                }
    2743            }
    2744        }
    2745        return INDEX_NOT_FOUND;
    2746    }
    2747
    2748    // IndexOfAny strings
    2749    //-----------------------------------------------------------------------
    2750    /**
    2751     * <p>Find the first index of any of a set of potential substrings.</p>
    2752     *
    2753     * <p>A {@code null} CharSequence will return {@code -1}.
    2754     * A {@code null} or zero length search array will return {@code -1}.
    2755     * A {@code null} search array entry will be ignored, but a search
    2756     * array containing "" will return {@code 0} if {@code str} is not
    2757     * null. This method uses {@link String#indexOf(String)} if possible.</p>
    2758     *
    2759     * <pre>
    2760     * StringUtils.indexOfAny(null, *)                      = -1
    2761     * StringUtils.indexOfAny(*, null)                      = -1
    2762     * StringUtils.indexOfAny(*, [])                        = -1
    2763     * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"])   = 2
    2764     * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"])   = 2
    2765     * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"])   = -1
    2766     * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1
    2767     * StringUtils.indexOfAny("zzabyycdxx", [""])           = 0
    2768     * StringUtils.indexOfAny("", [""])                     = 0
    2769     * StringUtils.indexOfAny("", ["a"])                    = -1
    2770     * </pre>
    2771     *
    2772     * @param str  the CharSequence to check, may be null
    2773     * @param searchStrs  the CharSequences to search for, may be null
    2774     * @return the first index of any of the searchStrs in str, -1 if no match
    2775     * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
    2776     */
    2777    public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
    2778        if (str == null || searchStrs == null) {
    2779            return INDEX_NOT_FOUND;
    2780        }
    2781
    2782        // String's can't have a MAX_VALUEth index.
    2783        int ret = Integer.MAX_VALUE;
    2784
    2785        int tmp = 0;
    2786        for (final CharSequence search : searchStrs) {
    2787            if (search == null) {
    2788                continue;
    2789            }
    2790            tmp = CharSequenceUtils.indexOf(str, search, 0);
    2791            if (tmp == INDEX_NOT_FOUND) {
    2792                continue;
    2793            }
    2794
    2795            if (tmp < ret) {
    2796                ret = tmp;
    2797            }
    2798        }
    2799
    2800        return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
    2801    }
    2802
    2803    /**
    2804     * <p>Search a CharSequence to find the first index of any
    2805     * character in the given set of characters.</p>
    2806     *
    2807     * <p>A {@code null} String will return {@code -1}.
    2808     * A {@code null} search string will return {@code -1}.</p>
    2809     *
    2810     * <pre>
    2811     * StringUtils.indexOfAny(null, *)            = -1
    2812     * StringUtils.indexOfAny("", *)              = -1
    2813     * StringUtils.indexOfAny(*, null)            = -1
    2814     * StringUtils.indexOfAny(*, "")              = -1
    2815     * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
    2816     * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
    2817     * StringUtils.indexOfAny("aba", "z")         = -1
    2818     * </pre>
    2819     *
    2820     * @param cs  the CharSequence to check, may be null
    2821     * @param searchChars  the chars to search for, may be null
    2822     * @return the index of any of the chars, -1 if no match or null input
    2823     * @since 2.0
    2824     * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
    2825     */
    2826    public static int indexOfAny(final CharSequence cs, final String searchChars) {
    2827        if (isEmpty(cs) || isEmpty(searchChars)) {
    2828            return INDEX_NOT_FOUND;
    2829        }
    2830        return indexOfAny(cs, searchChars.toCharArray());
    2831    }
    2832
    2833    // IndexOfAnyBut chars
    2834    //-----------------------------------------------------------------------
    2835    /**
    2836     * <p>Searches a CharSequence to find the first index of any
    2837     * character not in the given set of characters.</p>
    2838     *
    2839     * <p>A {@code null} CharSequence will return {@code -1}.
    2840     * A {@code null} or zero length search array will return {@code -1}.</p>
    2841     *
    2842     * <pre>
    2843     * StringUtils.indexOfAnyBut(null, *)                              = -1
    2844     * StringUtils.indexOfAnyBut("", *)                                = -1
    2845     * StringUtils.indexOfAnyBut(*, null)                              = -1
    2846     * StringUtils.indexOfAnyBut(*, [])                                = -1
    2847     * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
    2848     * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
    2849     * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1
    2850
    2851     * </pre>
    2852     *
    2853     * @param cs  the CharSequence to check, may be null
    2854     * @param searchChars  the chars to search for, may be null
    2855     * @return the index of any of the chars, -1 if no match or null input
    2856     * @since 2.0
    2857     * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
    2858     */
    2859    public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
    2860        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
    2861            return INDEX_NOT_FOUND;
    2862        }
    2863        final int csLen = cs.length();
    2864        final int csLast = csLen - 1;
    2865        final int searchLen = searchChars.length;
    2866        final int searchLast = searchLen - 1;
    2867        outer:
    2868        for (int i = 0; i < csLen; i++) {
    2869            final char ch = cs.charAt(i);
    2870            for (int j = 0; j < searchLen; j++) {
    2871                if (searchChars[j] == ch) {
    2872                    if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
    2873                        if (searchChars[j + 1] == cs.charAt(i + 1)) {
    2874                            continue outer;
    2875                        }
    2876                    } else {
    2877                        continue outer;
    2878                    }
    2879                }
    2880            }
    2881            return i;
    2882        }
    2883        return INDEX_NOT_FOUND;
    2884    }
    2885
    2886    /**
    2887     * <p>Search a CharSequence to find the first index of any
    2888     * character not in the given set of characters.</p>
    2889     *
    2890     * <p>A {@code null} CharSequence will return {@code -1}.
    2891     * A {@code null} or empty search string will return {@code -1}.</p>
    2892     *
    2893     * <pre>
    2894     * StringUtils.indexOfAnyBut(null, *)            = -1
    2895     * StringUtils.indexOfAnyBut("", *)              = -1
    2896     * StringUtils.indexOfAnyBut(*, null)            = -1
    2897     * StringUtils.indexOfAnyBut(*, "")              = -1
    2898     * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
    2899     * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
    2900     * StringUtils.indexOfAnyBut("aba", "ab")        = -1
    2901     * </pre>
    2902     *
    2903     * @param seq  the CharSequence to check, may be null
    2904     * @param searchChars  the chars to search for, may be null
    2905     * @return the index of any of the chars, -1 if no match or null input
    2906     * @since 2.0
    2907     * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
    2908     */
    2909    public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
    2910        if (isEmpty(seq) || isEmpty(searchChars)) {
    2911            return INDEX_NOT_FOUND;
    2912        }
    2913        final int strLen = seq.length();
    2914        for (int i = 0; i < strLen; i++) {
    2915            final char ch = seq.charAt(i);
    2916            final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;
    2917            if (i + 1 < strLen && Character.isHighSurrogate(ch)) {
    2918                final char ch2 = seq.charAt(i + 1);
    2919                if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {
    2920                    return i;
    2921                }
    2922            } else {
    2923                if (!chFound) {
    2924                    return i;
    2925                }
    2926            }
    2927        }
    2928        return INDEX_NOT_FOUND;
    2929    }
    2930
    2931    /**
    2932     * <p>Compares all CharSequences in an array and returns the index at which the
    2933     * CharSequences begin to differ.</p>
    2934     *
    2935     * <p>For example,
    2936     * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p>
    2937     *
    2938     * <pre>
    2939     * StringUtils.indexOfDifference(null) = -1
    2940     * StringUtils.indexOfDifference(new String[] {}) = -1
    2941     * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
    2942     * StringUtils.indexOfDifference(new String[] {null, null}) = -1
    2943     * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
    2944     * StringUtils.indexOfDifference(new String[] {"", null}) = 0
    2945     * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
    2946     * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
    2947     * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
    2948     * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
    2949     * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
    2950     * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
    2951     * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
    2952     * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
    2953     * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
    2954     * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
    2955     * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
    2956     * </pre>
    2957     *
    2958     * @param css  array of CharSequences, entries may be null
    2959     * @return the index where the strings begin to differ; -1 if they are all equal
    2960     * @since 2.4
    2961     * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
    2962     */
    2963    public static int indexOfDifference(final CharSequence... css) {
    2964        if (ArrayUtils.getLength(css) <= 1) {
    2965            return INDEX_NOT_FOUND;
    2966        }
    2967        boolean anyStringNull = false;
    2968        boolean allStringsNull = true;
    2969        final int arrayLen = css.length;
    2970        int shortestStrLen = Integer.MAX_VALUE;
    2971        int longestStrLen = 0;
    2972
    2973        // find the min and max string lengths; this avoids checking to make
    2974        // sure we are not exceeding the length of the string each time through
    2975        // the bottom loop.
    2976        for (final CharSequence cs : css) {
    2977            if (cs == null) {
    2978                anyStringNull = true;
    2979                shortestStrLen = 0;
    2980            } else {
    2981                allStringsNull = false;
    2982                shortestStrLen = Math.min(cs.length(), shortestStrLen);
    2983                longestStrLen = Math.max(cs.length(), longestStrLen);
    2984            }
    2985        }
    2986
    2987        // handle lists containing all nulls or all empty strings
    2988        if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
    2989            return INDEX_NOT_FOUND;
    2990        }
    2991
    2992        // handle lists containing some nulls or some empty strings
    2993        if (shortestStrLen == 0) {
    2994            return 0;
    2995        }
    2996
    2997        // find the position with the first difference across all strings
    2998        int firstDiff = -1;
    2999        for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
    3000            final char comparisonChar = css[0].charAt(stringPos);
    3001            for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
    3002                if (css[arrayPos].charAt(stringPos) != comparisonChar) {
    3003                    firstDiff = stringPos;
    3004                    break;
    3005                }
    3006            }
    3007            if (firstDiff != -1) {
    3008                break;
    3009            }
    3010        }
    3011
    3012        if (firstDiff == -1 && shortestStrLen != longestStrLen) {
    3013            // we compared all of the characters up to the length of the
    3014            // shortest string and didn't find a match, but the string lengths
    3015            // vary, so return the length of the shortest string.
    3016            return shortestStrLen;
    3017        }
    3018        return firstDiff;
    3019    }
    3020
    3021    /**
    3022     * <p>Compares two CharSequences, and returns the index at which the
    3023     * CharSequences begin to differ.</p>
    3024     *
    3025     * <p>For example,
    3026     * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p>
    3027     *
    3028     * <pre>
    3029     * StringUtils.indexOfDifference(null, null) = -1
    3030     * StringUtils.indexOfDifference("", "") = -1
    3031     * StringUtils.indexOfDifference("", "abc") = 0
    3032     * StringUtils.indexOfDifference("abc", "") = 0
    3033     * StringUtils.indexOfDifference("abc", "abc") = -1
    3034     * StringUtils.indexOfDifference("ab", "abxyz") = 2
    3035     * StringUtils.indexOfDifference("abcde", "abxyz") = 2
    3036     * StringUtils.indexOfDifference("abcde", "xyz") = 0
    3037     * </pre>
    3038     *
    3039     * @param cs1  the first CharSequence, may be null
    3040     * @param cs2  the second CharSequence, may be null
    3041     * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
    3042     * @since 2.0
    3043     * @since 3.0 Changed signature from indexOfDifference(String, String) to
    3044     * indexOfDifference(CharSequence, CharSequence)
    3045     */
    3046    public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
    3047        if (cs1 == cs2) {
    3048            return INDEX_NOT_FOUND;
    3049        }
    3050        if (cs1 == null || cs2 == null) {
    3051            return 0;
    3052        }
    3053        int i;
    3054        for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
    3055            if (cs1.charAt(i) != cs2.charAt(i)) {
    3056                break;
    3057            }
    3058        }
    3059        if (i < cs2.length() || i < cs1.length()) {
    3060            return i;
    3061        }
    3062        return INDEX_NOT_FOUND;
    3063    }
    3064
    3065    /**
    3066     * <p>Case in-sensitive find of the first index within a CharSequence.</p>
    3067     *
    3068     * <p>A {@code null} CharSequence will return {@code -1}.
    3069     * A negative start position is treated as zero.
    3070     * An empty ("") search CharSequence always matches.
    3071     * A start position greater than the string length only matches
    3072     * an empty search CharSequence.</p>
    3073     *
    3074     * <pre>
    3075     * StringUtils.indexOfIgnoreCase(null, *)          = -1
    3076     * StringUtils.indexOfIgnoreCase(*, null)          = -1
    3077     * StringUtils.indexOfIgnoreCase("", "")           = 0
    3078     * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
    3079     * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
    3080     * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
    3081     * </pre>
    3082     *
    3083     * @param str  the CharSequence to check, may be null
    3084     * @param searchStr  the CharSequence to find, may be null
    3085     * @return the first index of the search CharSequence,
    3086     *  -1 if no match or {@code null} string input
    3087     * @since 2.5
    3088     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
    3089     */
    3090    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    3091        return indexOfIgnoreCase(str, searchStr, 0);
    3092    }
    3093
    3094    /**
    3095     * <p>Case in-sensitive find of the first index within a CharSequence
    3096     * from the specified position.</p>
    3097     *
    3098     * <p>A {@code null} CharSequence will return {@code -1}.
    3099     * A negative start position is treated as zero.
    3100     * An empty ("") search CharSequence always matches.
    3101     * A start position greater than the string length only matches
    3102     * an empty search CharSequence.</p>
    3103     *
    3104     * <pre>
    3105     * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
    3106     * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
    3107     * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
    3108     * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    3109     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
    3110     * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
    3111     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
    3112     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
    3113     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
    3114     * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
    3115     * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1
    3116     * </pre>
    3117     *
    3118     * @param str  the CharSequence to check, may be null
    3119     * @param searchStr  the CharSequence to find, may be null
    3120     * @param startPos  the start position, negative treated as zero
    3121     * @return the first index of the search CharSequence (always &ge; startPos),
    3122     *  -1 if no match or {@code null} string input
    3123     * @since 2.5
    3124     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
    3125     */
    3126    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
    3127        if (str == null || searchStr == null) {
    3128            return INDEX_NOT_FOUND;
    3129        }
    3130        if (startPos < 0) {
    3131            startPos = 0;
    3132        }
    3133        final int endLimit = str.length() - searchStr.length() + 1;
    3134        if (startPos > endLimit) {
    3135            return INDEX_NOT_FOUND;
    3136        }
    3137        if (searchStr.length() == 0) {
    3138            return startPos;
    3139        }
    3140        for (int i = startPos; i < endLimit; i++) {
    3141            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
    3142                return i;
    3143            }
    3144        }
    3145        return INDEX_NOT_FOUND;
    3146    }
    3147
    3148    /**
    3149     * <p>Checks if all of the CharSequences are empty (""), null or whitespace only.</p>
    3150     *
    3151     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3152     *
    3153     * <pre>
    3154     * StringUtils.isAllBlank(null)             = true
    3155     * StringUtils.isAllBlank(null, "foo")      = false
    3156     * StringUtils.isAllBlank(null, null)       = true
    3157     * StringUtils.isAllBlank("", "bar")        = false
    3158     * StringUtils.isAllBlank("bob", "")        = false
    3159     * StringUtils.isAllBlank("  bob  ", null)  = false
    3160     * StringUtils.isAllBlank(" ", "bar")       = false
    3161     * StringUtils.isAllBlank("foo", "bar")     = false
    3162     * StringUtils.isAllBlank(new String[] {})  = true
    3163     * </pre>
    3164     *
    3165     * @param css  the CharSequences to check, may be null or empty
    3166     * @return {@code true} if all of the CharSequences are empty or null or whitespace only
    3167     * @since 3.6
    3168     */
    3169    public static boolean isAllBlank(final CharSequence... css) {
    3170        if (ArrayUtils.isEmpty(css)) {
    3171            return true;
    3172        }
    3173        for (final CharSequence cs : css) {
    3174            if (isNotBlank(cs)) {
    3175               return false;
    3176            }
    3177        }
    3178        return true;
    3179    }
    3180
    3181    /**
    3182     * <p>Checks if all of the CharSequences are empty ("") or null.</p>
    3183     *
    3184     * <pre>
    3185     * StringUtils.isAllEmpty(null)             = true
    3186     * StringUtils.isAllEmpty(null, "")         = true
    3187     * StringUtils.isAllEmpty(new String[] {})  = true
    3188     * StringUtils.isAllEmpty(null, "foo")      = false
    3189     * StringUtils.isAllEmpty("", "bar")        = false
    3190     * StringUtils.isAllEmpty("bob", "")        = false
    3191     * StringUtils.isAllEmpty("  bob  ", null)  = false
    3192     * StringUtils.isAllEmpty(" ", "bar")       = false
    3193     * StringUtils.isAllEmpty("foo", "bar")     = false
    3194     * </pre>
    3195     *
    3196     * @param css  the CharSequences to check, may be null or empty
    3197     * @return {@code true} if all of the CharSequences are empty or null
    3198     * @since 3.6
    3199     */
    3200    public static boolean isAllEmpty(final CharSequence... css) {
    3201        if (ArrayUtils.isEmpty(css)) {
    3202            return true;
    3203        }
    3204        for (final CharSequence cs : css) {
    3205            if (isNotEmpty(cs)) {
    3206                return false;
    3207            }
    3208        }
    3209        return true;
    3210    }
    3211
    3212    /**
    3213     * <p>Checks if the CharSequence contains only lowercase characters.</p>
    3214     *
    3215     * <p>{@code null} will return {@code false}.
    3216     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3217     *
    3218     * <pre>
    3219     * StringUtils.isAllLowerCase(null)   = false
    3220     * StringUtils.isAllLowerCase("")     = false
    3221     * StringUtils.isAllLowerCase("  ")   = false
    3222     * StringUtils.isAllLowerCase("abc")  = true
    3223     * StringUtils.isAllLowerCase("abC")  = false
    3224     * StringUtils.isAllLowerCase("ab c") = false
    3225     * StringUtils.isAllLowerCase("ab1c") = false
    3226     * StringUtils.isAllLowerCase("ab/c") = false
    3227     * </pre>
    3228     *
    3229     * @param cs  the CharSequence to check, may be null
    3230     * @return {@code true} if only contains lowercase characters, and is non-null
    3231     * @since 2.5
    3232     * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
    3233     */
    3234    public static boolean isAllLowerCase(final CharSequence cs) {
    3235        if (isEmpty(cs)) {
    3236            return false;
    3237        }
    3238        final int sz = cs.length();
    3239        for (int i = 0; i < sz; i++) {
    3240            if (!Character.isLowerCase(cs.charAt(i))) {
    3241                return false;
    3242            }
    3243        }
    3244        return true;
    3245    }
    3246
    3247    /**
    3248     * <p>Checks if the CharSequence contains only uppercase characters.</p>
    3249     *
    3250     * <p>{@code null} will return {@code false}.
    3251     * An empty String (length()=0) will return {@code false}.</p>
    3252     *
    3253     * <pre>
    3254     * StringUtils.isAllUpperCase(null)   = false
    3255     * StringUtils.isAllUpperCase("")     = false
    3256     * StringUtils.isAllUpperCase("  ")   = false
    3257     * StringUtils.isAllUpperCase("ABC")  = true
    3258     * StringUtils.isAllUpperCase("aBC")  = false
    3259     * StringUtils.isAllUpperCase("A C")  = false
    3260     * StringUtils.isAllUpperCase("A1C")  = false
    3261     * StringUtils.isAllUpperCase("A/C")  = false
    3262     * </pre>
    3263     *
    3264     * @param cs the CharSequence to check, may be null
    3265     * @return {@code true} if only contains uppercase characters, and is non-null
    3266     * @since 2.5
    3267     * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
    3268     */
    3269    public static boolean isAllUpperCase(final CharSequence cs) {
    3270        if (isEmpty(cs)) {
    3271            return false;
    3272        }
    3273        final int sz = cs.length();
    3274        for (int i = 0; i < sz; i++) {
    3275            if (!Character.isUpperCase(cs.charAt(i))) {
    3276                return false;
    3277            }
    3278        }
    3279        return true;
    3280    }
    3281
    3282    // Character Tests
    3283    //-----------------------------------------------------------------------
    3284    /**
    3285     * <p>Checks if the CharSequence contains only Unicode letters.</p>
    3286     *
    3287     * <p>{@code null} will return {@code false}.
    3288     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3289     *
    3290     * <pre>
    3291     * StringUtils.isAlpha(null)   = false
    3292     * StringUtils.isAlpha("")     = false
    3293     * StringUtils.isAlpha("  ")   = false
    3294     * StringUtils.isAlpha("abc")  = true
    3295     * StringUtils.isAlpha("ab2c") = false
    3296     * StringUtils.isAlpha("ab-c") = false
    3297     * </pre>
    3298     *
    3299     * @param cs  the CharSequence to check, may be null
    3300     * @return {@code true} if only contains letters, and is non-null
    3301     * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
    3302     * @since 3.0 Changed "" to return false and not true
    3303     */
    3304    public static boolean isAlpha(final CharSequence cs) {
    3305        if (isEmpty(cs)) {
    3306            return false;
    3307        }
    3308        final int sz = cs.length();
    3309        for (int i = 0; i < sz; i++) {
    3310            if (!Character.isLetter(cs.charAt(i))) {
    3311                return false;
    3312            }
    3313        }
    3314        return true;
    3315    }
    3316
    3317    /**
    3318     * <p>Checks if the CharSequence contains only Unicode letters or digits.</p>
    3319     *
    3320     * <p>{@code null} will return {@code false}.
    3321     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3322     *
    3323     * <pre>
    3324     * StringUtils.isAlphanumeric(null)   = false
    3325     * StringUtils.isAlphanumeric("")     = false
    3326     * StringUtils.isAlphanumeric("  ")   = false
    3327     * StringUtils.isAlphanumeric("abc")  = true
    3328     * StringUtils.isAlphanumeric("ab c") = false
    3329     * StringUtils.isAlphanumeric("ab2c") = true
    3330     * StringUtils.isAlphanumeric("ab-c") = false
    3331     * </pre>
    3332     *
    3333     * @param cs  the CharSequence to check, may be null
    3334     * @return {@code true} if only contains letters or digits,
    3335     *  and is non-null
    3336     * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
    3337     * @since 3.0 Changed "" to return false and not true
    3338     */
    3339    public static boolean isAlphanumeric(final CharSequence cs) {
    3340        if (isEmpty(cs)) {
    3341            return false;
    3342        }
    3343        final int sz = cs.length();
    3344        for (int i = 0; i < sz; i++) {
    3345            if (!Character.isLetterOrDigit(cs.charAt(i))) {
    3346                return false;
    3347            }
    3348        }
    3349        return true;
    3350    }
    3351
    3352    /**
    3353     * <p>Checks if the CharSequence contains only Unicode letters, digits
    3354     * or space ({@code ' '}).</p>
    3355     *
    3356     * <p>{@code null} will return {@code false}.
    3357     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3358     *
    3359     * <pre>
    3360     * StringUtils.isAlphanumericSpace(null)   = false
    3361     * StringUtils.isAlphanumericSpace("")     = true
    3362     * StringUtils.isAlphanumericSpace("  ")   = true
    3363     * StringUtils.isAlphanumericSpace("abc")  = true
    3364     * StringUtils.isAlphanumericSpace("ab c") = true
    3365     * StringUtils.isAlphanumericSpace("ab2c") = true
    3366     * StringUtils.isAlphanumericSpace("ab-c") = false
    3367     * </pre>
    3368     *
    3369     * @param cs  the CharSequence to check, may be null
    3370     * @return {@code true} if only contains letters, digits or space,
    3371     *  and is non-null
    3372     * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
    3373     */
    3374    public static boolean isAlphanumericSpace(final CharSequence cs) {
    3375        if (cs == null) {
    3376            return false;
    3377        }
    3378        final int sz = cs.length();
    3379        for (int i = 0; i < sz; i++) {
    3380            if (!Character.isLetterOrDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3381                return false;
    3382            }
    3383        }
    3384        return true;
    3385    }
    3386
    3387    /**
    3388     * <p>Checks if the CharSequence contains only Unicode letters and
    3389     * space (' ').</p>
    3390     *
    3391     * <p>{@code null} will return {@code false}
    3392     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3393     *
    3394     * <pre>
    3395     * StringUtils.isAlphaSpace(null)   = false
    3396     * StringUtils.isAlphaSpace("")     = true
    3397     * StringUtils.isAlphaSpace("  ")   = true
    3398     * StringUtils.isAlphaSpace("abc")  = true
    3399     * StringUtils.isAlphaSpace("ab c") = true
    3400     * StringUtils.isAlphaSpace("ab2c") = false
    3401     * StringUtils.isAlphaSpace("ab-c") = false
    3402     * </pre>
    3403     *
    3404     * @param cs  the CharSequence to check, may be null
    3405     * @return {@code true} if only contains letters and space,
    3406     *  and is non-null
    3407     * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
    3408     */
    3409    public static boolean isAlphaSpace(final CharSequence cs) {
    3410        if (cs == null) {
    3411            return false;
    3412        }
    3413        final int sz = cs.length();
    3414        for (int i = 0; i < sz; i++) {
    3415            if (!Character.isLetter(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3416                return false;
    3417            }
    3418        }
    3419        return true;
    3420    }
    3421
    3422    /**
    3423     * <p>Checks if any of the CharSequences are empty ("") or null or whitespace only.</p>
    3424     *
    3425     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3426     *
    3427     * <pre>
    3428     * StringUtils.isAnyBlank((String) null)    = true
    3429     * StringUtils.isAnyBlank((String[]) null)  = false
    3430     * StringUtils.isAnyBlank(null, "foo")      = true
    3431     * StringUtils.isAnyBlank(null, null)       = true
    3432     * StringUtils.isAnyBlank("", "bar")        = true
    3433     * StringUtils.isAnyBlank("bob", "")        = true
    3434     * StringUtils.isAnyBlank("  bob  ", null)  = true
    3435     * StringUtils.isAnyBlank(" ", "bar")       = true
    3436     * StringUtils.isAnyBlank(new String[] {})  = false
    3437     * StringUtils.isAnyBlank(new String[]{""}) = true
    3438     * StringUtils.isAnyBlank("foo", "bar")     = false
    3439     * </pre>
    3440     *
    3441     * @param css  the CharSequences to check, may be null or empty
    3442     * @return {@code true} if any of the CharSequences are empty or null or whitespace only
    3443     * @since 3.2
    3444     */
    3445    public static boolean isAnyBlank(final CharSequence... css) {
    3446      if (ArrayUtils.isEmpty(css)) {
    3447        return false;
    3448      }
    3449      for (final CharSequence cs : css) {
    3450        if (isBlank(cs)) {
    3451          return true;
    3452        }
    3453      }
    3454      return false;
    3455    }
    3456
    3457    /**
    3458     * <p>Checks if any of the CharSequences are empty ("") or null.</p>
    3459     *
    3460     * <pre>
    3461     * StringUtils.isAnyEmpty((String) null)    = true
    3462     * StringUtils.isAnyEmpty((String[]) null)  = false
    3463     * StringUtils.isAnyEmpty(null, "foo")      = true
    3464     * StringUtils.isAnyEmpty("", "bar")        = true
    3465     * StringUtils.isAnyEmpty("bob", "")        = true
    3466     * StringUtils.isAnyEmpty("  bob  ", null)  = true
    3467     * StringUtils.isAnyEmpty(" ", "bar")       = false
    3468     * StringUtils.isAnyEmpty("foo", "bar")     = false
    3469     * StringUtils.isAnyEmpty(new String[]{})   = false
    3470     * StringUtils.isAnyEmpty(new String[]{""}) = true
    3471     * </pre>
    3472     *
    3473     * @param css  the CharSequences to check, may be null or empty
    3474     * @return {@code true} if any of the CharSequences are empty or null
    3475     * @since 3.2
    3476     */
    3477    public static boolean isAnyEmpty(final CharSequence... css) {
    3478      if (ArrayUtils.isEmpty(css)) {
    3479        return false;
    3480      }
    3481      for (final CharSequence cs : css) {
    3482        if (isEmpty(cs)) {
    3483          return true;
    3484        }
    3485      }
    3486      return false;
    3487    }
    3488
    3489    /**
    3490     * <p>Checks if the CharSequence contains only ASCII printable characters.</p>
    3491     *
    3492     * <p>{@code null} will return {@code false}.
    3493     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3494     *
    3495     * <pre>
    3496     * StringUtils.isAsciiPrintable(null)     = false
    3497     * StringUtils.isAsciiPrintable("")       = true
    3498     * StringUtils.isAsciiPrintable(" ")      = true
    3499     * StringUtils.isAsciiPrintable("Ceki")   = true
    3500     * StringUtils.isAsciiPrintable("ab2c")   = true
    3501     * StringUtils.isAsciiPrintable("!ab-c~") = true
    3502     * StringUtils.isAsciiPrintable("\u0020") = true
    3503     * StringUtils.isAsciiPrintable("\u0021") = true
    3504     * StringUtils.isAsciiPrintable("\u007e") = true
    3505     * StringUtils.isAsciiPrintable("\u007f") = false
    3506     * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
    3507     * </pre>
    3508     *
    3509     * @param cs the CharSequence to check, may be null
    3510     * @return {@code true} if every character is in the range
    3511     *  32 thru 126
    3512     * @since 2.1
    3513     * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
    3514     */
    3515    public static boolean isAsciiPrintable(final CharSequence cs) {
    3516        if (cs == null) {
    3517            return false;
    3518        }
    3519        final int sz = cs.length();
    3520        for (int i = 0; i < sz; i++) {
    3521            if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
    3522                return false;
    3523            }
    3524        }
    3525        return true;
    3526    }
    3527
    3528    // Nested extraction
    3529    //-----------------------------------------------------------------------
    3530
    3531    /**
    3532     * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
    3533     *
    3534     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3535     *
    3536     * <pre>
    3537     * StringUtils.isBlank(null)      = true
    3538     * StringUtils.isBlank("")        = true
    3539     * StringUtils.isBlank(" ")       = true
    3540     * StringUtils.isBlank("bob")     = false
    3541     * StringUtils.isBlank("  bob  ") = false
    3542     * </pre>
    3543     *
    3544     * @param cs  the CharSequence to check, may be null
    3545     * @return {@code true} if the CharSequence is null, empty or whitespace only
    3546     * @since 2.0
    3547     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
    3548     */
    3549    public static boolean isBlank(final CharSequence cs) {
    3550        final int strLen = length(cs);
    3551        if (strLen == 0) {
    3552            return true;
    3553        }
    3554        for (int i = 0; i < strLen; i++) {
    3555            if (!Character.isWhitespace(cs.charAt(i))) {
    3556                return false;
    3557            }
    3558        }
    3559        return true;
    3560    }
    3561
    3562    // Empty checks
    3563    //-----------------------------------------------------------------------
    3564    /**
    3565     * <p>Checks if a CharSequence is empty ("") or null.</p>
    3566     *
    3567     * <pre>
    3568     * StringUtils.isEmpty(null)      = true
    3569     * StringUtils.isEmpty("")        = true
    3570     * StringUtils.isEmpty(" ")       = false
    3571     * StringUtils.isEmpty("bob")     = false
    3572     * StringUtils.isEmpty("  bob  ") = false
    3573     * </pre>
    3574     *
    3575     * <p>NOTE: This method changed in Lang version 2.0.
    3576     * It no longer trims the CharSequence.
    3577     * That functionality is available in isBlank().</p>
    3578     *
    3579     * @param cs  the CharSequence to check, may be null
    3580     * @return {@code true} if the CharSequence is empty or null
    3581     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
    3582     */
    3583    public static boolean isEmpty(final CharSequence cs) {
    3584        return cs == null || cs.length() == 0;
    3585    }
    3586
    3587    /**
    3588     * <p>Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.</p>
    3589     *
    3590     * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return
    3591     * {@code false}.</p>
    3592     *
    3593     * <pre>
    3594     * StringUtils.isMixedCase(null)    = false
    3595     * StringUtils.isMixedCase("")      = false
    3596     * StringUtils.isMixedCase("ABC")   = false
    3597     * StringUtils.isMixedCase("abc")   = false
    3598     * StringUtils.isMixedCase("aBc")   = true
    3599     * StringUtils.isMixedCase("A c")   = true
    3600     * StringUtils.isMixedCase("A1c")   = true
    3601     * StringUtils.isMixedCase("a/C")   = true
    3602     * StringUtils.isMixedCase("aC\t")  = true
    3603     * </pre>
    3604     *
    3605     * @param cs the CharSequence to check, may be null
    3606     * @return {@code true} if the CharSequence contains both uppercase and lowercase characters
    3607     * @since 3.5
    3608     */
    3609    public static boolean isMixedCase(final CharSequence cs) {
    3610        if (isEmpty(cs) || cs.length() == 1) {
    3611            return false;
    3612        }
    3613        boolean containsUppercase = false;
    3614        boolean containsLowercase = false;
    3615        final int sz = cs.length();
    3616        for (int i = 0; i < sz; i++) {
    3617            if (containsUppercase && containsLowercase) {
    3618                return true;
    3619            } else if (Character.isUpperCase(cs.charAt(i))) {
    3620                containsUppercase = true;
    3621            } else if (Character.isLowerCase(cs.charAt(i))) {
    3622                containsLowercase = true;
    3623            }
    3624        }
    3625        return containsUppercase && containsLowercase;
    3626    }
    3627
    3628    /**
    3629     * <p>Checks if none of the CharSequences are empty (""), null or whitespace only.</p>
    3630     *
    3631     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3632     *
    3633     * <pre>
    3634     * StringUtils.isNoneBlank((String) null)    = false
    3635     * StringUtils.isNoneBlank((String[]) null)  = true
    3636     * StringUtils.isNoneBlank(null, "foo")      = false
    3637     * StringUtils.isNoneBlank(null, null)       = false
    3638     * StringUtils.isNoneBlank("", "bar")        = false
    3639     * StringUtils.isNoneBlank("bob", "")        = false
    3640     * StringUtils.isNoneBlank("  bob  ", null)  = false
    3641     * StringUtils.isNoneBlank(" ", "bar")       = false
    3642     * StringUtils.isNoneBlank(new String[] {})  = true
    3643     * StringUtils.isNoneBlank(new String[]{""}) = false
    3644     * StringUtils.isNoneBlank("foo", "bar")     = true
    3645     * </pre>
    3646     *
    3647     * @param css  the CharSequences to check, may be null or empty
    3648     * @return {@code true} if none of the CharSequences are empty or null or whitespace only
    3649     * @since 3.2
    3650     */
    3651    public static boolean isNoneBlank(final CharSequence... css) {
    3652      return !isAnyBlank(css);
    3653    }
    3654
    3655    /**
    3656     * <p>Checks if none of the CharSequences are empty ("") or null.</p>
    3657     *
    3658     * <pre>
    3659     * StringUtils.isNoneEmpty((String) null)    = false
    3660     * StringUtils.isNoneEmpty((String[]) null)  = true
    3661     * StringUtils.isNoneEmpty(null, "foo")      = false
    3662     * StringUtils.isNoneEmpty("", "bar")        = false
    3663     * StringUtils.isNoneEmpty("bob", "")        = false
    3664     * StringUtils.isNoneEmpty("  bob  ", null)  = false
    3665     * StringUtils.isNoneEmpty(new String[] {})  = true
    3666     * StringUtils.isNoneEmpty(new String[]{""}) = false
    3667     * StringUtils.isNoneEmpty(" ", "bar")       = true
    3668     * StringUtils.isNoneEmpty("foo", "bar")     = true
    3669     * </pre>
    3670     *
    3671     * @param css  the CharSequences to check, may be null or empty
    3672     * @return {@code true} if none of the CharSequences are empty or null
    3673     * @since 3.2
    3674     */
    3675    public static boolean isNoneEmpty(final CharSequence... css) {
    3676      return !isAnyEmpty(css);
    3677    }
    3678
    3679    /**
    3680     * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
    3681     *
    3682     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3683     *
    3684     * <pre>
    3685     * StringUtils.isNotBlank(null)      = false
    3686     * StringUtils.isNotBlank("")        = false
    3687     * StringUtils.isNotBlank(" ")       = false
    3688     * StringUtils.isNotBlank("bob")     = true
    3689     * StringUtils.isNotBlank("  bob  ") = true
    3690     * </pre>
    3691     *
    3692     * @param cs  the CharSequence to check, may be null
    3693     * @return {@code true} if the CharSequence is
    3694     *  not empty and not null and not whitespace only
    3695     * @since 2.0
    3696     * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
    3697     */
    3698    public static boolean isNotBlank(final CharSequence cs) {
    3699        return !isBlank(cs);
    3700    }
    3701
    3702    /**
    3703     * <p>Checks if a CharSequence is not empty ("") and not null.</p>
    3704     *
    3705     * <pre>
    3706     * StringUtils.isNotEmpty(null)      = false
    3707     * StringUtils.isNotEmpty("")        = false
    3708     * StringUtils.isNotEmpty(" ")       = true
    3709     * StringUtils.isNotEmpty("bob")     = true
    3710     * StringUtils.isNotEmpty("  bob  ") = true
    3711     * </pre>
    3712     *
    3713     * @param cs  the CharSequence to check, may be null
    3714     * @return {@code true} if the CharSequence is not empty and not null
    3715     * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
    3716     */
    3717    public static boolean isNotEmpty(final CharSequence cs) {
    3718        return !isEmpty(cs);
    3719    }
    3720
    3721    /**
    3722     * <p>Checks if the CharSequence contains only Unicode digits.
    3723     * A decimal point is not a Unicode digit and returns false.</p>
    3724     *
    3725     * <p>{@code null} will return {@code false}.
    3726     * An empty CharSequence (length()=0) will return {@code false}.</p>
    3727     *
    3728     * <p>Note that the method does not allow for a leading sign, either positive or negative.
    3729     * Also, if a String passes the numeric test, it may still generate a NumberFormatException
    3730     * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
    3731     * for int or long respectively.</p>
    3732     *
    3733     * <pre>
    3734     * StringUtils.isNumeric(null)   = false
    3735     * StringUtils.isNumeric("")     = false
    3736     * StringUtils.isNumeric("  ")   = false
    3737     * StringUtils.isNumeric("123")  = true
    3738     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
    3739     * StringUtils.isNumeric("12 3") = false
    3740     * StringUtils.isNumeric("ab2c") = false
    3741     * StringUtils.isNumeric("12-3") = false
    3742     * StringUtils.isNumeric("12.3") = false
    3743     * StringUtils.isNumeric("-123") = false
    3744     * StringUtils.isNumeric("+123") = false
    3745     * </pre>
    3746     *
    3747     * @param cs  the CharSequence to check, may be null
    3748     * @return {@code true} if only contains digits, and is non-null
    3749     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
    3750     * @since 3.0 Changed "" to return false and not true
    3751     */
    3752    public static boolean isNumeric(final CharSequence cs) {
    3753        if (isEmpty(cs)) {
    3754            return false;
    3755        }
    3756        final int sz = cs.length();
    3757        for (int i = 0; i < sz; i++) {
    3758            if (!Character.isDigit(cs.charAt(i))) {
    3759                return false;
    3760            }
    3761        }
    3762        return true;
    3763    }
    3764
    3765    /**
    3766     * <p>Checks if the CharSequence contains only Unicode digits or space
    3767     * ({@code ' '}).
    3768     * A decimal point is not a Unicode digit and returns false.</p>
    3769     *
    3770     * <p>{@code null} will return {@code false}.
    3771     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3772     *
    3773     * <pre>
    3774     * StringUtils.isNumericSpace(null)   = false
    3775     * StringUtils.isNumericSpace("")     = true
    3776     * StringUtils.isNumericSpace("  ")   = true
    3777     * StringUtils.isNumericSpace("123")  = true
    3778     * StringUtils.isNumericSpace("12 3") = true
    3779     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
    3780     * StringUtils.isNumeric("\u0967\u0968 \u0969")  = true
    3781     * StringUtils.isNumericSpace("ab2c") = false
    3782     * StringUtils.isNumericSpace("12-3") = false
    3783     * StringUtils.isNumericSpace("12.3") = false
    3784     * </pre>
    3785     *
    3786     * @param cs  the CharSequence to check, may be null
    3787     * @return {@code true} if only contains digits or space,
    3788     *  and is non-null
    3789     * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
    3790     */
    3791    public static boolean isNumericSpace(final CharSequence cs) {
    3792        if (cs == null) {
    3793            return false;
    3794        }
    3795        final int sz = cs.length();
    3796        for (int i = 0; i < sz; i++) {
    3797            if (!Character.isDigit(cs.charAt(i)) && cs.charAt(i) != ' ') {
    3798                return false;
    3799            }
    3800        }
    3801        return true;
    3802    }
    3803
    3804    /**
    3805     * <p>Checks if the CharSequence contains only whitespace.</p>
    3806     *
    3807     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    3808     *
    3809     * <p>{@code null} will return {@code false}.
    3810     * An empty CharSequence (length()=0) will return {@code true}.</p>
    3811     *
    3812     * <pre>
    3813     * StringUtils.isWhitespace(null)   = false
    3814     * StringUtils.isWhitespace("")     = true
    3815     * StringUtils.isWhitespace("  ")   = true
    3816     * StringUtils.isWhitespace("abc")  = false
    3817     * StringUtils.isWhitespace("ab2c") = false
    3818     * StringUtils.isWhitespace("ab-c") = false
    3819     * </pre>
    3820     *
    3821     * @param cs  the CharSequence to check, may be null
    3822     * @return {@code true} if only contains whitespace, and is non-null
    3823     * @since 2.0
    3824     * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
    3825     */
    3826    public static boolean isWhitespace(final CharSequence cs) {
    3827        if (cs == null) {
    3828            return false;
    3829        }
    3830        final int sz = cs.length();
    3831        for (int i = 0; i < sz; i++) {
    3832            if (!Character.isWhitespace(cs.charAt(i))) {
    3833                return false;
    3834            }
    3835        }
    3836        return true;
    3837    }
    3838
    3839    /**
    3840     * <p>
    3841     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3842     * </p>
    3843     *
    3844     * <p>
    3845     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3846     * by empty strings.
    3847     * </p>
    3848     *
    3849     * <pre>
    3850     * StringUtils.join(null, *)               = null
    3851     * StringUtils.join([], *)                 = ""
    3852     * StringUtils.join([null], *)             = ""
    3853     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3854     * StringUtils.join([1, 2, 3], null) = "123"
    3855     * </pre>
    3856     *
    3857     * @param array
    3858     *            the array of values to join together, may be null
    3859     * @param separator
    3860     *            the separator character to use
    3861     * @return the joined String, {@code null} if null array input
    3862     * @since 3.2
    3863     */
    3864    public static String join(final byte[] array, final char separator) {
    3865        if (array == null) {
    3866            return null;
    3867        }
    3868        return join(array, separator, 0, array.length);
    3869    }
    3870
    3871    /**
    3872     * <p>
    3873     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3874     * </p>
    3875     *
    3876     * <p>
    3877     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3878     * by empty strings.
    3879     * </p>
    3880     *
    3881     * <pre>
    3882     * StringUtils.join(null, *)               = null
    3883     * StringUtils.join([], *)                 = ""
    3884     * StringUtils.join([null], *)             = ""
    3885     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3886     * StringUtils.join([1, 2, 3], null) = "123"
    3887     * </pre>
    3888     *
    3889     * @param array
    3890     *            the array of values to join together, may be null
    3891     * @param separator
    3892     *            the separator character to use
    3893     * @param startIndex
    3894     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    3895     *            array
    3896     * @param endIndex
    3897     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    3898     *            the array
    3899     * @return the joined String, {@code null} if null array input
    3900     * @since 3.2
    3901     */
    3902    public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
    3903        if (array == null) {
    3904            return null;
    3905        }
    3906        final int noOfItems = endIndex - startIndex;
    3907        if (noOfItems <= 0) {
    3908            return EMPTY;
    3909        }
    3910        final StringBuilder buf = newStringBuilder(noOfItems);
    3911        buf.append(array[startIndex]);
    3912        for (int i = startIndex + 1; i < endIndex; i++) {
    3913            buf.append(separator);
    3914            buf.append(array[i]);
    3915        }
    3916        return buf.toString();
    3917    }
    3918
    3919    /**
    3920     * <p>
    3921     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3922     * </p>
    3923     *
    3924     * <p>
    3925     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3926     * by empty strings.
    3927     * </p>
    3928     *
    3929     * <pre>
    3930     * StringUtils.join(null, *)               = null
    3931     * StringUtils.join([], *)                 = ""
    3932     * StringUtils.join([null], *)             = ""
    3933     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3934     * StringUtils.join([1, 2, 3], null) = "123"
    3935     * </pre>
    3936     *
    3937     * @param array
    3938     *            the array of values to join together, may be null
    3939     * @param separator
    3940     *            the separator character to use
    3941     * @return the joined String, {@code null} if null array input
    3942     * @since 3.2
    3943     */
    3944    public static String join(final char[] array, final char separator) {
    3945        if (array == null) {
    3946            return null;
    3947        }
    3948        return join(array, separator, 0, array.length);
    3949    }
    3950
    3951    /**
    3952     * <p>
    3953     * Joins the elements of the provided array into a single String containing the provided list of elements.
    3954     * </p>
    3955     *
    3956     * <p>
    3957     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    3958     * by empty strings.
    3959     * </p>
    3960     *
    3961     * <pre>
    3962     * StringUtils.join(null, *)               = null
    3963     * StringUtils.join([], *)                 = ""
    3964     * StringUtils.join([null], *)             = ""
    3965     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    3966     * StringUtils.join([1, 2, 3], null) = "123"
    3967     * </pre>
    3968     *
    3969     * @param array
    3970     *            the array of values to join together, may be null
    3971     * @param separator
    3972     *            the separator character to use
    3973     * @param startIndex
    3974     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    3975     *            array
    3976     * @param endIndex
    3977     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    3978     *            the array
    3979     * @return the joined String, {@code null} if null array input
    3980     * @since 3.2
    3981     */
    3982    public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
    3983        if (array == null) {
    3984            return null;
    3985        }
    3986        final int noOfItems = endIndex - startIndex;
    3987        if (noOfItems <= 0) {
    3988            return EMPTY;
    3989        }
    3990        final StringBuilder buf = newStringBuilder(noOfItems);
    3991        buf.append(array[startIndex]);
    3992        for (int i = startIndex + 1; i < endIndex; i++) {
    3993            buf.append(separator);
    3994            buf.append(array[i]);
    3995        }
    3996        return buf.toString();
    3997    }
    3998
    3999    /**
    4000     * <p>
    4001     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4002     * </p>
    4003     *
    4004     * <p>
    4005     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4006     * by empty strings.
    4007     * </p>
    4008     *
    4009     * <pre>
    4010     * StringUtils.join(null, *)               = null
    4011     * StringUtils.join([], *)                 = ""
    4012     * StringUtils.join([null], *)             = ""
    4013     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4014     * StringUtils.join([1, 2, 3], null) = "123"
    4015     * </pre>
    4016     *
    4017     * @param array
    4018     *            the array of values to join together, may be null
    4019     * @param separator
    4020     *            the separator character to use
    4021     * @return the joined String, {@code null} if null array input
    4022     * @since 3.2
    4023     */
    4024    public static String join(final double[] array, final char separator) {
    4025        if (array == null) {
    4026            return null;
    4027        }
    4028        return join(array, separator, 0, array.length);
    4029    }
    4030
    4031    /**
    4032     * <p>
    4033     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4034     * </p>
    4035     *
    4036     * <p>
    4037     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4038     * by empty strings.
    4039     * </p>
    4040     *
    4041     * <pre>
    4042     * StringUtils.join(null, *)               = null
    4043     * StringUtils.join([], *)                 = ""
    4044     * StringUtils.join([null], *)             = ""
    4045     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4046     * StringUtils.join([1, 2, 3], null) = "123"
    4047     * </pre>
    4048     *
    4049     * @param array
    4050     *            the array of values to join together, may be null
    4051     * @param separator
    4052     *            the separator character to use
    4053     * @param startIndex
    4054     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4055     *            array
    4056     * @param endIndex
    4057     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4058     *            the array
    4059     * @return the joined String, {@code null} if null array input
    4060     * @since 3.2
    4061     */
    4062    public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
    4063        if (array == null) {
    4064            return null;
    4065        }
    4066        final int noOfItems = endIndex - startIndex;
    4067        if (noOfItems <= 0) {
    4068            return EMPTY;
    4069        }
    4070        final StringBuilder buf = newStringBuilder(noOfItems);
    4071        buf.append(array[startIndex]);
    4072        for (int i = startIndex + 1; i < endIndex; i++) {
    4073            buf.append(separator);
    4074            buf.append(array[i]);
    4075        }
    4076        return buf.toString();
    4077    }
    4078
    4079    /**
    4080     * <p>
    4081     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4082     * </p>
    4083     *
    4084     * <p>
    4085     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4086     * by empty strings.
    4087     * </p>
    4088     *
    4089     * <pre>
    4090     * StringUtils.join(null, *)               = null
    4091     * StringUtils.join([], *)                 = ""
    4092     * StringUtils.join([null], *)             = ""
    4093     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4094     * StringUtils.join([1, 2, 3], null) = "123"
    4095     * </pre>
    4096     *
    4097     * @param array
    4098     *            the array of values to join together, may be null
    4099     * @param separator
    4100     *            the separator character to use
    4101     * @return the joined String, {@code null} if null array input
    4102     * @since 3.2
    4103     */
    4104    public static String join(final float[] array, final char separator) {
    4105        if (array == null) {
    4106            return null;
    4107        }
    4108        return join(array, separator, 0, array.length);
    4109    }
    4110
    4111    /**
    4112     * <p>
    4113     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4114     * </p>
    4115     *
    4116     * <p>
    4117     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4118     * by empty strings.
    4119     * </p>
    4120     *
    4121     * <pre>
    4122     * StringUtils.join(null, *)               = null
    4123     * StringUtils.join([], *)                 = ""
    4124     * StringUtils.join([null], *)             = ""
    4125     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4126     * StringUtils.join([1, 2, 3], null) = "123"
    4127     * </pre>
    4128     *
    4129     * @param array
    4130     *            the array of values to join together, may be null
    4131     * @param separator
    4132     *            the separator character to use
    4133     * @param startIndex
    4134     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4135     *            array
    4136     * @param endIndex
    4137     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4138     *            the array
    4139     * @return the joined String, {@code null} if null array input
    4140     * @since 3.2
    4141     */
    4142    public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
    4143        if (array == null) {
    4144            return null;
    4145        }
    4146        final int noOfItems = endIndex - startIndex;
    4147        if (noOfItems <= 0) {
    4148            return EMPTY;
    4149        }
    4150        final StringBuilder buf = newStringBuilder(noOfItems);
    4151        buf.append(array[startIndex]);
    4152        for (int i = startIndex + 1; i < endIndex; i++) {
    4153            buf.append(separator);
    4154            buf.append(array[i]);
    4155        }
    4156        return buf.toString();
    4157    }
    4158
    4159    /**
    4160     * <p>
    4161     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4162     * </p>
    4163     *
    4164     * <p>
    4165     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4166     * by empty strings.
    4167     * </p>
    4168     *
    4169     * <pre>
    4170     * StringUtils.join(null, *)               = null
    4171     * StringUtils.join([], *)                 = ""
    4172     * StringUtils.join([null], *)             = ""
    4173     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4174     * StringUtils.join([1, 2, 3], null) = "123"
    4175     * </pre>
    4176     *
    4177     * @param array
    4178     *            the array of values to join together, may be null
    4179     * @param separator
    4180     *            the separator character to use
    4181     * @return the joined String, {@code null} if null array input
    4182     * @since 3.2
    4183     */
    4184    public static String join(final int[] array, final char separator) {
    4185        if (array == null) {
    4186            return null;
    4187        }
    4188        return join(array, separator, 0, array.length);
    4189    }
    4190
    4191    /**
    4192     * <p>
    4193     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4194     * </p>
    4195     *
    4196     * <p>
    4197     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4198     * by empty strings.
    4199     * </p>
    4200     *
    4201     * <pre>
    4202     * StringUtils.join(null, *)               = null
    4203     * StringUtils.join([], *)                 = ""
    4204     * StringUtils.join([null], *)             = ""
    4205     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4206     * StringUtils.join([1, 2, 3], null) = "123"
    4207     * </pre>
    4208     *
    4209     * @param array
    4210     *            the array of values to join together, may be null
    4211     * @param separator
    4212     *            the separator character to use
    4213     * @param startIndex
    4214     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4215     *            array
    4216     * @param endIndex
    4217     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4218     *            the array
    4219     * @return the joined String, {@code null} if null array input
    4220     * @since 3.2
    4221     */
    4222    public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
    4223        if (array == null) {
    4224            return null;
    4225        }
    4226        final int noOfItems = endIndex - startIndex;
    4227        if (noOfItems <= 0) {
    4228            return EMPTY;
    4229        }
    4230        final StringBuilder buf = newStringBuilder(noOfItems);
    4231        buf.append(array[startIndex]);
    4232        for (int i = startIndex + 1; i < endIndex; i++) {
    4233            buf.append(separator);
    4234            buf.append(array[i]);
    4235        }
    4236        return buf.toString();
    4237    }
    4238
    4239    /**
    4240     * <p>Joins the elements of the provided {@code Iterable} into
    4241     * a single String containing the provided elements.</p>
    4242     *
    4243     * <p>No delimiter is added before or after the list. Null objects or empty
    4244     * strings within the iteration are represented by empty strings.</p>
    4245     *
    4246     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    4247     *
    4248     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    4249     * @param separator  the separator character to use
    4250     * @return the joined String, {@code null} if null iterator input
    4251     * @since 2.3
    4252     */
    4253    public static String join(final Iterable<?> iterable, final char separator) {
    4254        if (iterable == null) {
    4255            return null;
    4256        }
    4257        return join(iterable.iterator(), separator);
    4258    }
    4259
    4260    /**
    4261     * <p>Joins the elements of the provided {@code Iterable} into
    4262     * a single String containing the provided elements.</p>
    4263     *
    4264     * <p>No delimiter is added before or after the list.
    4265     * A {@code null} separator is the same as an empty String ("").</p>
    4266     *
    4267     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    4268     *
    4269     * @param iterable  the {@code Iterable} providing the values to join together, may be null
    4270     * @param separator  the separator character to use, null treated as ""
    4271     * @return the joined String, {@code null} if null iterator input
    4272     * @since 2.3
    4273     */
    4274    public static String join(final Iterable<?> iterable, final String separator) {
    4275        if (iterable == null) {
    4276            return null;
    4277        }
    4278        return join(iterable.iterator(), separator);
    4279    }
    4280
    4281    /**
    4282     * <p>Joins the elements of the provided {@code Iterator} into
    4283     * a single String containing the provided elements.</p>
    4284     *
    4285     * <p>No delimiter is added before or after the list. Null objects or empty
    4286     * strings within the iteration are represented by empty strings.</p>
    4287     *
    4288     * <p>See the examples here: {@link #join(Object[],char)}. </p>
    4289     *
    4290     * @param iterator  the {@code Iterator} of values to join together, may be null
    4291     * @param separator  the separator character to use
    4292     * @return the joined String, {@code null} if null iterator input
    4293     * @since 2.0
    4294     */
    4295    public static String join(final Iterator<?> iterator, final char separator) {
    4296
    4297        // handle null, zero and one elements before building a buffer
    4298        if (iterator == null) {
    4299            return null;
    4300        }
    4301        if (!iterator.hasNext()) {
    4302            return EMPTY;
    4303        }
    4304        final Object first = iterator.next();
    4305        if (!iterator.hasNext()) {
    4306            return Objects.toString(first, EMPTY);
    4307        }
    4308
    4309        // two or more elements
    4310        final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
    4311        if (first != null) {
    4312            buf.append(first);
    4313        }
    4314
    4315        while (iterator.hasNext()) {
    4316            buf.append(separator);
    4317            final Object obj = iterator.next();
    4318            if (obj != null) {
    4319                buf.append(obj);
    4320            }
    4321        }
    4322
    4323        return buf.toString();
    4324    }
    4325
    4326    /**
    4327     * <p>Joins the elements of the provided {@code Iterator} into
    4328     * a single String containing the provided elements.</p>
    4329     *
    4330     * <p>No delimiter is added before or after the list.
    4331     * A {@code null} separator is the same as an empty String ("").</p>
    4332     *
    4333     * <p>See the examples here: {@link #join(Object[],String)}. </p>
    4334     *
    4335     * @param iterator  the {@code Iterator} of values to join together, may be null
    4336     * @param separator  the separator character to use, null treated as ""
    4337     * @return the joined String, {@code null} if null iterator input
    4338     */
    4339    public static String join(final Iterator<?> iterator, final String separator) {
    4340
    4341        // handle null, zero and one elements before building a buffer
    4342        if (iterator == null) {
    4343            return null;
    4344        }
    4345        if (!iterator.hasNext()) {
    4346            return EMPTY;
    4347        }
    4348        final Object first = iterator.next();
    4349        if (!iterator.hasNext()) {
    4350            return Objects.toString(first, "");
    4351        }
    4352
    4353        // two or more elements
    4354        final StringBuilder buf = new StringBuilder(STRING_BUILDER_SIZE); // Java default is 16, probably too small
    4355        if (first != null) {
    4356            buf.append(first);
    4357        }
    4358
    4359        while (iterator.hasNext()) {
    4360            if (separator != null) {
    4361                buf.append(separator);
    4362            }
    4363            final Object obj = iterator.next();
    4364            if (obj != null) {
    4365                buf.append(obj);
    4366            }
    4367        }
    4368        return buf.toString();
    4369    }
    4370
    4371    /**
    4372     * <p>Joins the elements of the provided {@code List} into a single String
    4373     * containing the provided list of elements.</p>
    4374     *
    4375     * <p>No delimiter is added before or after the list.
    4376     * Null objects or empty strings within the array are represented by
    4377     * empty strings.</p>
    4378     *
    4379     * <pre>
    4380     * StringUtils.join(null, *)               = null
    4381     * StringUtils.join([], *)                 = ""
    4382     * StringUtils.join([null], *)             = ""
    4383     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4384     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4385     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4386     * </pre>
    4387     *
    4388     * @param list  the {@code List} of values to join together, may be null
    4389     * @param separator  the separator character to use
    4390     * @param startIndex the first index to start joining from.  It is
    4391     * an error to pass in a start index past the end of the list
    4392     * @param endIndex the index to stop joining from (exclusive). It is
    4393     * an error to pass in an end index past the end of the list
    4394     * @return the joined String, {@code null} if null list input
    4395     * @since 3.8
    4396     */
    4397    public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
    4398        if (list == null) {
    4399            return null;
    4400        }
    4401        final int noOfItems = endIndex - startIndex;
    4402        if (noOfItems <= 0) {
    4403            return EMPTY;
    4404        }
    4405        final List<?> subList = list.subList(startIndex, endIndex);
    4406        return join(subList.iterator(), separator);
    4407    }
    4408
    4409    /**
    4410     * <p>Joins the elements of the provided {@code List} into a single String
    4411     * containing the provided list of elements.</p>
    4412     *
    4413     * <p>No delimiter is added before or after the list.
    4414     * Null objects or empty strings within the array are represented by
    4415     * empty strings.</p>
    4416     *
    4417     * <pre>
    4418     * StringUtils.join(null, *)               = null
    4419     * StringUtils.join([], *)                 = ""
    4420     * StringUtils.join([null], *)             = ""
    4421     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4422     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4423     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4424     * </pre>
    4425     *
    4426     * @param list  the {@code List} of values to join together, may be null
    4427     * @param separator  the separator character to use
    4428     * @param startIndex the first index to start joining from.  It is
    4429     * an error to pass in a start index past the end of the list
    4430     * @param endIndex the index to stop joining from (exclusive). It is
    4431     * an error to pass in an end index past the end of the list
    4432     * @return the joined String, {@code null} if null list input
    4433     * @since 3.8
    4434     */
    4435    public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
    4436        if (list == null) {
    4437            return null;
    4438        }
    4439        final int noOfItems = endIndex - startIndex;
    4440        if (noOfItems <= 0) {
    4441            return EMPTY;
    4442        }
    4443        final List<?> subList = list.subList(startIndex, endIndex);
    4444        return join(subList.iterator(), separator);
    4445    }
    4446
    4447
    4448    /**
    4449     * <p>
    4450     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4451     * </p>
    4452     *
    4453     * <p>
    4454     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4455     * by empty strings.
    4456     * </p>
    4457     *
    4458     * <pre>
    4459     * StringUtils.join(null, *)               = null
    4460     * StringUtils.join([], *)                 = ""
    4461     * StringUtils.join([null], *)             = ""
    4462     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4463     * StringUtils.join([1, 2, 3], null) = "123"
    4464     * </pre>
    4465     *
    4466     * @param array
    4467     *            the array of values to join together, may be null
    4468     * @param separator
    4469     *            the separator character to use
    4470     * @return the joined String, {@code null} if null array input
    4471     * @since 3.2
    4472     */
    4473    public static String join(final long[] array, final char separator) {
    4474        if (array == null) {
    4475            return null;
    4476        }
    4477        return join(array, separator, 0, array.length);
    4478    }
    4479
    4480    /**
    4481     * <p>
    4482     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4483     * </p>
    4484     *
    4485     * <p>
    4486     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4487     * by empty strings.
    4488     * </p>
    4489     *
    4490     * <pre>
    4491     * StringUtils.join(null, *)               = null
    4492     * StringUtils.join([], *)                 = ""
    4493     * StringUtils.join([null], *)             = ""
    4494     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4495     * StringUtils.join([1, 2, 3], null) = "123"
    4496     * </pre>
    4497     *
    4498     * @param array
    4499     *            the array of values to join together, may be null
    4500     * @param separator
    4501     *            the separator character to use
    4502     * @param startIndex
    4503     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4504     *            array
    4505     * @param endIndex
    4506     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4507     *            the array
    4508     * @return the joined String, {@code null} if null array input
    4509     * @since 3.2
    4510     */
    4511    public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
    4512        if (array == null) {
    4513            return null;
    4514        }
    4515        final int noOfItems = endIndex - startIndex;
    4516        if (noOfItems <= 0) {
    4517            return EMPTY;
    4518        }
    4519        final StringBuilder buf = newStringBuilder(noOfItems);
    4520        buf.append(array[startIndex]);
    4521        for (int i = startIndex + 1; i < endIndex; i++) {
    4522            buf.append(separator);
    4523            buf.append(array[i]);
    4524        }
    4525        return buf.toString();
    4526    }
    4527
    4528    /**
    4529     * <p>Joins the elements of the provided array into a single String
    4530     * containing the provided list of elements.</p>
    4531     *
    4532     * <p>No delimiter is added before or after the list.
    4533     * Null objects or empty strings within the array are represented by
    4534     * empty strings.</p>
    4535     *
    4536     * <pre>
    4537     * StringUtils.join(null, *)               = null
    4538     * StringUtils.join([], *)                 = ""
    4539     * StringUtils.join([null], *)             = ""
    4540     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4541     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4542     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4543     * </pre>
    4544     *
    4545     * @param array  the array of values to join together, may be null
    4546     * @param separator  the separator character to use
    4547     * @return the joined String, {@code null} if null array input
    4548     * @since 2.0
    4549     */
    4550    public static String join(final Object[] array, final char separator) {
    4551        if (array == null) {
    4552            return null;
    4553        }
    4554        return join(array, separator, 0, array.length);
    4555    }
    4556
    4557    /**
    4558     * <p>Joins the elements of the provided array into a single String
    4559     * containing the provided list of elements.</p>
    4560     *
    4561     * <p>No delimiter is added before or after the list.
    4562     * Null objects or empty strings within the array are represented by
    4563     * empty strings.</p>
    4564     *
    4565     * <pre>
    4566     * StringUtils.join(null, *)               = null
    4567     * StringUtils.join([], *)                 = ""
    4568     * StringUtils.join([null], *)             = ""
    4569     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
    4570     * StringUtils.join(["a", "b", "c"], null) = "abc"
    4571     * StringUtils.join([null, "", "a"], ';')  = ";;a"
    4572     * </pre>
    4573     *
    4574     * @param array  the array of values to join together, may be null
    4575     * @param separator  the separator character to use
    4576     * @param startIndex the first index to start joining from.  It is
    4577     * an error to pass in a start index past the end of the array
    4578     * @param endIndex the index to stop joining from (exclusive). It is
    4579     * an error to pass in an end index past the end of the array
    4580     * @return the joined String, {@code null} if null array input
    4581     * @since 2.0
    4582     */
    4583    public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
    4584        if (array == null) {
    4585            return null;
    4586        }
    4587        final int noOfItems = endIndex - startIndex;
    4588        if (noOfItems <= 0) {
    4589            return EMPTY;
    4590        }
    4591        final StringBuilder buf = newStringBuilder(noOfItems);
    4592        if (array[startIndex] != null) {
    4593            buf.append(array[startIndex]);
    4594        }
    4595        for (int i = startIndex + 1; i < endIndex; i++) {
    4596            buf.append(separator);
    4597            if (array[i] != null) {
    4598                buf.append(array[i]);
    4599            }
    4600        }
    4601        return buf.toString();
    4602    }
    4603
    4604    /**
    4605     * <p>Joins the elements of the provided array into a single String
    4606     * containing the provided list of elements.</p>
    4607     *
    4608     * <p>No delimiter is added before or after the list.
    4609     * A {@code null} separator is the same as an empty String ("").
    4610     * Null objects or empty strings within the array are represented by
    4611     * empty strings.</p>
    4612     *
    4613     * <pre>
    4614     * StringUtils.join(null, *)                = null
    4615     * StringUtils.join([], *)                  = ""
    4616     * StringUtils.join([null], *)              = ""
    4617     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
    4618     * StringUtils.join(["a", "b", "c"], null)  = "abc"
    4619     * StringUtils.join(["a", "b", "c"], "")    = "abc"
    4620     * StringUtils.join([null, "", "a"], ',')   = ",,a"
    4621     * </pre>
    4622     *
    4623     * @param array  the array of values to join together, may be null
    4624     * @param separator  the separator character to use, null treated as ""
    4625     * @return the joined String, {@code null} if null array input
    4626     */
    4627    public static String join(final Object[] array, final String separator) {
    4628        if (array == null) {
    4629            return null;
    4630        }
    4631        return join(array, separator, 0, array.length);
    4632    }
    4633
    4634    /**
    4635     * <p>Joins the elements of the provided array into a single String
    4636     * containing the provided list of elements.</p>
    4637     *
    4638     * <p>No delimiter is added before or after the list.
    4639     * A {@code null} separator is the same as an empty String ("").
    4640     * Null objects or empty strings within the array are represented by
    4641     * empty strings.</p>
    4642     *
    4643     * <pre>
    4644     * StringUtils.join(null, *, *, *)                = null
    4645     * StringUtils.join([], *, *, *)                  = ""
    4646     * StringUtils.join([null], *, *, *)              = ""
    4647     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
    4648     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
    4649     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
    4650     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
    4651     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
    4652     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
    4653     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
    4654     * </pre>
    4655     *
    4656     * @param array  the array of values to join together, may be null
    4657     * @param separator  the separator character to use, null treated as ""
    4658     * @param startIndex the first index to start joining from.
    4659     * @param endIndex the index to stop joining from (exclusive).
    4660     * @return the joined String, {@code null} if null array input; or the empty string
    4661     * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
    4662     * {@code endIndex - startIndex}
    4663     * @throws ArrayIndexOutOfBoundsException ife<br>
    4664     * {@code startIndex < 0} or <br>
    4665     * {@code startIndex >= array.length()} or <br>
    4666     * {@code endIndex < 0} or <br>
    4667     * {@code endIndex > array.length()}
    4668     */
    4669    public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
    4670        if (array == null) {
    4671            return null;
    4672        }
    4673        if (separator == null) {
    4674            separator = EMPTY;
    4675        }
    4676
    4677        // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    4678        //           (Assuming that all Strings are roughly equally long)
    4679        final int noOfItems = endIndex - startIndex;
    4680        if (noOfItems <= 0) {
    4681            return EMPTY;
    4682        }
    4683
    4684        final StringBuilder buf = newStringBuilder(noOfItems);
    4685
    4686        if (array[startIndex] != null) {
    4687            buf.append(array[startIndex]);
    4688        }
    4689
    4690        for (int i = startIndex + 1; i < endIndex; i++) {
    4691            buf.append(separator);
    4692
    4693            if (array[i] != null) {
    4694                buf.append(array[i]);
    4695            }
    4696        }
    4697        return buf.toString();
    4698    }
    4699
    4700    /**
    4701     * <p>
    4702     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4703     * </p>
    4704     *
    4705     * <p>
    4706     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4707     * by empty strings.
    4708     * </p>
    4709     *
    4710     * <pre>
    4711     * StringUtils.join(null, *)               = null
    4712     * StringUtils.join([], *)                 = ""
    4713     * StringUtils.join([null], *)             = ""
    4714     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4715     * StringUtils.join([1, 2, 3], null) = "123"
    4716     * </pre>
    4717     *
    4718     * @param array
    4719     *            the array of values to join together, may be null
    4720     * @param separator
    4721     *            the separator character to use
    4722     * @return the joined String, {@code null} if null array input
    4723     * @since 3.2
    4724     */
    4725    public static String join(final short[] array, final char separator) {
    4726        if (array == null) {
    4727            return null;
    4728        }
    4729        return join(array, separator, 0, array.length);
    4730    }
    4731
    4732    /**
    4733     * <p>
    4734     * Joins the elements of the provided array into a single String containing the provided list of elements.
    4735     * </p>
    4736     *
    4737     * <p>
    4738     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
    4739     * by empty strings.
    4740     * </p>
    4741     *
    4742     * <pre>
    4743     * StringUtils.join(null, *)               = null
    4744     * StringUtils.join([], *)                 = ""
    4745     * StringUtils.join([null], *)             = ""
    4746     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
    4747     * StringUtils.join([1, 2, 3], null) = "123"
    4748     * </pre>
    4749     *
    4750     * @param array
    4751     *            the array of values to join together, may be null
    4752     * @param separator
    4753     *            the separator character to use
    4754     * @param startIndex
    4755     *            the first index to start joining from. It is an error to pass in a start index past the end of the
    4756     *            array
    4757     * @param endIndex
    4758     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
    4759     *            the array
    4760     * @return the joined String, {@code null} if null array input
    4761     * @since 3.2
    4762     */
    4763    public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
    4764        if (array == null) {
    4765            return null;
    4766        }
    4767        final int noOfItems = endIndex - startIndex;
    4768        if (noOfItems <= 0) {
    4769            return EMPTY;
    4770        }
    4771        final StringBuilder buf = newStringBuilder(noOfItems);
    4772        buf.append(array[startIndex]);
    4773        for (int i = startIndex + 1; i < endIndex; i++) {
    4774            buf.append(separator);
    4775            buf.append(array[i]);
    4776        }
    4777        return buf.toString();
    4778    }
    4779
    4780
    4781    // Joining
    4782    //-----------------------------------------------------------------------
    4783    /**
    4784     * <p>Joins the elements of the provided array into a single String
    4785     * containing the provided list of elements.</p>
    4786     *
    4787     * <p>No separator is added to the joined String.
    4788     * Null objects or empty strings within the array are represented by
    4789     * empty strings.</p>
    4790     *
    4791     * <pre>
    4792     * StringUtils.join(null)            = null
    4793     * StringUtils.join([])              = ""
    4794     * StringUtils.join([null])          = ""
    4795     * StringUtils.join(["a", "b", "c"]) = "abc"
    4796     * StringUtils.join([null, "", "a"]) = "a"
    4797     * </pre>
    4798     *
    4799     * @param <T> the specific type of values to join together
    4800     * @param elements  the values to join together, may be null
    4801     * @return the joined String, {@code null} if null array input
    4802     * @since 2.0
    4803     * @since 3.0 Changed signature to use varargs
    4804     */
    4805    @SafeVarargs
    4806    public static <T> String join(final T... elements) {
    4807        return join(elements, null);
    4808    }
    4809
    4810    /**
    4811     * <p>Joins the elements of the provided varargs into a
    4812     * single String containing the provided elements.</p>
    4813     *
    4814     * <p>No delimiter is added before or after the list.
    4815     * {@code null} elements and separator are treated as empty Strings ("").</p>
    4816     *
    4817     * <pre>
    4818     * StringUtils.joinWith(",", {"a", "b"})        = "a,b"
    4819     * StringUtils.joinWith(",", {"a", "b",""})     = "a,b,"
    4820     * StringUtils.joinWith(",", {"a", null, "b"})  = "a,,b"
    4821     * StringUtils.joinWith(null, {"a", "b"})       = "ab"
    4822     * </pre>
    4823     *
    4824     * @param separator the separator character to use, null treated as ""
    4825     * @param objects the varargs providing the values to join together. {@code null} elements are treated as ""
    4826     * @return the joined String.
    4827     * @throws java.lang.IllegalArgumentException if a null varargs is provided
    4828     * @since 3.5
    4829     */
    4830    public static String joinWith(final String separator, final Object... objects) {
    4831        if (objects == null) {
    4832            throw new IllegalArgumentException("Object varargs must not be null");
    4833        }
    4834
    4835        final String sanitizedSeparator = defaultString(separator);
    4836
    4837        final StringBuilder result = new StringBuilder();
    4838
    4839        final Iterator<Object> iterator = Arrays.asList(objects).iterator();
    4840        while (iterator.hasNext()) {
    4841            final String value = Objects.toString(iterator.next(), "");
    4842            result.append(value);
    4843
    4844            if (iterator.hasNext()) {
    4845                result.append(sanitizedSeparator);
    4846            }
    4847        }
    4848
    4849        return result.toString();
    4850    }
    4851
    4852    /**
    4853     * <p>Finds the last index within a CharSequence, handling {@code null}.
    4854     * This method uses {@link String#lastIndexOf(String)} if possible.</p>
    4855     *
    4856     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    4857     *
    4858     * <pre>
    4859     * StringUtils.lastIndexOf(null, *)          = -1
    4860     * StringUtils.lastIndexOf(*, null)          = -1
    4861     * StringUtils.lastIndexOf("", "")           = 0
    4862     * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
    4863     * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
    4864     * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
    4865     * StringUtils.lastIndexOf("aabaabaa", "")   = 8
    4866     * </pre>
    4867     *
    4868     * @param seq  the CharSequence to check, may be null
    4869     * @param searchSeq  the CharSequence to find, may be null
    4870     * @return the last index of the search String,
    4871     *  -1 if no match or {@code null} string input
    4872     * @since 2.0
    4873     * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
    4874     */
    4875    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
    4876        if (seq == null || searchSeq == null) {
    4877            return INDEX_NOT_FOUND;
    4878        }
    4879        return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());
    4880    }
    4881
    4882    /**
    4883     * <p>Finds the last index within a CharSequence, handling {@code null}.
    4884     * This method uses {@link String#lastIndexOf(String, int)} if possible.</p>
    4885     *
    4886     * <p>A {@code null} CharSequence will return {@code -1}.
    4887     * A negative start position returns {@code -1}.
    4888     * An empty ("") search CharSequence always matches unless the start position is negative.
    4889     * A start position greater than the string length searches the whole string.
    4890     * The search starts at the startPos and works backwards; matches starting after the start
    4891     * position are ignored.
    4892     * </p>
    4893     *
    4894     * <pre>
    4895     * StringUtils.lastIndexOf(null, *, *)          = -1
    4896     * StringUtils.lastIndexOf(*, null, *)          = -1
    4897     * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
    4898     * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
    4899     * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
    4900     * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
    4901     * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
    4902     * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
    4903     * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
    4904     * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1
    4905     * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2
    4906     * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2
    4907     * </pre>
    4908     *
    4909     * @param seq  the CharSequence to check, may be null
    4910     * @param searchSeq  the CharSequence to find, may be null
    4911     * @param startPos  the start position, negative treated as zero
    4912     * @return the last index of the search CharSequence (always &le; startPos),
    4913     *  -1 if no match or {@code null} string input
    4914     * @since 2.0
    4915     * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
    4916     */
    4917    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
    4918        if (seq == null || searchSeq == null) {
    4919            return INDEX_NOT_FOUND;
    4920        }
    4921        return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);
    4922    }
    4923
    4924    // LastIndexOf
    4925    //-----------------------------------------------------------------------
    4926    /**
    4927     * Returns the index within {@code seq} of the last occurrence of
    4928     * the specified character. For values of {@code searchChar} in the
    4929     * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
    4930     * units) returned is the largest value <i>k</i> such that:
    4931     * <blockquote><pre>
    4932     * this.charAt(<i>k</i>) == searchChar
    4933     * </pre></blockquote>
    4934     * is true. For other values of {@code searchChar}, it is the
    4935     * largest value <i>k</i> such that:
    4936     * <blockquote><pre>
    4937     * this.codePointAt(<i>k</i>) == searchChar
    4938     * </pre></blockquote>
    4939     * is true.  In either case, if no such character occurs in this
    4940     * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
    4941     * {@code CharSequence} will return {@code -1}. The
    4942     * {@code seq} {@code CharSequence} object is searched backwards
    4943     * starting at the last character.
    4944     *
    4945     * <pre>
    4946     * StringUtils.lastIndexOf(null, *)         = -1
    4947     * StringUtils.lastIndexOf("", *)           = -1
    4948     * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
    4949     * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
    4950     * </pre>
    4951     *
    4952     * @param seq  the {@code CharSequence} to check, may be null
    4953     * @param searchChar  the character to find
    4954     * @return the last index of the search character,
    4955     *  -1 if no match or {@code null} string input
    4956     * @since 2.0
    4957     * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
    4958     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@code String}
    4959     */
    4960    public static int lastIndexOf(final CharSequence seq, final int searchChar) {
    4961        if (isEmpty(seq)) {
    4962            return INDEX_NOT_FOUND;
    4963        }
    4964        return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
    4965    }
    4966
    4967    /**
    4968     * Returns the index within {@code seq} of the last occurrence of
    4969     * the specified character, searching backward starting at the
    4970     * specified index. For values of {@code searchChar} in the range
    4971     * from 0 to 0xFFFF (inclusive), the index returned is the largest
    4972     * value <i>k</i> such that:
    4973     * <blockquote><pre>
    4974     * (this.charAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &lt;= startPos)
    4975     * </pre></blockquote>
    4976     * is true. For other values of {@code searchChar}, it is the
    4977     * largest value <i>k</i> such that:
    4978     * <blockquote><pre>
    4979     * (this.codePointAt(<i>k</i>) == searchChar) &amp;&amp; (<i>k</i> &lt;= startPos)
    4980     * </pre></blockquote>
    4981     * is true. In either case, if no such character occurs in {@code seq}
    4982     * at or before position {@code startPos}, then
    4983     * {@code -1} is returned. Furthermore, a {@code null} or empty ("")
    4984     * {@code CharSequence} will return {@code -1}. A start position greater
    4985     * than the string length searches the whole string.
    4986     * The search starts at the {@code startPos} and works backwards;
    4987     * matches starting after the start position are ignored.
    4988     *
    4989     * <p>All indices are specified in {@code char} values
    4990     * (Unicode code units).
    4991     *
    4992     * <pre>
    4993     * StringUtils.lastIndexOf(null, *, *)          = -1
    4994     * StringUtils.lastIndexOf("", *,  *)           = -1
    4995     * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
    4996     * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
    4997     * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
    4998     * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
    4999     * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
    5000     * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
    5001     * </pre>
    5002     *
    5003     * @param seq  the CharSequence to check, may be null
    5004     * @param searchChar  the character to find
    5005     * @param startPos  the start position
    5006     * @return the last index of the search character (always &le; startPos),
    5007     *  -1 if no match or {@code null} string input
    5008     * @since 2.0
    5009     * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
    5010     */
    5011    public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
    5012        if (isEmpty(seq)) {
    5013            return INDEX_NOT_FOUND;
    5014        }
    5015        return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
    5016    }
    5017
    5018    /**
    5019     * <p>Find the latest index of any substring in a set of potential substrings.</p>
    5020     *
    5021     * <p>A {@code null} CharSequence will return {@code -1}.
    5022     * A {@code null} search array will return {@code -1}.
    5023     * A {@code null} or zero length search array entry will be ignored,
    5024     * but a search array containing "" will return the length of {@code str}
    5025     * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p>
    5026     *
    5027     * <pre>
    5028     * StringUtils.lastIndexOfAny(null, *)                    = -1
    5029     * StringUtils.lastIndexOfAny(*, null)                    = -1
    5030     * StringUtils.lastIndexOfAny(*, [])                      = -1
    5031     * StringUtils.lastIndexOfAny(*, [null])                  = -1
    5032     * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
    5033     * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
    5034     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
    5035     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
    5036     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""])   = 10
    5037     * </pre>
    5038     *
    5039     * @param str  the CharSequence to check, may be null
    5040     * @param searchStrs  the CharSequences to search for, may be null
    5041     * @return the last index of any of the CharSequences, -1 if no match
    5042     * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
    5043     */
    5044    public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
    5045        if (str == null || searchStrs == null) {
    5046            return INDEX_NOT_FOUND;
    5047        }
    5048        int ret = INDEX_NOT_FOUND;
    5049        int tmp = 0;
    5050        for (final CharSequence search : searchStrs) {
    5051            if (search == null) {
    5052                continue;
    5053            }
    5054            tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
    5055            if (tmp > ret) {
    5056                ret = tmp;
    5057            }
    5058        }
    5059        return ret;
    5060    }
    5061
    5062    /**
    5063     * <p>Case in-sensitive find of the last index within a CharSequence.</p>
    5064     *
    5065     * <p>A {@code null} CharSequence will return {@code -1}.
    5066     * A negative start position returns {@code -1}.
    5067     * An empty ("") search CharSequence always matches unless the start position is negative.
    5068     * A start position greater than the string length searches the whole string.</p>
    5069     *
    5070     * <pre>
    5071     * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
    5072     * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
    5073     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
    5074     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
    5075     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
    5076     * </pre>
    5077     *
    5078     * @param str  the CharSequence to check, may be null
    5079     * @param searchStr  the CharSequence to find, may be null
    5080     * @return the first index of the search CharSequence,
    5081     *  -1 if no match or {@code null} string input
    5082     * @since 2.5
    5083     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
    5084     */
    5085    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
    5086        if (str == null || searchStr == null) {
    5087            return INDEX_NOT_FOUND;
    5088        }
    5089        return lastIndexOfIgnoreCase(str, searchStr, str.length());
    5090    }
    5091
    5092    /**
    5093     * <p>Case in-sensitive find of the last index within a CharSequence
    5094     * from the specified position.</p>
    5095     *
    5096     * <p>A {@code null} CharSequence will return {@code -1}.
    5097     * A negative start position returns {@code -1}.
    5098     * An empty ("") search CharSequence always matches unless the start position is negative.
    5099     * A start position greater than the string length searches the whole string.
    5100     * The search starts at the startPos and works backwards; matches starting after the start
    5101     * position are ignored.
    5102     * </p>
    5103     *
    5104     * <pre>
    5105     * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
    5106     * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
    5107     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
    5108     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
    5109     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
    5110     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
    5111     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
    5112     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
    5113     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
    5114     * </pre>
    5115     *
    5116     * @param str  the CharSequence to check, may be null
    5117     * @param searchStr  the CharSequence to find, may be null
    5118     * @param startPos  the start position
    5119     * @return the last index of the search CharSequence (always &le; startPos),
    5120     *  -1 if no match or {@code null} input
    5121     * @since 2.5
    5122     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
    5123     */
    5124    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
    5125        if (str == null || searchStr == null) {
    5126            return INDEX_NOT_FOUND;
    5127        }
    5128        if (startPos > str.length() - searchStr.length()) {
    5129            startPos = str.length() - searchStr.length();
    5130        }
    5131        if (startPos < 0) {
    5132            return INDEX_NOT_FOUND;
    5133        }
    5134        if (searchStr.length() == 0) {
    5135            return startPos;
    5136        }
    5137
    5138        for (int i = startPos; i >= 0; i--) {
    5139            if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
    5140                return i;
    5141            }
    5142        }
    5143        return INDEX_NOT_FOUND;
    5144    }
    5145
    5146    /**
    5147     * <p>Finds the n-th last index within a String, handling {@code null}.
    5148     * This method uses {@link String#lastIndexOf(String)}.</p>
    5149     *
    5150     * <p>A {@code null} String will return {@code -1}.</p>
    5151     *
    5152     * <pre>
    5153     * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
    5154     * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
    5155     * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
    5156     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
    5157     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
    5158     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
    5159     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
    5160     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
    5161     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
    5162     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
    5163     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
    5164     * </pre>
    5165     *
    5166     * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p>
    5167     *
    5168     * <pre>
    5169     *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
    5170     * </pre>
    5171     *
    5172     * @param str  the CharSequence to check, may be null
    5173     * @param searchStr  the CharSequence to find, may be null
    5174     * @param ordinal  the n-th last {@code searchStr} to find
    5175     * @return the n-th last index of the search CharSequence,
    5176     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5177     * @since 2.5
    5178     * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
    5179     */
    5180    public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
    5181        return ordinalIndexOf(str, searchStr, ordinal, true);
    5182    }
    5183
    5184    // Left/Right/Mid
    5185    //-----------------------------------------------------------------------
    5186    /**
    5187     * <p>Gets the leftmost {@code len} characters of a String.</p>
    5188     *
    5189     * <p>If {@code len} characters are not available, or the
    5190     * String is {@code null}, the String will be returned without
    5191     * an exception. An empty String is returned if len is negative.</p>
    5192     *
    5193     * <pre>
    5194     * StringUtils.left(null, *)    = null
    5195     * StringUtils.left(*, -ve)     = ""
    5196     * StringUtils.left("", *)      = ""
    5197     * StringUtils.left("abc", 0)   = ""
    5198     * StringUtils.left("abc", 2)   = "ab"
    5199     * StringUtils.left("abc", 4)   = "abc"
    5200     * </pre>
    5201     *
    5202     * @param str  the String to get the leftmost characters from, may be null
    5203     * @param len  the length of the required String
    5204     * @return the leftmost characters, {@code null} if null String input
    5205     */
    5206    public static String left(final String str, final int len) {
    5207        if (str == null) {
    5208            return null;
    5209        }
    5210        if (len < 0) {
    5211            return EMPTY;
    5212        }
    5213        if (str.length() <= len) {
    5214            return str;
    5215        }
    5216        return str.substring(0, len);
    5217    }
    5218
    5219    /**
    5220     * <p>Left pad a String with spaces (' ').</p>
    5221     *
    5222     * <p>The String is padded to the size of {@code size}.</p>
    5223     *
    5224     * <pre>
    5225     * StringUtils.leftPad(null, *)   = null
    5226     * StringUtils.leftPad("", 3)     = "   "
    5227     * StringUtils.leftPad("bat", 3)  = "bat"
    5228     * StringUtils.leftPad("bat", 5)  = "  bat"
    5229     * StringUtils.leftPad("bat", 1)  = "bat"
    5230     * StringUtils.leftPad("bat", -1) = "bat"
    5231     * </pre>
    5232     *
    5233     * @param str  the String to pad out, may be null
    5234     * @param size  the size to pad to
    5235     * @return left padded String or original String if no padding is necessary,
    5236     *  {@code null} if null String input
    5237     */
    5238    public static String leftPad(final String str, final int size) {
    5239        return leftPad(str, size, ' ');
    5240    }
    5241
    5242    /**
    5243     * <p>Left pad a String with a specified character.</p>
    5244     *
    5245     * <p>Pad to a size of {@code size}.</p>
    5246     *
    5247     * <pre>
    5248     * StringUtils.leftPad(null, *, *)     = null
    5249     * StringUtils.leftPad("", 3, 'z')     = "zzz"
    5250     * StringUtils.leftPad("bat", 3, 'z')  = "bat"
    5251     * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
    5252     * StringUtils.leftPad("bat", 1, 'z')  = "bat"
    5253     * StringUtils.leftPad("bat", -1, 'z') = "bat"
    5254     * </pre>
    5255     *
    5256     * @param str  the String to pad out, may be null
    5257     * @param size  the size to pad to
    5258     * @param padChar  the character to pad with
    5259     * @return left padded String or original String if no padding is necessary,
    5260     *  {@code null} if null String input
    5261     * @since 2.0
    5262     */
    5263    public static String leftPad(final String str, final int size, final char padChar) {
    5264        if (str == null) {
    5265            return null;
    5266        }
    5267        final int pads = size - str.length();
    5268        if (pads <= 0) {
    5269            return str; // returns original String when possible
    5270        }
    5271        if (pads > PAD_LIMIT) {
    5272            return leftPad(str, size, String.valueOf(padChar));
    5273        }
    5274        return repeat(padChar, pads).concat(str);
    5275    }
    5276
    5277    /**
    5278     * <p>Left pad a String with a specified String.</p>
    5279     *
    5280     * <p>Pad to a size of {@code size}.</p>
    5281     *
    5282     * <pre>
    5283     * StringUtils.leftPad(null, *, *)      = null
    5284     * StringUtils.leftPad("", 3, "z")      = "zzz"
    5285     * StringUtils.leftPad("bat", 3, "yz")  = "bat"
    5286     * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
    5287     * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
    5288     * StringUtils.leftPad("bat", 1, "yz")  = "bat"
    5289     * StringUtils.leftPad("bat", -1, "yz") = "bat"
    5290     * StringUtils.leftPad("bat", 5, null)  = "  bat"
    5291     * StringUtils.leftPad("bat", 5, "")    = "  bat"
    5292     * </pre>
    5293     *
    5294     * @param str  the String to pad out, may be null
    5295     * @param size  the size to pad to
    5296     * @param padStr  the String to pad with, null or empty treated as single space
    5297     * @return left padded String or original String if no padding is necessary,
    5298     *  {@code null} if null String input
    5299     */
    5300    public static String leftPad(final String str, final int size, String padStr) {
    5301        if (str == null) {
    5302            return null;
    5303        }
    5304        if (isEmpty(padStr)) {
    5305            padStr = SPACE;
    5306        }
    5307        final int padLen = padStr.length();
    5308        final int strLen = str.length();
    5309        final int pads = size - strLen;
    5310        if (pads <= 0) {
    5311            return str; // returns original String when possible
    5312        }
    5313        if (padLen == 1 && pads <= PAD_LIMIT) {
    5314            return leftPad(str, size, padStr.charAt(0));
    5315        }
    5316
    5317        if (pads == padLen) {
    5318            return padStr.concat(str);
    5319        } else if (pads < padLen) {
    5320            return padStr.substring(0, pads).concat(str);
    5321        } else {
    5322            final char[] padding = new char[pads];
    5323            final char[] padChars = padStr.toCharArray();
    5324            for (int i = 0; i < pads; i++) {
    5325                padding[i] = padChars[i % padLen];
    5326            }
    5327            return new String(padding).concat(str);
    5328        }
    5329    }
    5330
    5331    /**
    5332     * Gets a CharSequence length or {@code 0} if the CharSequence is
    5333     * {@code null}.
    5334     *
    5335     * @param cs
    5336     *            a CharSequence or {@code null}
    5337     * @return CharSequence length or {@code 0} if the CharSequence is
    5338     *         {@code null}.
    5339     * @since 2.4
    5340     * @since 3.0 Changed signature from length(String) to length(CharSequence)
    5341     */
    5342    public static int length(final CharSequence cs) {
    5343        return cs == null ? 0 : cs.length();
    5344    }
    5345
    5346    /**
    5347     * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
    5348     *
    5349     * <p>A {@code null} input String returns {@code null}.</p>
    5350     *
    5351     * <pre>
    5352     * StringUtils.lowerCase(null)  = null
    5353     * StringUtils.lowerCase("")    = ""
    5354     * StringUtils.lowerCase("aBc") = "abc"
    5355     * </pre>
    5356     *
    5357     * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
    5358     * the result of this method is affected by the current locale.
    5359     * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    5360     * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    5361     *
    5362     * @param str  the String to lower case, may be null
    5363     * @return the lower cased String, {@code null} if null String input
    5364     */
    5365    public static String lowerCase(final String str) {
    5366        if (str == null) {
    5367            return null;
    5368        }
    5369        return str.toLowerCase();
    5370    }
    5371
    5372    /**
    5373     * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p>
    5374     *
    5375     * <p>A {@code null} input String returns {@code null}.</p>
    5376     *
    5377     * <pre>
    5378     * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
    5379     * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
    5380     * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
    5381     * </pre>
    5382     *
    5383     * @param str  the String to lower case, may be null
    5384     * @param locale  the locale that defines the case transformation rules, must not be null
    5385     * @return the lower cased String, {@code null} if null String input
    5386     * @since 2.5
    5387     */
    5388    public static String lowerCase(final String str, final Locale locale) {
    5389        if (str == null) {
    5390            return null;
    5391        }
    5392        return str.toLowerCase(locale);
    5393    }
    5394
    5395    private static int[] matches(final CharSequence first, final CharSequence second) {
    5396        CharSequence max, min;
    5397        if (first.length() > second.length()) {
    5398            max = first;
    5399            min = second;
    5400        } else {
    5401            max = second;
    5402            min = first;
    5403        }
    5404        final int range = Math.max(max.length() / 2 - 1, 0);
    5405        final int[] matchIndexes = new int[min.length()];
    5406        Arrays.fill(matchIndexes, -1);
    5407        final boolean[] matchFlags = new boolean[max.length()];
    5408        int matches = 0;
    5409        for (int mi = 0; mi < min.length(); mi++) {
    5410            final char c1 = min.charAt(mi);
    5411            for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
    5412                if (!matchFlags[xi] && c1 == max.charAt(xi)) {
    5413                    matchIndexes[mi] = xi;
    5414                    matchFlags[xi] = true;
    5415                    matches++;
    5416                    break;
    5417                }
    5418            }
    5419        }
    5420        final char[] ms1 = new char[matches];
    5421        final char[] ms2 = new char[matches];
    5422        for (int i = 0, si = 0; i < min.length(); i++) {
    5423            if (matchIndexes[i] != -1) {
    5424                ms1[si] = min.charAt(i);
    5425                si++;
    5426            }
    5427        }
    5428        for (int i = 0, si = 0; i < max.length(); i++) {
    5429            if (matchFlags[i]) {
    5430                ms2[si] = max.charAt(i);
    5431                si++;
    5432            }
    5433        }
    5434        int transpositions = 0;
    5435        for (int mi = 0; mi < ms1.length; mi++) {
    5436            if (ms1[mi] != ms2[mi]) {
    5437                transpositions++;
    5438            }
    5439        }
    5440        int prefix = 0;
    5441        for (int mi = 0; mi < min.length(); mi++) {
    5442            if (first.charAt(mi) == second.charAt(mi)) {
    5443                prefix++;
    5444            } else {
    5445                break;
    5446            }
    5447        }
    5448        return new int[] { matches, transpositions / 2, prefix, max.length() };
    5449    }
    5450
    5451    /**
    5452     * <p>Gets {@code len} characters from the middle of a String.</p>
    5453     *
    5454     * <p>If {@code len} characters are not available, the remainder
    5455     * of the String will be returned without an exception. If the
    5456     * String is {@code null}, {@code null} will be returned.
    5457     * An empty String is returned if len is negative or exceeds the
    5458     * length of {@code str}.</p>
    5459     *
    5460     * <pre>
    5461     * StringUtils.mid(null, *, *)    = null
    5462     * StringUtils.mid(*, *, -ve)     = ""
    5463     * StringUtils.mid("", 0, *)      = ""
    5464     * StringUtils.mid("abc", 0, 2)   = "ab"
    5465     * StringUtils.mid("abc", 0, 4)   = "abc"
    5466     * StringUtils.mid("abc", 2, 4)   = "c"
    5467     * StringUtils.mid("abc", 4, 2)   = ""
    5468     * StringUtils.mid("abc", -2, 2)  = "ab"
    5469     * </pre>
    5470     *
    5471     * @param str  the String to get the characters from, may be null
    5472     * @param pos  the position to start from, negative treated as zero
    5473     * @param len  the length of the required String
    5474     * @return the middle characters, {@code null} if null String input
    5475     */
    5476    public static String mid(final String str, int pos, final int len) {
    5477        if (str == null) {
    5478            return null;
    5479        }
    5480        if (len < 0 || pos > str.length()) {
    5481            return EMPTY;
    5482        }
    5483        if (pos < 0) {
    5484            pos = 0;
    5485        }
    5486        if (str.length() <= pos + len) {
    5487            return str.substring(pos);
    5488        }
    5489        return str.substring(pos, pos + len);
    5490    }
    5491
    5492    private static StringBuilder newStringBuilder(final int noOfItems) {
    5493        return new StringBuilder(noOfItems * 16);
    5494    }
    5495
    5496    /**
    5497     * <p>
    5498     * Similar to <a
    5499     * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize
    5500     * -space</a>
    5501     * </p>
    5502     * <p>
    5503     * The function returns the argument string with whitespace normalized by using
    5504     * {@code {@link #trim(String)}} to remove leading and trailing whitespace
    5505     * and then replacing sequences of whitespace characters by a single space.
    5506     * </p>
    5507     * In XML Whitespace characters are the same as those allowed by the <a
    5508     * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
    5509     * <p>
    5510     * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
    5511     *
    5512     * <p>For reference:</p>
    5513     * <ul>
    5514     * <li>\x0B = vertical tab</li>
    5515     * <li>\f = #xC = form feed</li>
    5516     * <li>#x20 = space</li>
    5517     * <li>#x9 = \t</li>
    5518     * <li>#xA = \n</li>
    5519     * <li>#xD = \r</li>
    5520     * </ul>
    5521     *
    5522     * <p>
    5523     * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
    5524     * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char &lt;= 32) from both
    5525     * ends of this String.
    5526     * </p>
    5527     *
    5528     * @see Pattern
    5529     * @see #trim(String)
    5530     * @see <a
    5531     *      href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a>
    5532     * @param str the source String to normalize whitespaces from, may be null
    5533     * @return the modified string with whitespace normalized, {@code null} if null String input
    5534     *
    5535     * @since 3.0
    5536     */
    5537    public static String normalizeSpace(final String str) {
    5538        // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
    5539        // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
    5540        if (isEmpty(str)) {
    5541            return str;
    5542        }
    5543        final int size = str.length();
    5544        final char[] newChars = new char[size];
    5545        int count = 0;
    5546        int whitespacesCount = 0;
    5547        boolean startWhitespaces = true;
    5548        for (int i = 0; i < size; i++) {
    5549            final char actualChar = str.charAt(i);
    5550            final boolean isWhitespace = Character.isWhitespace(actualChar);
    5551            if (isWhitespace) {
    5552                if (whitespacesCount == 0 && !startWhitespaces) {
    5553                    newChars[count++] = SPACE.charAt(0);
    5554                }
    5555                whitespacesCount++;
    5556            } else {
    5557                startWhitespaces = false;
    5558                newChars[count++] = (actualChar == 160 ? 32 : actualChar);
    5559                whitespacesCount = 0;
    5560            }
    5561        }
    5562        if (startWhitespaces) {
    5563            return EMPTY;
    5564        }
    5565        return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
    5566    }
    5567
    5568    /**
    5569     * <p>Finds the n-th index within a CharSequence, handling {@code null}.
    5570     * This method uses {@link String#indexOf(String)} if possible.</p>
    5571     * <p><b>Note:</b> The code starts looking for a match at the start of the target,
    5572     * incrementing the starting index by one after each successful match
    5573     * (unless {@code searchStr} is an empty string in which case the position
    5574     * is never incremented and {@code 0} is returned immediately).
    5575     * This means that matches may overlap.</p>
    5576     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    5577     *
    5578     * <pre>
    5579     * StringUtils.ordinalIndexOf(null, *, *)          = -1
    5580     * StringUtils.ordinalIndexOf(*, null, *)          = -1
    5581     * StringUtils.ordinalIndexOf("", "", *)           = 0
    5582     * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
    5583     * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
    5584     * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
    5585     * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
    5586     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
    5587     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
    5588     * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
    5589     * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
    5590     * </pre>
    5591     *
    5592     * <p>Matches may overlap:</p>
    5593     * <pre>
    5594     * StringUtils.ordinalIndexOf("ababab", "aba", 1)   = 0
    5595     * StringUtils.ordinalIndexOf("ababab", "aba", 2)   = 2
    5596     * StringUtils.ordinalIndexOf("ababab", "aba", 3)   = -1
    5597     *
    5598     * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
    5599     * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
    5600     * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
    5601     * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
    5602     * </pre>
    5603     *
    5604     * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p>
    5605     *
    5606     * <pre>
    5607     *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
    5608     * </pre>
    5609     *
    5610     * @param str  the CharSequence to check, may be null
    5611     * @param searchStr  the CharSequence to find, may be null
    5612     * @param ordinal  the n-th {@code searchStr} to find
    5613     * @return the n-th index of the search CharSequence,
    5614     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5615     * @since 2.1
    5616     * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
    5617     */
    5618    public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
    5619        return ordinalIndexOf(str, searchStr, ordinal, false);
    5620    }
    5621
    5622    /**
    5623     * <p>Finds the n-th index within a String, handling {@code null}.
    5624     * This method uses {@link String#indexOf(String)} if possible.</p>
    5625     * <p>Note that matches may overlap<p>
    5626     *
    5627     * <p>A {@code null} CharSequence will return {@code -1}.</p>
    5628     *
    5629     * @param str  the CharSequence to check, may be null
    5630     * @param searchStr  the CharSequence to find, may be null
    5631     * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
    5632     * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
    5633     * @return the n-th index of the search CharSequence,
    5634     *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
    5635     */
    5636    // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
    5637    private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
    5638        if (str == null || searchStr == null || ordinal <= 0) {
    5639            return INDEX_NOT_FOUND;
    5640        }
    5641        if (searchStr.length() == 0) {
    5642            return lastIndex ? str.length() : 0;
    5643        }
    5644        int found = 0;
    5645        // set the initial index beyond the end of the string
    5646        // this is to allow for the initial index decrement/increment
    5647        int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
    5648        do {
    5649            if (lastIndex) {
    5650                index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string
    5651            } else {
    5652                index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
    5653            }
    5654            if (index < 0) {
    5655                return index;
    5656            }
    5657            found++;
    5658        } while (found < ordinal);
    5659        return index;
    5660    }
    5661
    5662    // Overlay
    5663    //-----------------------------------------------------------------------
    5664    /**
    5665     * <p>Overlays part of a String with another String.</p>
    5666     *
    5667     * <p>A {@code null} string input returns {@code null}.
    5668     * A negative index is treated as zero.
    5669     * An index greater than the string length is treated as the string length.
    5670     * The start index is always the smaller of the two indices.</p>
    5671     *
    5672     * <pre>
    5673     * StringUtils.overlay(null, *, *, *)            = null
    5674     * StringUtils.overlay("", "abc", 0, 0)          = "abc"
    5675     * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
    5676     * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
    5677     * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
    5678     * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
    5679     * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
    5680     * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
    5681     * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
    5682     * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
    5683     * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
    5684     * </pre>
    5685     *
    5686     * @param str  the String to do overlaying in, may be null
    5687     * @param overlay  the String to overlay, may be null
    5688     * @param start  the position to start overlaying at
    5689     * @param end  the position to stop overlaying before
    5690     * @return overlayed String, {@code null} if null String input
    5691     * @since 2.0
    5692     */
    5693    public static String overlay(final String str, String overlay, int start, int end) {
    5694        if (str == null) {
    5695            return null;
    5696        }
    5697        if (overlay == null) {
    5698            overlay = EMPTY;
    5699        }
    5700        final int len = str.length();
    5701        if (start < 0) {
    5702            start = 0;
    5703        }
    5704        if (start > len) {
    5705            start = len;
    5706        }
    5707        if (end < 0) {
    5708            end = 0;
    5709        }
    5710        if (end > len) {
    5711            end = len;
    5712        }
    5713        if (start > end) {
    5714            final int temp = start;
    5715            start = end;
    5716            end = temp;
    5717        }
    5718        return str.substring(0, start) +
    5719            overlay +
    5720            str.substring(end);
    5721    }
    5722
    5723    /**
    5724     * Prepends the prefix to the start of the string if the string does not
    5725     * already start with any of the prefixes.
    5726     *
    5727     * @param str The string.
    5728     * @param prefix The prefix to prepend to the start of the string.
    5729     * @param ignoreCase Indicates whether the compare should ignore case.
    5730     * @param prefixes Additional prefixes that are valid (optional).
    5731     *
    5732     * @return A new String if prefix was prepended, the same string otherwise.
    5733     */
    5734    private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
    5735        if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) {
    5736            return str;
    5737        }
    5738        if (ArrayUtils.isNotEmpty(prefixes)) {
    5739            for (final CharSequence p : prefixes) {
    5740                if (startsWith(str, p, ignoreCase)) {
    5741                    return str;
    5742                }
    5743            }
    5744        }
    5745        return prefix.toString() + str;
    5746    }
    5747
    5748    /**
    5749     * Prepends the prefix to the start of the string if the string does not
    5750     * already start with any of the prefixes.
    5751     *
    5752     * <pre>
    5753     * StringUtils.prependIfMissing(null, null) = null
    5754     * StringUtils.prependIfMissing("abc", null) = "abc"
    5755     * StringUtils.prependIfMissing("", "xyz") = "xyz"
    5756     * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
    5757     * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
    5758     * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
    5759     * </pre>
    5760     * <p>With additional prefixes,</p>
    5761     * <pre>
    5762     * StringUtils.prependIfMissing(null, null, null) = null
    5763     * StringUtils.prependIfMissing("abc", null, null) = "abc"
    5764     * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
    5765     * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
    5766     * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
    5767     * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
    5768     * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
    5769     * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
    5770     * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
    5771     * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
    5772     * </pre>
    5773     *
    5774     * @param str The string.
    5775     * @param prefix The prefix to prepend to the start of the string.
    5776     * @param prefixes Additional prefixes that are valid.
    5777     *
    5778     * @return A new String if prefix was prepended, the same string otherwise.
    5779     *
    5780     * @since 3.2
    5781     */
    5782    public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
    5783        return prependIfMissing(str, prefix, false, prefixes);
    5784    }
    5785
    5786    /**
    5787     * Prepends the prefix to the start of the string if the string does not
    5788     * already start, case insensitive, with any of the prefixes.
    5789     *
    5790     * <pre>
    5791     * StringUtils.prependIfMissingIgnoreCase(null, null) = null
    5792     * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
    5793     * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
    5794     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
    5795     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
    5796     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
    5797     * </pre>
    5798     * <p>With additional prefixes,</p>
    5799     * <pre>
    5800     * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
    5801     * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
    5802     * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
    5803     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
    5804     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
    5805     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
    5806     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
    5807     * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
    5808     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
    5809     * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
    5810     * </pre>
    5811     *
    5812     * @param str The string.
    5813     * @param prefix The prefix to prepend to the start of the string.
    5814     * @param prefixes Additional prefixes that are valid (optional).
    5815     *
    5816     * @return A new String if prefix was prepended, the same string otherwise.
    5817     *
    5818     * @since 3.2
    5819     */
    5820    public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
    5821        return prependIfMissing(str, prefix, true, prefixes);
    5822    }
    5823
    5824    /**
    5825     * <p>Removes all occurrences of a character from within the source string.</p>
    5826     *
    5827     * <p>A {@code null} source string will return {@code null}.
    5828     * An empty ("") source string will return the empty string.</p>
    5829     *
    5830     * <pre>
    5831     * StringUtils.remove(null, *)       = null
    5832     * StringUtils.remove("", *)         = ""
    5833     * StringUtils.remove("queued", 'u') = "qeed"
    5834     * StringUtils.remove("queued", 'z') = "queued"
    5835     * </pre>
    5836     *
    5837     * @param str  the source String to search, may be null
    5838     * @param remove  the char to search for and remove, may be null
    5839     * @return the substring with the char removed if found,
    5840     *  {@code null} if null String input
    5841     * @since 2.1
    5842     */
    5843    public static String remove(final String str, final char remove) {
    5844        if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
    5845            return str;
    5846        }
    5847        final char[] chars = str.toCharArray();
    5848        int pos = 0;
    5849        for (int i = 0; i < chars.length; i++) {
    5850            if (chars[i] != remove) {
    5851                chars[pos++] = chars[i];
    5852            }
    5853        }
    5854        return new String(chars, 0, pos);
    5855    }
    5856
    5857    /**
    5858     * <p>Removes all occurrences of a substring from within the source string.</p>
    5859     *
    5860     * <p>A {@code null} source string will return {@code null}.
    5861     * An empty ("") source string will return the empty string.
    5862     * A {@code null} remove string will return the source string.
    5863     * An empty ("") remove string will return the source string.</p>
    5864     *
    5865     * <pre>
    5866     * StringUtils.remove(null, *)        = null
    5867     * StringUtils.remove("", *)          = ""
    5868     * StringUtils.remove(*, null)        = *
    5869     * StringUtils.remove(*, "")          = *
    5870     * StringUtils.remove("queued", "ue") = "qd"
    5871     * StringUtils.remove("queued", "zz") = "queued"
    5872     * </pre>
    5873     *
    5874     * @param str  the source String to search, may be null
    5875     * @param remove  the String to search for and remove, may be null
    5876     * @return the substring with the string removed if found,
    5877     *  {@code null} if null String input
    5878     * @since 2.1
    5879     */
    5880    public static String remove(final String str, final String remove) {
    5881        if (isEmpty(str) || isEmpty(remove)) {
    5882            return str;
    5883        }
    5884        return replace(str, remove, EMPTY, -1);
    5885    }
    5886
    5887    /**
    5888     * <p>Removes each substring of the text String that matches the given regular expression.</p>
    5889     *
    5890     * This method is a {@code null} safe equivalent to:
    5891     * <ul>
    5892     *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
    5893     *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
    5894     * </ul>
    5895     *
    5896     * <p>A {@code null} reference passed to this method is a no-op.</p>
    5897     *
    5898     * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
    5899     * is NOT automatically added.
    5900     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    5901     * DOTALL is also known as single-line mode in Perl.</p>
    5902     *
    5903     * <pre>
    5904     * StringUtils.removeAll(null, *)      = null
    5905     * StringUtils.removeAll("any", (String) null)  = "any"
    5906     * StringUtils.removeAll("any", "")    = "any"
    5907     * StringUtils.removeAll("any", ".*")  = ""
    5908     * StringUtils.removeAll("any", ".+")  = ""
    5909     * StringUtils.removeAll("abc", ".?")  = ""
    5910     * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\nB"
    5911     * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
    5912     * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
    5913     * </pre>
    5914     *
    5915     * @param text  text to remove from, may be null
    5916     * @param regex  the regular expression to which this string is to be matched
    5917     * @return  the text with any removes processed,
    5918     *              {@code null} if null String input
    5919     *
    5920     * @throws  java.util.regex.PatternSyntaxException
    5921     *              if the regular expression's syntax is invalid
    5922     *
    5923     * @see #replaceAll(String, String, String)
    5924     * @see #removePattern(String, String)
    5925     * @see String#replaceAll(String, String)
    5926     * @see java.util.regex.Pattern
    5927     * @see java.util.regex.Pattern#DOTALL
    5928     * @since 3.5
    5929     *
    5930     * @deprecated Moved to RegExUtils.
    5931     */
    5932    @Deprecated
    5933    public static String removeAll(final String text, final String regex) {
    5934        return RegExUtils.removeAll(text, regex);
    5935    }
    5936
    5937    /**
    5938     * <p>Removes a substring only if it is at the end of a source string,
    5939     * otherwise returns the source string.</p>
    5940     *
    5941     * <p>A {@code null} source string will return {@code null}.
    5942     * An empty ("") source string will return the empty string.
    5943     * A {@code null} search string will return the source string.</p>
    5944     *
    5945     * <pre>
    5946     * StringUtils.removeEnd(null, *)      = null
    5947     * StringUtils.removeEnd("", *)        = ""
    5948     * StringUtils.removeEnd(*, null)      = *
    5949     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
    5950     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
    5951     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
    5952     * StringUtils.removeEnd("abc", "")    = "abc"
    5953     * </pre>
    5954     *
    5955     * @param str  the source String to search, may be null
    5956     * @param remove  the String to search for and remove, may be null
    5957     * @return the substring with the string removed if found,
    5958     *  {@code null} if null String input
    5959     * @since 2.1
    5960     */
    5961    public static String removeEnd(final String str, final String remove) {
    5962        if (isEmpty(str) || isEmpty(remove)) {
    5963            return str;
    5964        }
    5965        if (str.endsWith(remove)) {
    5966            return str.substring(0, str.length() - remove.length());
    5967        }
    5968        return str;
    5969    }
    5970
    5971    /**
    5972     * <p>Case insensitive removal of a substring if it is at the end of a source string,
    5973     * otherwise returns the source string.</p>
    5974     *
    5975     * <p>A {@code null} source string will return {@code null}.
    5976     * An empty ("") source string will return the empty string.
    5977     * A {@code null} search string will return the source string.</p>
    5978     *
    5979     * <pre>
    5980     * StringUtils.removeEndIgnoreCase(null, *)      = null
    5981     * StringUtils.removeEndIgnoreCase("", *)        = ""
    5982     * StringUtils.removeEndIgnoreCase(*, null)      = *
    5983     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
    5984     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
    5985     * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    5986     * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
    5987     * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
    5988     * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
    5989     * </pre>
    5990     *
    5991     * @param str  the source String to search, may be null
    5992     * @param remove  the String to search for (case insensitive) and remove, may be null
    5993     * @return the substring with the string removed if found,
    5994     *  {@code null} if null String input
    5995     * @since 2.4
    5996     */
    5997    public static String removeEndIgnoreCase(final String str, final String remove) {
    5998        if (isEmpty(str) || isEmpty(remove)) {
    5999            return str;
    6000        }
    6001        if (endsWithIgnoreCase(str, remove)) {
    6002            return str.substring(0, str.length() - remove.length());
    6003        }
    6004        return str;
    6005    }
    6006
    6007    /**
    6008     * <p>Removes the first substring of the text string that matches the given regular expression.</p>
    6009     *
    6010     * This method is a {@code null} safe equivalent to:
    6011     * <ul>
    6012     *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
    6013     *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
    6014     * </ul>
    6015     *
    6016     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6017     *
    6018     * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
    6019     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    6020     * DOTALL is also known as single-line mode in Perl.</p>
    6021     *
    6022     * <pre>
    6023     * StringUtils.removeFirst(null, *)      = null
    6024     * StringUtils.removeFirst("any", (String) null)  = "any"
    6025     * StringUtils.removeFirst("any", "")    = "any"
    6026     * StringUtils.removeFirst("any", ".*")  = ""
    6027     * StringUtils.removeFirst("any", ".+")  = ""
    6028     * StringUtils.removeFirst("abc", ".?")  = "bc"
    6029     * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")      = "A\n&lt;__&gt;B"
    6030     * StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B", "(?s)&lt;.*&gt;")  = "AB"
    6031     * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
    6032     * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
    6033     * </pre>
    6034     *
    6035     * @param text  text to remove from, may be null
    6036     * @param regex  the regular expression to which this string is to be matched
    6037     * @return  the text with the first replacement processed,
    6038     *              {@code null} if null String input
    6039     *
    6040     * @throws  java.util.regex.PatternSyntaxException
    6041     *              if the regular expression's syntax is invalid
    6042     *
    6043     * @see #replaceFirst(String, String, String)
    6044     * @see String#replaceFirst(String, String)
    6045     * @see java.util.regex.Pattern
    6046     * @see java.util.regex.Pattern#DOTALL
    6047     * @since 3.5
    6048     *
    6049     * @deprecated Moved to RegExUtils.
    6050     */
    6051    @Deprecated
    6052    public static String removeFirst(final String text, final String regex) {
    6053        return replaceFirst(text, regex, EMPTY);
    6054    }
    6055
    6056    /**
    6057     * <p>
    6058     * Case insensitive removal of all occurrences of a substring from within
    6059     * the source string.
    6060     * </p>
    6061     *
    6062     * <p>
    6063     * A {@code null} source string will return {@code null}. An empty ("")
    6064     * source string will return the empty string. A {@code null} remove string
    6065     * will return the source string. An empty ("") remove string will return
    6066     * the source string.
    6067     * </p>
    6068     *
    6069     * <pre>
    6070     * StringUtils.removeIgnoreCase(null, *)        = null
    6071     * StringUtils.removeIgnoreCase("", *)          = ""
    6072     * StringUtils.removeIgnoreCase(*, null)        = *
    6073     * StringUtils.removeIgnoreCase(*, "")          = *
    6074     * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
    6075     * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
    6076     * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
    6077     * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
    6078     * </pre>
    6079     *
    6080     * @param str
    6081     *            the source String to search, may be null
    6082     * @param remove
    6083     *            the String to search for (case insensitive) and remove, may be
    6084     *            null
    6085     * @return the substring with the string removed if found, {@code null} if
    6086     *         null String input
    6087     * @since 3.5
    6088     */
    6089    public static String removeIgnoreCase(final String str, final String remove) {
    6090        if (isEmpty(str) || isEmpty(remove)) {
    6091            return str;
    6092        }
    6093        return replaceIgnoreCase(str, remove, EMPTY, -1);
    6094    }
    6095
    6096    /**
    6097     * <p>Removes each substring of the source String that matches the given regular expression using the DOTALL option.
    6098     * </p>
    6099     *
    6100     * This call is a {@code null} safe equivalent to:
    6101     * <ul>
    6102     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
    6103     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
    6104     * </ul>
    6105     *
    6106     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6107     *
    6108     * <pre>
    6109     * StringUtils.removePattern(null, *)       = null
    6110     * StringUtils.removePattern("any", (String) null)   = "any"
    6111     * StringUtils.removePattern("A&lt;__&gt;\n&lt;__&gt;B", "&lt;.*&gt;")  = "AB"
    6112     * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
    6113     * </pre>
    6114     *
    6115     * @param source
    6116     *            the source string
    6117     * @param regex
    6118     *            the regular expression to which this string is to be matched
    6119     * @return The resulting {@code String}
    6120     * @see #replacePattern(String, String, String)
    6121     * @see String#replaceAll(String, String)
    6122     * @see Pattern#DOTALL
    6123     * @since 3.2
    6124     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
    6125     *
    6126     * @deprecated Moved to RegExUtils.
    6127     */
    6128    @Deprecated
    6129    public static String removePattern(final String source, final String regex) {
    6130        return RegExUtils.removePattern(source, regex);
    6131    }
    6132
    6133    // Remove
    6134    //-----------------------------------------------------------------------
    6135    /**
    6136     * <p>Removes a substring only if it is at the beginning of a source string,
    6137     * otherwise returns the source string.</p>
    6138     *
    6139     * <p>A {@code null} source string will return {@code null}.
    6140     * An empty ("") source string will return the empty string.
    6141     * A {@code null} search string will return the source string.</p>
    6142     *
    6143     * <pre>
    6144     * StringUtils.removeStart(null, *)      = null
    6145     * StringUtils.removeStart("", *)        = ""
    6146     * StringUtils.removeStart(*, null)      = *
    6147     * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
    6148     * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
    6149     * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
    6150     * StringUtils.removeStart("abc", "")    = "abc"
    6151     * </pre>
    6152     *
    6153     * @param str  the source String to search, may be null
    6154     * @param remove  the String to search for and remove, may be null
    6155     * @return the substring with the string removed if found,
    6156     *  {@code null} if null String input
    6157     * @since 2.1
    6158     */
    6159    public static String removeStart(final String str, final String remove) {
    6160        if (isEmpty(str) || isEmpty(remove)) {
    6161            return str;
    6162        }
    6163        if (str.startsWith(remove)) {
    6164            return str.substring(remove.length());
    6165        }
    6166        return str;
    6167    }
    6168
    6169    /**
    6170     * <p>Case insensitive removal of a substring if it is at the beginning of a source string,
    6171     * otherwise returns the source string.</p>
    6172     *
    6173     * <p>A {@code null} source string will return {@code null}.
    6174     * An empty ("") source string will return the empty string.
    6175     * A {@code null} search string will return the source string.</p>
    6176     *
    6177     * <pre>
    6178     * StringUtils.removeStartIgnoreCase(null, *)      = null
    6179     * StringUtils.removeStartIgnoreCase("", *)        = ""
    6180     * StringUtils.removeStartIgnoreCase(*, null)      = *
    6181     * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
    6182     * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
    6183     * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
    6184     * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
    6185     * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
    6186     * </pre>
    6187     *
    6188     * @param str  the source String to search, may be null
    6189     * @param remove  the String to search for (case insensitive) and remove, may be null
    6190     * @return the substring with the string removed if found,
    6191     *  {@code null} if null String input
    6192     * @since 2.4
    6193     */
    6194    public static String removeStartIgnoreCase(final String str, final String remove) {
    6195        if (isEmpty(str) || isEmpty(remove)) {
    6196            return str;
    6197        }
    6198        if (startsWithIgnoreCase(str, remove)) {
    6199            return str.substring(remove.length());
    6200        }
    6201        return str;
    6202    }
    6203
    6204    /**
    6205     * <p>Returns padding using the specified delimiter repeated
    6206     * to a given length.</p>
    6207     *
    6208     * <pre>
    6209     * StringUtils.repeat('e', 0)  = ""
    6210     * StringUtils.repeat('e', 3)  = "eee"
    6211     * StringUtils.repeat('e', -2) = ""
    6212     * </pre>
    6213     *
    6214     * <p>Note: this method does not support padding with
    6215     * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
    6216     * as they require a pair of {@code char}s to be represented.
    6217     * If you are needing to support full I18N of your applications
    6218     * consider using {@link #repeat(String, int)} instead.
    6219     * </p>
    6220     *
    6221     * @param ch  character to repeat
    6222     * @param repeat  number of times to repeat char, negative treated as zero
    6223     * @return String with repeated character
    6224     * @see #repeat(String, int)
    6225     */
    6226    public static String repeat(final char ch, final int repeat) {
    6227        if (repeat <= 0) {
    6228            return EMPTY;
    6229        }
    6230        final char[] buf = new char[repeat];
    6231        for (int i = repeat - 1; i >= 0; i--) {
    6232            buf[i] = ch;
    6233        }
    6234        return new String(buf);
    6235    }
    6236
    6237    // Padding
    6238    //-----------------------------------------------------------------------
    6239    /**
    6240     * <p>Repeat a String {@code repeat} times to form a
    6241     * new String.</p>
    6242     *
    6243     * <pre>
    6244     * StringUtils.repeat(null, 2) = null
    6245     * StringUtils.repeat("", 0)   = ""
    6246     * StringUtils.repeat("", 2)   = ""
    6247     * StringUtils.repeat("a", 3)  = "aaa"
    6248     * StringUtils.repeat("ab", 2) = "abab"
    6249     * StringUtils.repeat("a", -2) = ""
    6250     * </pre>
    6251     *
    6252     * @param str  the String to repeat, may be null
    6253     * @param repeat  number of times to repeat str, negative treated as zero
    6254     * @return a new String consisting of the original String repeated,
    6255     *  {@code null} if null String input
    6256     */
    6257    public static String repeat(final String str, final int repeat) {
    6258        // Performance tuned for 2.0 (JDK1.4)
    6259
    6260        if (str == null) {
    6261            return null;
    6262        }
    6263        if (repeat <= 0) {
    6264            return EMPTY;
    6265        }
    6266        final int inputLength = str.length();
    6267        if (repeat == 1 || inputLength == 0) {
    6268            return str;
    6269        }
    6270        if (inputLength == 1 && repeat <= PAD_LIMIT) {
    6271            return repeat(str.charAt(0), repeat);
    6272        }
    6273
    6274        final int outputLength = inputLength * repeat;
    6275        switch (inputLength) {
    6276            case 1 :
    6277                return repeat(str.charAt(0), repeat);
    6278            case 2 :
    6279                final char ch0 = str.charAt(0);
    6280                final char ch1 = str.charAt(1);
    6281                final char[] output2 = new char[outputLength];
    6282                for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
    6283                    output2[i] = ch0;
    6284                    output2[i + 1] = ch1;
    6285                }
    6286                return new String(output2);
    6287            default :
    6288                final StringBuilder buf = new StringBuilder(outputLength);
    6289                for (int i = 0; i < repeat; i++) {
    6290                    buf.append(str);
    6291                }
    6292                return buf.toString();
    6293        }
    6294    }
    6295
    6296    // Conversion
    6297    //-----------------------------------------------------------------------
    6298
    6299    /**
    6300     * <p>Repeat a String {@code repeat} times to form a
    6301     * new String, with a String separator injected each time. </p>
    6302     *
    6303     * <pre>
    6304     * StringUtils.repeat(null, null, 2) = null
    6305     * StringUtils.repeat(null, "x", 2)  = null
    6306     * StringUtils.repeat("", null, 0)   = ""
    6307     * StringUtils.repeat("", "", 2)     = ""
    6308     * StringUtils.repeat("", "x", 3)    = "xxx"
    6309     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
    6310     * </pre>
    6311     *
    6312     * @param str        the String to repeat, may be null
    6313     * @param separator  the String to inject, may be null
    6314     * @param repeat     number of times to repeat str, negative treated as zero
    6315     * @return a new String consisting of the original String repeated,
    6316     *  {@code null} if null String input
    6317     * @since 2.5
    6318     */
    6319    public static String repeat(final String str, final String separator, final int repeat) {
    6320        if (str == null || separator == null) {
    6321            return repeat(str, repeat);
    6322        }
    6323        // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
    6324        final String result = repeat(str + separator, repeat);
    6325        return removeEnd(result, separator);
    6326    }
    6327
    6328    /**
    6329     * <p>Replaces all occurrences of a String within another String.</p>
    6330     *
    6331     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6332     *
    6333     * <pre>
    6334     * StringUtils.replace(null, *, *)        = null
    6335     * StringUtils.replace("", *, *)          = ""
    6336     * StringUtils.replace("any", null, *)    = "any"
    6337     * StringUtils.replace("any", *, null)    = "any"
    6338     * StringUtils.replace("any", "", *)      = "any"
    6339     * StringUtils.replace("aba", "a", null)  = "aba"
    6340     * StringUtils.replace("aba", "a", "")    = "b"
    6341     * StringUtils.replace("aba", "a", "z")   = "zbz"
    6342     * </pre>
    6343     *
    6344     * @see #replace(String text, String searchString, String replacement, int max)
    6345     * @param text  text to search and replace in, may be null
    6346     * @param searchString  the String to search for, may be null
    6347     * @param replacement  the String to replace it with, may be null
    6348     * @return the text with any replacements processed,
    6349     *  {@code null} if null String input
    6350     */
    6351    public static String replace(final String text, final String searchString, final String replacement) {
    6352        return replace(text, searchString, replacement, -1);
    6353    }
    6354
    6355    /**
    6356     * <p>Replaces a String with another String inside a larger String,
    6357     * for the first {@code max} values of the search String.</p>
    6358     *
    6359     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6360     *
    6361     * <pre>
    6362     * StringUtils.replace(null, *, *, *)         = null
    6363     * StringUtils.replace("", *, *, *)           = ""
    6364     * StringUtils.replace("any", null, *, *)     = "any"
    6365     * StringUtils.replace("any", *, null, *)     = "any"
    6366     * StringUtils.replace("any", "", *, *)       = "any"
    6367     * StringUtils.replace("any", *, *, 0)        = "any"
    6368     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
    6369     * StringUtils.replace("abaa", "a", "", -1)   = "b"
    6370     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
    6371     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
    6372     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
    6373     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
    6374     * </pre>
    6375     *
    6376     * @param text  text to search and replace in, may be null
    6377     * @param searchString  the String to search for, may be null
    6378     * @param replacement  the String to replace it with, may be null
    6379     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6380     * @return the text with any replacements processed,
    6381     *  {@code null} if null String input
    6382     */
    6383    public static String replace(final String text, final String searchString, final String replacement, final int max) {
    6384        return replace(text, searchString, replacement, max, false);
    6385    }
    6386
    6387    /**
    6388     * <p>Replaces a String with another String inside a larger String,
    6389     * for the first {@code max} values of the search String,
    6390     * case sensitively/insensitively based on {@code ignoreCase} value.</p>
    6391     *
    6392     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6393     *
    6394     * <pre>
    6395     * StringUtils.replace(null, *, *, *, false)         = null
    6396     * StringUtils.replace("", *, *, *, false)           = ""
    6397     * StringUtils.replace("any", null, *, *, false)     = "any"
    6398     * StringUtils.replace("any", *, null, *, false)     = "any"
    6399     * StringUtils.replace("any", "", *, *, false)       = "any"
    6400     * StringUtils.replace("any", *, *, 0, false)        = "any"
    6401     * StringUtils.replace("abaa", "a", null, -1, false) = "abaa"
    6402     * StringUtils.replace("abaa", "a", "", -1, false)   = "b"
    6403     * StringUtils.replace("abaa", "a", "z", 0, false)   = "abaa"
    6404     * StringUtils.replace("abaa", "A", "z", 1, false)   = "abaa"
    6405     * StringUtils.replace("abaa", "A", "z", 1, true)   = "zbaa"
    6406     * StringUtils.replace("abAa", "a", "z", 2, true)   = "zbza"
    6407     * StringUtils.replace("abAa", "a", "z", -1, true)  = "zbzz"
    6408     * </pre>
    6409     *
    6410     * @param text  text to search and replace in, may be null
    6411     * @param searchString  the String to search for (case insensitive), may be null
    6412     * @param replacement  the String to replace it with, may be null
    6413     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6414     * @param ignoreCase if true replace is case insensitive, otherwise case sensitive
    6415     * @return the text with any replacements processed,
    6416     *  {@code null} if null String input
    6417     */
    6418     private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) {
    6419         if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
    6420             return text;
    6421         }
    6422         if (ignoreCase) {
    6423             searchString = searchString.toLowerCase();
    6424         }
    6425         int start = 0;
    6426         int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start);
    6427         if (end == INDEX_NOT_FOUND) {
    6428             return text;
    6429         }
    6430         final int replLength = searchString.length();
    6431         int increase = Math.max(replacement.length() - replLength, 0);
    6432         increase *= max < 0 ? 16 : Math.min(max, 64);
    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 recursing, this shouldn't be less than 0
    6695        if (timeToLive < 0) {
    6696            final Set<String> searchSet = new HashSet<>(Arrays.asList(searchList));
    6697            final Set<String> replacementSet = new HashSet<>(Arrays.asList(replacementList));
    6698            searchSet.retainAll(replacementSet);
    6699            if (searchSet.size() > 0) {
    6700                throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
    6701                        "output of one loop is the input of another");
    6702            }
    6703        }
    6704
    6705        if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList) || (ArrayUtils.isNotEmpty(searchList) && timeToLive == -1)) {
    6706            return text;
    6707        }
    6708
    6709        final int searchLength = searchList.length;
    6710        final int replacementLength = replacementList.length;
    6711
    6712        // make sure lengths are ok, these need to be equal
    6713        if (searchLength != replacementLength) {
    6714            throw new IllegalArgumentException("Search and Replace array lengths don't match: "
    6715                + searchLength
    6716                + " vs "
    6717                + replacementLength);
    6718        }
    6719
    6720        // keep track of which still have matches
    6721        final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
    6722
    6723        // index on index that the match was found
    6724        int textIndex = -1;
    6725        int replaceIndex = -1;
    6726        int tempIndex = -1;
    6727
    6728        // index of replace array that will replace the search string found
    6729        // NOTE: logic duplicated below START
    6730        for (int i = 0; i < searchLength; i++) {
    6731            if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
    6732                continue;
    6733            }
    6734            tempIndex = text.indexOf(searchList[i]);
    6735
    6736            // see if we need to keep searching for this
    6737            if (tempIndex == -1) {
    6738                noMoreMatchesForReplIndex[i] = true;
    6739            } else {
    6740                if (textIndex == -1 || tempIndex < textIndex) {
    6741                    textIndex = tempIndex;
    6742                    replaceIndex = i;
    6743                }
    6744            }
    6745        }
    6746        // NOTE: logic mostly below END
    6747
    6748        // no search strings found, we are done
    6749        if (textIndex == -1) {
    6750            return text;
    6751        }
    6752
    6753        int start = 0;
    6754
    6755        // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
    6756        int increase = 0;
    6757
    6758        // count the replacement text elements that are larger than their corresponding text being replaced
    6759        for (int i = 0; i < searchList.length; i++) {
    6760            if (searchList[i] == null || replacementList[i] == null) {
    6761                continue;
    6762            }
    6763            final int greater = replacementList[i].length() - searchList[i].length();
    6764            if (greater > 0) {
    6765                increase += 3 * greater; // assume 3 matches
    6766            }
    6767        }
    6768        // have upper-bound at 20% increase, then let Java take over
    6769        increase = Math.min(increase, text.length() / 5);
    6770
    6771        final StringBuilder buf = new StringBuilder(text.length() + increase);
    6772
    6773        while (textIndex != -1) {
    6774
    6775            for (int i = start; i < textIndex; i++) {
    6776                buf.append(text.charAt(i));
    6777            }
    6778            buf.append(replacementList[replaceIndex]);
    6779
    6780            start = textIndex + searchList[replaceIndex].length();
    6781
    6782            textIndex = -1;
    6783            replaceIndex = -1;
    6784            tempIndex = -1;
    6785            // find the next earliest match
    6786            // NOTE: logic mostly duplicated above START
    6787            for (int i = 0; i < searchLength; i++) {
    6788                if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
    6789                        searchList[i].isEmpty() || replacementList[i] == null) {
    6790                    continue;
    6791                }
    6792                tempIndex = text.indexOf(searchList[i], start);
    6793
    6794                // see if we need to keep searching for this
    6795                if (tempIndex == -1) {
    6796                    noMoreMatchesForReplIndex[i] = true;
    6797                } else {
    6798                    if (textIndex == -1 || tempIndex < textIndex) {
    6799                        textIndex = tempIndex;
    6800                        replaceIndex = i;
    6801                    }
    6802                }
    6803            }
    6804            // NOTE: logic duplicated above END
    6805
    6806        }
    6807        final int textLength = text.length();
    6808        for (int i = start; i < textLength; i++) {
    6809            buf.append(text.charAt(i));
    6810        }
    6811        final String result = buf.toString();
    6812        if (!repeat) {
    6813            return result;
    6814        }
    6815
    6816        return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
    6817    }
    6818
    6819    /**
    6820     * <p>
    6821     * Replaces all occurrences of Strings within another String.
    6822     * </p>
    6823     *
    6824     * <p>
    6825     * A {@code null} reference passed to this method is a no-op, or if
    6826     * any "search string" or "string to replace" is null, that replace will be
    6827     * ignored.
    6828     * </p>
    6829     *
    6830     * <pre>
    6831     *  StringUtils.replaceEachRepeatedly(null, *, *) = null
    6832     *  StringUtils.replaceEachRepeatedly("", *, *) = ""
    6833     *  StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
    6834     *  StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
    6835     *  StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
    6836     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
    6837     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
    6838     *  StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
    6839     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
    6840     *  (example of how it repeats)
    6841     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
    6842     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
    6843     * </pre>
    6844     *
    6845     * @param text
    6846     *            text to search and replace in, no-op if null
    6847     * @param searchList
    6848     *            the Strings to search for, no-op if null
    6849     * @param replacementList
    6850     *            the Strings to replace them with, no-op if null
    6851     * @return the text with any replacements processed, {@code null} if
    6852     *         null String input
    6853     * @throws IllegalStateException
    6854     *             if the search is repeating and there is an endless loop due
    6855     *             to outputs of one being inputs to another
    6856     * @throws IllegalArgumentException
    6857     *             if the lengths of the arrays are not the same (null is ok,
    6858     *             and/or size 0)
    6859     * @since 2.4
    6860     */
    6861    public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
    6862        // timeToLive should be 0 if not used or nothing to replace, else it's
    6863        // the length of the replace array
    6864        final int timeToLive = searchList == null ? 0 : searchList.length;
    6865        return replaceEach(text, searchList, replacementList, true, timeToLive);
    6866    }
    6867
    6868    /**
    6869     * <p>Replaces the first substring of the text string that matches the given regular expression
    6870     * with the given replacement.</p>
    6871     *
    6872     * This method is a {@code null} safe equivalent to:
    6873     * <ul>
    6874     *  <li>{@code text.replaceFirst(regex, replacement)}</li>
    6875     *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
    6876     * </ul>
    6877     *
    6878     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6879     *
    6880     * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
    6881     * To use the DOTALL option prepend {@code "(?s)"} to the regex.
    6882     * DOTALL is also known as single-line mode in Perl.</p>
    6883     *
    6884     * <pre>
    6885     * StringUtils.replaceFirst(null, *, *)       = null
    6886     * StringUtils.replaceFirst("any", (String) null, *)   = "any"
    6887     * StringUtils.replaceFirst("any", *, null)   = "any"
    6888     * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
    6889     * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
    6890     * StringUtils.replaceFirst("", ".+", "zzz")  = ""
    6891     * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
    6892     * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")      = "z\n&lt;__&gt;"
    6893     * StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;", "(?s)&lt;.*&gt;", "z")  = "z"
    6894     * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
    6895     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
    6896     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
    6897     * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
    6898     * </pre>
    6899     *
    6900     * @param text  text to search and replace in, may be null
    6901     * @param regex  the regular expression to which this string is to be matched
    6902     * @param replacement  the string to be substituted for the first match
    6903     * @return  the text with the first replacement processed,
    6904     *              {@code null} if null String input
    6905     *
    6906     * @throws  java.util.regex.PatternSyntaxException
    6907     *              if the regular expression's syntax is invalid
    6908     *
    6909     * @see String#replaceFirst(String, String)
    6910     * @see java.util.regex.Pattern
    6911     * @see java.util.regex.Pattern#DOTALL
    6912     * @since 3.5
    6913     *
    6914     * @deprecated Moved to RegExUtils.
    6915     */
    6916    @Deprecated
    6917    public static String replaceFirst(final String text, final String regex, final String replacement) {
    6918        return RegExUtils.replaceFirst(text, regex, replacement);
    6919    }
    6920
    6921    /**
    6922    * <p>Case insensitively replaces all occurrences of a String within another String.</p>
    6923    *
    6924    * <p>A {@code null} reference passed to this method is a no-op.</p>
    6925    *
    6926    * <pre>
    6927    * StringUtils.replaceIgnoreCase(null, *, *)        = null
    6928    * StringUtils.replaceIgnoreCase("", *, *)          = ""
    6929    * StringUtils.replaceIgnoreCase("any", null, *)    = "any"
    6930    * StringUtils.replaceIgnoreCase("any", *, null)    = "any"
    6931    * StringUtils.replaceIgnoreCase("any", "", *)      = "any"
    6932    * StringUtils.replaceIgnoreCase("aba", "a", null)  = "aba"
    6933    * StringUtils.replaceIgnoreCase("abA", "A", "")    = "b"
    6934    * StringUtils.replaceIgnoreCase("aba", "A", "z")   = "zbz"
    6935    * </pre>
    6936    *
    6937    * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
    6938    * @param text  text to search and replace in, may be null
    6939    * @param searchString  the String to search for (case insensitive), may be null
    6940    * @param replacement  the String to replace it with, may be null
    6941    * @return the text with any replacements processed,
    6942    *  {@code null} if null String input
    6943    * @since 3.5
    6944    */
    6945   public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
    6946       return replaceIgnoreCase(text, searchString, replacement, -1);
    6947   }
    6948
    6949    /**
    6950     * <p>Case insensitively replaces a String with another String inside a larger String,
    6951     * for the first {@code max} values of the search String.</p>
    6952     *
    6953     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6954     *
    6955     * <pre>
    6956     * StringUtils.replaceIgnoreCase(null, *, *, *)         = null
    6957     * StringUtils.replaceIgnoreCase("", *, *, *)           = ""
    6958     * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"
    6959     * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"
    6960     * StringUtils.replaceIgnoreCase("any", "", *, *)       = "any"
    6961     * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"
    6962     * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
    6963     * StringUtils.replaceIgnoreCase("abaa", "a", "", -1)   = "b"
    6964     * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0)   = "abaa"
    6965     * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1)   = "zbaa"
    6966     * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2)   = "zbza"
    6967     * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1)  = "zbzz"
    6968     * </pre>
    6969     *
    6970     * @param text  text to search and replace in, may be null
    6971     * @param searchString  the String to search for (case insensitive), may be null
    6972     * @param replacement  the String to replace it with, may be null
    6973     * @param max  maximum number of values to replace, or {@code -1} if no maximum
    6974     * @return the text with any replacements processed,
    6975     *  {@code null} if null String input
    6976     * @since 3.5
    6977     */
    6978    public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
    6979        return replace(text, searchString, replacement, max, true);
    6980    }
    6981
    6982    // Replacing
    6983    //-----------------------------------------------------------------------
    6984    /**
    6985     * <p>Replaces a String with another String inside a larger String, once.</p>
    6986     *
    6987     * <p>A {@code null} reference passed to this method is a no-op.</p>
    6988     *
    6989     * <pre>
    6990     * StringUtils.replaceOnce(null, *, *)        = null
    6991     * StringUtils.replaceOnce("", *, *)          = ""
    6992     * StringUtils.replaceOnce("any", null, *)    = "any"
    6993     * StringUtils.replaceOnce("any", *, null)    = "any"
    6994     * StringUtils.replaceOnce("any", "", *)      = "any"
    6995     * StringUtils.replaceOnce("aba", "a", null)  = "aba"
    6996     * StringUtils.replaceOnce("aba", "a", "")    = "ba"
    6997     * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
    6998     * </pre>
    6999     *
    7000     * @see #replace(String text, String searchString, String replacement, int max)
    7001     * @param text  text to search and replace in, may be null
    7002     * @param searchString  the String to search for, may be null
    7003     * @param replacement  the String to replace with, may be null
    7004     * @return the text with any replacements processed,
    7005     *  {@code null} if null String input
    7006     */
    7007    public static String replaceOnce(final String text, final String searchString, final String replacement) {
    7008        return replace(text, searchString, replacement, 1);
    7009    }
    7010
    7011    /**
    7012     * <p>Case insensitively replaces a String with another String inside a larger String, once.</p>
    7013     *
    7014     * <p>A {@code null} reference passed to this method is a no-op.</p>
    7015     *
    7016     * <pre>
    7017     * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null
    7018     * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""
    7019     * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"
    7020     * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"
    7021     * StringUtils.replaceOnceIgnoreCase("any", "", *)      = "any"
    7022     * StringUtils.replaceOnceIgnoreCase("aba", "a", null)  = "aba"
    7023     * StringUtils.replaceOnceIgnoreCase("aba", "a", "")    = "ba"
    7024     * StringUtils.replaceOnceIgnoreCase("aba", "a", "z")   = "zba"
    7025     * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
    7026     * </pre>
    7027     *
    7028     * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
    7029     * @param text  text to search and replace in, may be null
    7030     * @param searchString  the String to search for (case insensitive), may be null
    7031     * @param replacement  the String to replace with, may be null
    7032     * @return the text with any replacements processed,
    7033     *  {@code null} if null String input
    7034     * @since 3.5
    7035     */
    7036    public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
    7037        return replaceIgnoreCase(text, searchString, replacement, 1);
    7038    }
    7039
    7040    /**
    7041     * <p>Replaces each substring of the source String that matches the given regular expression with the given
    7042     * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.</p>
    7043     *
    7044     * This call is a {@code null} safe equivalent to:
    7045     * <ul>
    7046     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
    7047     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
    7048     * </ul>
    7049     *
    7050     * <p>A {@code null} reference passed to this method is a no-op.</p>
    7051     *
    7052     * <pre>
    7053     * StringUtils.replacePattern(null, *, *)       = null
    7054     * StringUtils.replacePattern("any", (String) null, *)   = "any"
    7055     * StringUtils.replacePattern("any", *, null)   = "any"
    7056     * StringUtils.replacePattern("", "", "zzz")    = "zzz"
    7057     * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
    7058     * StringUtils.replacePattern("", ".+", "zzz")  = ""
    7059     * StringUtils.replacePattern("&lt;__&gt;\n&lt;__&gt;", "&lt;.*&gt;", "z")       = "z"
    7060     * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
    7061     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
    7062     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
    7063     * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
    7064     * </pre>
    7065     *
    7066     * @param source
    7067     *            the source string
    7068     * @param regex
    7069     *            the regular expression to which this string is to be matched
    7070     * @param replacement
    7071     *            the string to be substituted for each match
    7072     * @return The resulting {@code String}
    7073     * @see #replaceAll(String, String, String)
    7074     * @see String#replaceAll(String, String)
    7075     * @see Pattern#DOTALL
    7076     * @since 3.2
    7077     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
    7078     *
    7079     * @deprecated Moved to RegExUtils.
    7080     */
    7081    @Deprecated
    7082    public static String replacePattern(final String source, final String regex, final String replacement) {
    7083        return RegExUtils.replacePattern(source, regex, replacement);
    7084    }
    7085
    7086    // Reversing
    7087    //-----------------------------------------------------------------------
    7088    /**
    7089     * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p>
    7090     *
    7091     * <p>A {@code null} String returns {@code null}.</p>
    7092     *
    7093     * <pre>
    7094     * StringUtils.reverse(null)  = null
    7095     * StringUtils.reverse("")    = ""
    7096     * StringUtils.reverse("bat") = "tab"
    7097     * </pre>
    7098     *
    7099     * @param str  the String to reverse, may be null
    7100     * @return the reversed String, {@code null} if null String input
    7101     */
    7102    public static String reverse(final String str) {
    7103        if (str == null) {
    7104            return null;
    7105        }
    7106        return new StringBuilder(str).reverse().toString();
    7107    }
    7108
    7109    /**
    7110     * <p>Reverses a String that is delimited by a specific character.</p>
    7111     *
    7112     * <p>The Strings between the delimiters are not reversed.
    7113     * Thus java.lang.String becomes String.lang.java (if the delimiter
    7114     * is {@code '.'}).</p>
    7115     *
    7116     * <pre>
    7117     * StringUtils.reverseDelimited(null, *)      = null
    7118     * StringUtils.reverseDelimited("", *)        = ""
    7119     * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
    7120     * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
    7121     * </pre>
    7122     *
    7123     * @param str  the String to reverse, may be null
    7124     * @param separatorChar  the separator character to use
    7125     * @return the reversed String, {@code null} if null String input
    7126     * @since 2.0
    7127     */
    7128    public static String reverseDelimited(final String str, final char separatorChar) {
    7129        if (str == null) {
    7130            return null;
    7131        }
    7132        // could implement manually, but simple way is to reuse other,
    7133        // probably slower, methods.
    7134        final String[] strs = split(str, separatorChar);
    7135        ArrayUtils.reverse(strs);
    7136        return join(strs, separatorChar);
    7137    }
    7138
    7139    /**
    7140     * <p>Gets the rightmost {@code len} characters of a String.</p>
    7141     *
    7142     * <p>If {@code len} characters are not available, or the String
    7143     * is {@code null}, the String will be returned without an
    7144     * an exception. An empty String is returned if len is negative.</p>
    7145     *
    7146     * <pre>
    7147     * StringUtils.right(null, *)    = null
    7148     * StringUtils.right(*, -ve)     = ""
    7149     * StringUtils.right("", *)      = ""
    7150     * StringUtils.right("abc", 0)   = ""
    7151     * StringUtils.right("abc", 2)   = "bc"
    7152     * StringUtils.right("abc", 4)   = "abc"
    7153     * </pre>
    7154     *
    7155     * @param str  the String to get the rightmost characters from, may be null
    7156     * @param len  the length of the required String
    7157     * @return the rightmost characters, {@code null} if null String input
    7158     */
    7159    public static String right(final String str, final int len) {
    7160        if (str == null) {
    7161            return null;
    7162        }
    7163        if (len < 0) {
    7164            return EMPTY;
    7165        }
    7166        if (str.length() <= len) {
    7167            return str;
    7168        }
    7169        return str.substring(str.length() - len);
    7170    }
    7171
    7172    /**
    7173     * <p>Right pad a String with spaces (' ').</p>
    7174     *
    7175     * <p>The String is padded to the size of {@code size}.</p>
    7176     *
    7177     * <pre>
    7178     * StringUtils.rightPad(null, *)   = null
    7179     * StringUtils.rightPad("", 3)     = "   "
    7180     * StringUtils.rightPad("bat", 3)  = "bat"
    7181     * StringUtils.rightPad("bat", 5)  = "bat  "
    7182     * StringUtils.rightPad("bat", 1)  = "bat"
    7183     * StringUtils.rightPad("bat", -1) = "bat"
    7184     * </pre>
    7185     *
    7186     * @param str  the String to pad out, may be null
    7187     * @param size  the size to pad to
    7188     * @return right padded String or original String if no padding is necessary,
    7189     *  {@code null} if null String input
    7190     */
    7191    public static String rightPad(final String str, final int size) {
    7192        return rightPad(str, size, ' ');
    7193    }
    7194
    7195    /**
    7196     * <p>Right pad a String with a specified character.</p>
    7197     *
    7198     * <p>The String is padded to the size of {@code size}.</p>
    7199     *
    7200     * <pre>
    7201     * StringUtils.rightPad(null, *, *)     = null
    7202     * StringUtils.rightPad("", 3, 'z')     = "zzz"
    7203     * StringUtils.rightPad("bat", 3, 'z')  = "bat"
    7204     * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
    7205     * StringUtils.rightPad("bat", 1, 'z')  = "bat"
    7206     * StringUtils.rightPad("bat", -1, 'z') = "bat"
    7207     * </pre>
    7208     *
    7209     * @param str  the String to pad out, may be null
    7210     * @param size  the size to pad to
    7211     * @param padChar  the character to pad with
    7212     * @return right padded String or original String if no padding is necessary,
    7213     *  {@code null} if null String input
    7214     * @since 2.0
    7215     */
    7216    public static String rightPad(final String str, final int size, final char padChar) {
    7217        if (str == null) {
    7218            return null;
    7219        }
    7220        final int pads = size - str.length();
    7221        if (pads <= 0) {
    7222            return str; // returns original String when possible
    7223        }
    7224        if (pads > PAD_LIMIT) {
    7225            return rightPad(str, size, String.valueOf(padChar));
    7226        }
    7227        return str.concat(repeat(padChar, pads));
    7228    }
    7229
    7230    /**
    7231     * <p>Right pad a String with a specified String.</p>
    7232     *
    7233     * <p>The String is padded to the size of {@code size}.</p>
    7234     *
    7235     * <pre>
    7236     * StringUtils.rightPad(null, *, *)      = null
    7237     * StringUtils.rightPad("", 3, "z")      = "zzz"
    7238     * StringUtils.rightPad("bat", 3, "yz")  = "bat"
    7239     * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
    7240     * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
    7241     * StringUtils.rightPad("bat", 1, "yz")  = "bat"
    7242     * StringUtils.rightPad("bat", -1, "yz") = "bat"
    7243     * StringUtils.rightPad("bat", 5, null)  = "bat  "
    7244     * StringUtils.rightPad("bat", 5, "")    = "bat  "
    7245     * </pre>
    7246     *
    7247     * @param str  the String to pad out, may be null
    7248     * @param size  the size to pad to
    7249     * @param padStr  the String to pad with, null or empty treated as single space
    7250     * @return right padded String or original String if no padding is necessary,
    7251     *  {@code null} if null String input
    7252     */
    7253    public static String rightPad(final String str, final int size, String padStr) {
    7254        if (str == null) {
    7255            return null;
    7256        }
    7257        if (isEmpty(padStr)) {
    7258            padStr = SPACE;
    7259        }
    7260        final int padLen = padStr.length();
    7261        final int strLen = str.length();
    7262        final int pads = size - strLen;
    7263        if (pads <= 0) {
    7264            return str; // returns original String when possible
    7265        }
    7266        if (padLen == 1 && pads <= PAD_LIMIT) {
    7267            return rightPad(str, size, padStr.charAt(0));
    7268        }
    7269
    7270        if (pads == padLen) {
    7271            return str.concat(padStr);
    7272        } else if (pads < padLen) {
    7273            return str.concat(padStr.substring(0, pads));
    7274        } else {
    7275            final char[] padding = new char[pads];
    7276            final char[] padChars = padStr.toCharArray();
    7277            for (int i = 0; i < pads; i++) {
    7278                padding[i] = padChars[i % padLen];
    7279            }
    7280            return str.concat(new String(padding));
    7281        }
    7282    }
    7283
    7284    // Rotating (circular shift)
    7285    //-----------------------------------------------------------------------
    7286    /**
    7287     * <p>Rotate (circular shift) a String of {@code shift} characters.</p>
    7288     * <ul>
    7289     *  <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
    7290     *  <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
    7291     * </ul>
    7292     *
    7293     * <pre>
    7294     * StringUtils.rotate(null, *)        = null
    7295     * StringUtils.rotate("", *)          = ""
    7296     * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
    7297     * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
    7298     * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
    7299     * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
    7300     * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
    7301     * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
    7302     * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
    7303     * </pre>
    7304     *
    7305     * @param str  the String to rotate, may be null
    7306     * @param shift  number of time to shift (positive : right shift, negative : left shift)
    7307     * @return the rotated String,
    7308     *          or the original String if {@code shift == 0},
    7309     *          or {@code null} if null String input
    7310     * @since 3.5
    7311     */
    7312    public static String rotate(final String str, final int shift) {
    7313        if (str == null) {
    7314            return null;
    7315        }
    7316
    7317        final int strLen = str.length();
    7318        if (shift == 0 || strLen == 0 || shift % strLen == 0) {
    7319            return str;
    7320        }
    7321
    7322        final StringBuilder builder = new StringBuilder(strLen);
    7323        final int offset = - (shift % strLen);
    7324        builder.append(substring(str, offset));
    7325        builder.append(substring(str, 0, offset));
    7326        return builder.toString();
    7327    }
    7328
    7329    // Splitting
    7330    //-----------------------------------------------------------------------
    7331    /**
    7332     * <p>Splits the provided text into an array, using whitespace as the
    7333     * separator.
    7334     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    7335     *
    7336     * <p>The separator is not included in the returned String array.
    7337     * Adjacent separators are treated as one separator.
    7338     * For more control over the split use the StrTokenizer class.</p>
    7339     *
    7340     * <p>A {@code null} input String returns {@code null}.</p>
    7341     *
    7342     * <pre>
    7343     * StringUtils.split(null)       = null
    7344     * StringUtils.split("")         = []
    7345     * StringUtils.split("abc def")  = ["abc", "def"]
    7346     * StringUtils.split("abc  def") = ["abc", "def"]
    7347     * StringUtils.split(" abc ")    = ["abc"]
    7348     * </pre>
    7349     *
    7350     * @param str  the String to parse, may be null
    7351     * @return an array of parsed Strings, {@code null} if null String input
    7352     */
    7353    public static String[] split(final String str) {
    7354        return split(str, null, -1);
    7355    }
    7356
    7357    /**
    7358     * <p>Splits the provided text into an array, separator specified.
    7359     * This is an alternative to using StringTokenizer.</p>
    7360     *
    7361     * <p>The separator is not included in the returned String array.
    7362     * Adjacent separators are treated as one separator.
    7363     * For more control over the split use the StrTokenizer class.</p>
    7364     *
    7365     * <p>A {@code null} input String returns {@code null}.</p>
    7366     *
    7367     * <pre>
    7368     * StringUtils.split(null, *)         = null
    7369     * StringUtils.split("", *)           = []
    7370     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
    7371     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
    7372     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
    7373     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
    7374     * </pre>
    7375     *
    7376     * @param str  the String to parse, may be null
    7377     * @param separatorChar  the character used as the delimiter
    7378     * @return an array of parsed Strings, {@code null} if null String input
    7379     * @since 2.0
    7380     */
    7381    public static String[] split(final String str, final char separatorChar) {
    7382        return splitWorker(str, separatorChar, false);
    7383    }
    7384
    7385    /**
    7386     * <p>Splits the provided text into an array, separators specified.
    7387     * This is an alternative to using StringTokenizer.</p>
    7388     *
    7389     * <p>The separator is not included in the returned String array.
    7390     * Adjacent separators are treated as one separator.
    7391     * For more control over the split use the StrTokenizer class.</p>
    7392     *
    7393     * <p>A {@code null} input String returns {@code null}.
    7394     * A {@code null} separatorChars splits on whitespace.</p>
    7395     *
    7396     * <pre>
    7397     * StringUtils.split(null, *)         = null
    7398     * StringUtils.split("", *)           = []
    7399     * StringUtils.split("abc def", null) = ["abc", "def"]
    7400     * StringUtils.split("abc def", " ")  = ["abc", "def"]
    7401     * StringUtils.split("abc  def", " ") = ["abc", "def"]
    7402     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
    7403     * </pre>
    7404     *
    7405     * @param str  the String to parse, may be null
    7406     * @param separatorChars  the characters used as the delimiters,
    7407     *  {@code null} splits on whitespace
    7408     * @return an array of parsed Strings, {@code null} if null String input
    7409     */
    7410    public static String[] split(final String str, final String separatorChars) {
    7411        return splitWorker(str, separatorChars, -1, false);
    7412    }
    7413
    7414    /**
    7415     * <p>Splits the provided text into an array with a maximum length,
    7416     * separators specified.</p>
    7417     *
    7418     * <p>The separator is not included in the returned String array.
    7419     * Adjacent separators are treated as one separator.</p>
    7420     *
    7421     * <p>A {@code null} input String returns {@code null}.
    7422     * A {@code null} separatorChars splits on whitespace.</p>
    7423     *
    7424     * <p>If more than {@code max} delimited substrings are found, the last
    7425     * returned string includes all characters after the first {@code max - 1}
    7426     * returned strings (including separator characters).</p>
    7427     *
    7428     * <pre>
    7429     * StringUtils.split(null, *, *)            = null
    7430     * StringUtils.split("", *, *)              = []
    7431     * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd", "ef"]
    7432     * StringUtils.split("ab   cd ef", null, 0) = ["ab", "cd", "ef"]
    7433     * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    7434     * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    7435     * </pre>
    7436     *
    7437     * @param str  the String to parse, may be null
    7438     * @param separatorChars  the characters used as the delimiters,
    7439     *  {@code null} splits on whitespace
    7440     * @param max  the maximum number of elements to include in the
    7441     *  array. A zero or negative value implies no limit
    7442     * @return an array of parsed Strings, {@code null} if null String input
    7443     */
    7444    public static String[] split(final String str, final String separatorChars, final int max) {
    7445        return splitWorker(str, separatorChars, max, false);
    7446    }
    7447
    7448    /**
    7449     * <p>Splits a String by Character type as returned by
    7450     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7451     * characters of the same type are returned as complete tokens.
    7452     * <pre>
    7453     * StringUtils.splitByCharacterType(null)         = null
    7454     * StringUtils.splitByCharacterType("")           = []
    7455     * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    7456     * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    7457     * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    7458     * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
    7459     * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
    7460     * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
    7461     * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
    7462     * </pre>
    7463     * @param str the String to split, may be {@code null}
    7464     * @return an array of parsed Strings, {@code null} if null String input
    7465     * @since 2.4
    7466     */
    7467    public static String[] splitByCharacterType(final String str) {
    7468        return splitByCharacterType(str, false);
    7469    }
    7470
    7471    /**
    7472     * <p>Splits a String by Character type as returned by
    7473     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7474     * characters of the same type are returned as complete tokens, with the
    7475     * following exception: if {@code camelCase} is {@code true},
    7476     * the character of type {@code Character.UPPERCASE_LETTER}, if any,
    7477     * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
    7478     * will belong to the following token rather than to the preceding, if any,
    7479     * {@code Character.UPPERCASE_LETTER} token.
    7480     * @param str the String to split, may be {@code null}
    7481     * @param camelCase whether to use so-called "camel-case" for letter types
    7482     * @return an array of parsed Strings, {@code null} if null String input
    7483     * @since 2.4
    7484     */
    7485    private static String[] splitByCharacterType(final String str, final boolean camelCase) {
    7486        if (str == null) {
    7487            return null;
    7488        }
    7489        if (str.isEmpty()) {
    7490            return ArrayUtils.EMPTY_STRING_ARRAY;
    7491        }
    7492        final char[] c = str.toCharArray();
    7493        final List<String> list = new ArrayList<>();
    7494        int tokenStart = 0;
    7495        int currentType = Character.getType(c[tokenStart]);
    7496        for (int pos = tokenStart + 1; pos < c.length; pos++) {
    7497            final int type = Character.getType(c[pos]);
    7498            if (type == currentType) {
    7499                continue;
    7500            }
    7501            if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
    7502                final int newTokenStart = pos - 1;
    7503                if (newTokenStart != tokenStart) {
    7504                    list.add(new String(c, tokenStart, newTokenStart - tokenStart));
    7505                    tokenStart = newTokenStart;
    7506                }
    7507            } else {
    7508                list.add(new String(c, tokenStart, pos - tokenStart));
    7509                tokenStart = pos;
    7510            }
    7511            currentType = type;
    7512        }
    7513        list.add(new String(c, tokenStart, c.length - tokenStart));
    7514        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7515    }
    7516
    7517    /**
    7518     * <p>Splits a String by Character type as returned by
    7519     * {@code java.lang.Character.getType(char)}. Groups of contiguous
    7520     * characters of the same type are returned as complete tokens, with the
    7521     * following exception: the character of type
    7522     * {@code Character.UPPERCASE_LETTER}, if any, immediately
    7523     * preceding a token of type {@code Character.LOWERCASE_LETTER}
    7524     * will belong to the following token rather than to the preceding, if any,
    7525     * {@code Character.UPPERCASE_LETTER} token.
    7526     * <pre>
    7527     * StringUtils.splitByCharacterTypeCamelCase(null)         = null
    7528     * StringUtils.splitByCharacterTypeCamelCase("")           = []
    7529     * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
    7530     * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
    7531     * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
    7532     * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
    7533     * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
    7534     * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
    7535     * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
    7536     * </pre>
    7537     * @param str the String to split, may be {@code null}
    7538     * @return an array of parsed Strings, {@code null} if null String input
    7539     * @since 2.4
    7540     */
    7541    public static String[] splitByCharacterTypeCamelCase(final String str) {
    7542        return splitByCharacterType(str, true);
    7543    }
    7544
    7545    /**
    7546     * <p>Splits the provided text into an array, separator string specified.</p>
    7547     *
    7548     * <p>The separator(s) will not be included in the returned String array.
    7549     * Adjacent separators are treated as one separator.</p>
    7550     *
    7551     * <p>A {@code null} input String returns {@code null}.
    7552     * A {@code null} separator splits on whitespace.</p>
    7553     *
    7554     * <pre>
    7555     * StringUtils.splitByWholeSeparator(null, *)               = null
    7556     * StringUtils.splitByWholeSeparator("", *)                 = []
    7557     * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
    7558     * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
    7559     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    7560     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    7561     * </pre>
    7562     *
    7563     * @param str  the String to parse, may be null
    7564     * @param separator  String containing the String to be used as a delimiter,
    7565     *  {@code null} splits on whitespace
    7566     * @return an array of parsed Strings, {@code null} if null String was input
    7567     */
    7568    public static String[] splitByWholeSeparator(final String str, final String separator) {
    7569        return splitByWholeSeparatorWorker(str, separator, -1, false);
    7570    }
    7571
    7572    /**
    7573     * <p>Splits the provided text into an array, separator string specified.
    7574     * Returns a maximum of {@code max} substrings.</p>
    7575     *
    7576     * <p>The separator(s) will not be included in the returned String array.
    7577     * Adjacent separators are treated as one separator.</p>
    7578     *
    7579     * <p>A {@code null} input String returns {@code null}.
    7580     * A {@code null} separator splits on whitespace.</p>
    7581     *
    7582     * <pre>
    7583     * StringUtils.splitByWholeSeparator(null, *, *)               = null
    7584     * StringUtils.splitByWholeSeparator("", *, *)                 = []
    7585     * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
    7586     * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
    7587     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    7588     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    7589     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    7590     * </pre>
    7591     *
    7592     * @param str  the String to parse, may be null
    7593     * @param separator  String containing the String to be used as a delimiter,
    7594     *  {@code null} splits on whitespace
    7595     * @param max  the maximum number of elements to include in the returned
    7596     *  array. A zero or negative value implies no limit.
    7597     * @return an array of parsed Strings, {@code null} if null String was input
    7598     */
    7599    public static String[] splitByWholeSeparator( final String str, final String separator, final int max) {
    7600        return splitByWholeSeparatorWorker(str, separator, max, false);
    7601    }
    7602
    7603    /**
    7604     * <p>Splits the provided text into an array, separator string specified. </p>
    7605     *
    7606     * <p>The separator is not included in the returned String array.
    7607     * Adjacent separators are treated as separators for empty tokens.
    7608     * For more control over the split use the StrTokenizer class.</p>
    7609     *
    7610     * <p>A {@code null} input String returns {@code null}.
    7611     * A {@code null} separator splits on whitespace.</p>
    7612     *
    7613     * <pre>
    7614     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
    7615     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
    7616     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
    7617     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
    7618     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
    7619     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
    7620     * </pre>
    7621     *
    7622     * @param str  the String to parse, may be null
    7623     * @param separator  String containing the String to be used as a delimiter,
    7624     *  {@code null} splits on whitespace
    7625     * @return an array of parsed Strings, {@code null} if null String was input
    7626     * @since 2.4
    7627     */
    7628    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
    7629        return splitByWholeSeparatorWorker(str, separator, -1, true);
    7630    }
    7631
    7632    /**
    7633     * <p>Splits the provided text into an array, separator string specified.
    7634     * Returns a maximum of {@code max} substrings.</p>
    7635     *
    7636     * <p>The separator is not included in the returned String array.
    7637     * Adjacent separators are treated as separators for empty tokens.
    7638     * For more control over the split use the StrTokenizer class.</p>
    7639     *
    7640     * <p>A {@code null} input String returns {@code null}.
    7641     * A {@code null} separator splits on whitespace.</p>
    7642     *
    7643     * <pre>
    7644     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
    7645     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
    7646     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
    7647     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
    7648     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
    7649     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
    7650     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
    7651     * </pre>
    7652     *
    7653     * @param str  the String to parse, may be null
    7654     * @param separator  String containing the String to be used as a delimiter,
    7655     *  {@code null} splits on whitespace
    7656     * @param max  the maximum number of elements to include in the returned
    7657     *  array. A zero or negative value implies no limit.
    7658     * @return an array of parsed Strings, {@code null} if null String was input
    7659     * @since 2.4
    7660     */
    7661    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
    7662        return splitByWholeSeparatorWorker(str, separator, max, true);
    7663    }
    7664
    7665    /**
    7666     * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
    7667     *
    7668     * @param str  the String to parse, may be {@code null}
    7669     * @param separator  String containing the String to be used as a delimiter,
    7670     *  {@code null} splits on whitespace
    7671     * @param max  the maximum number of elements to include in the returned
    7672     *  array. A zero or negative value implies no limit.
    7673     * @param preserveAllTokens if {@code true}, adjacent separators are
    7674     * treated as empty token separators; if {@code false}, adjacent
    7675     * separators are treated as one separator.
    7676     * @return an array of parsed Strings, {@code null} if null String input
    7677     * @since 2.4
    7678     */
    7679    private static String[] splitByWholeSeparatorWorker(
    7680            final String str, final String separator, final int max, final boolean preserveAllTokens) {
    7681        if (str == null) {
    7682            return null;
    7683        }
    7684
    7685        final int len = str.length();
    7686
    7687        if (len == 0) {
    7688            return ArrayUtils.EMPTY_STRING_ARRAY;
    7689        }
    7690
    7691        if (separator == null || EMPTY.equals(separator)) {
    7692            // Split on whitespace.
    7693            return splitWorker(str, null, max, preserveAllTokens);
    7694        }
    7695
    7696        final int separatorLength = separator.length();
    7697
    7698        final ArrayList<String> substrings = new ArrayList<>();
    7699        int numberOfSubstrings = 0;
    7700        int beg = 0;
    7701        int end = 0;
    7702        while (end < len) {
    7703            end = str.indexOf(separator, beg);
    7704
    7705            if (end > -1) {
    7706                if (end > beg) {
    7707                    numberOfSubstrings += 1;
    7708
    7709                    if (numberOfSubstrings == max) {
    7710                        end = len;
    7711                        substrings.add(str.substring(beg));
    7712                    } else {
    7713                        // The following is OK, because String.substring( beg, end ) excludes
    7714                        // the character at the position 'end'.
    7715                        substrings.add(str.substring(beg, end));
    7716
    7717                        // Set the starting point for the next search.
    7718                        // The following is equivalent to beg = end + (separatorLength - 1) + 1,
    7719                        // which is the right calculation:
    7720                        beg = end + separatorLength;
    7721                    }
    7722                } else {
    7723                    // We found a consecutive occurrence of the separator, so skip it.
    7724                    if (preserveAllTokens) {
    7725                        numberOfSubstrings += 1;
    7726                        if (numberOfSubstrings == max) {
    7727                            end = len;
    7728                            substrings.add(str.substring(beg));
    7729                        } else {
    7730                            substrings.add(EMPTY);
    7731                        }
    7732                    }
    7733                    beg = end + separatorLength;
    7734                }
    7735            } else {
    7736                // String.substring( beg ) goes from 'beg' to the end of the String.
    7737                substrings.add(str.substring(beg));
    7738                end = len;
    7739            }
    7740        }
    7741
    7742        return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7743    }
    7744
    7745    // -----------------------------------------------------------------------
    7746    /**
    7747     * <p>Splits the provided text into an array, using whitespace as the
    7748     * separator, preserving all tokens, including empty tokens created by
    7749     * adjacent separators. This is an alternative to using StringTokenizer.
    7750     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    7751     *
    7752     * <p>The separator is not included in the returned String array.
    7753     * Adjacent separators are treated as separators for empty tokens.
    7754     * For more control over the split use the StrTokenizer class.</p>
    7755     *
    7756     * <p>A {@code null} input String returns {@code null}.</p>
    7757     *
    7758     * <pre>
    7759     * StringUtils.splitPreserveAllTokens(null)       = null
    7760     * StringUtils.splitPreserveAllTokens("")         = []
    7761     * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
    7762     * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
    7763     * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
    7764     * </pre>
    7765     *
    7766     * @param str  the String to parse, may be {@code null}
    7767     * @return an array of parsed Strings, {@code null} if null String input
    7768     * @since 2.1
    7769     */
    7770    public static String[] splitPreserveAllTokens(final String str) {
    7771        return splitWorker(str, null, -1, true);
    7772    }
    7773
    7774    /**
    7775     * <p>Splits the provided text into an array, separator specified,
    7776     * preserving all tokens, including empty tokens created by adjacent
    7777     * separators. This is an alternative to using StringTokenizer.</p>
    7778     *
    7779     * <p>The separator is not included in the returned String array.
    7780     * Adjacent separators are treated as separators for empty tokens.
    7781     * For more control over the split use the StrTokenizer class.</p>
    7782     *
    7783     * <p>A {@code null} input String returns {@code null}.</p>
    7784     *
    7785     * <pre>
    7786     * StringUtils.splitPreserveAllTokens(null, *)         = null
    7787     * StringUtils.splitPreserveAllTokens("", *)           = []
    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\tb\nc", null) = ["a", "b", "c"]
    7792     * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
    7793     * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
    7794     * StringUtils.splitPreserveAllTokens("a b c  ", ' ')   = ["a", "b", "c", "", ""]
    7795     * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b", "c"]
    7796     * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a", "b", "c"]
    7797     * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b", "c", ""]
    7798     * </pre>
    7799     *
    7800     * @param str  the String to parse, may be {@code null}
    7801     * @param separatorChar  the character used as the delimiter,
    7802     *  {@code null} splits on whitespace
    7803     * @return an array of parsed Strings, {@code null} if null String input
    7804     * @since 2.1
    7805     */
    7806    public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
    7807        return splitWorker(str, separatorChar, true);
    7808    }
    7809
    7810    /**
    7811     * <p>Splits the provided text into an array, separators specified,
    7812     * preserving all tokens, including empty tokens created by adjacent
    7813     * separators. This is an alternative to using StringTokenizer.</p>
    7814     *
    7815     * <p>The separator is not included in the returned String array.
    7816     * Adjacent separators are treated as separators for empty tokens.
    7817     * For more control over the split use the StrTokenizer class.</p>
    7818     *
    7819     * <p>A {@code null} input String returns {@code null}.
    7820     * A {@code null} separatorChars splits on whitespace.</p>
    7821     *
    7822     * <pre>
    7823     * StringUtils.splitPreserveAllTokens(null, *)           = null
    7824     * StringUtils.splitPreserveAllTokens("", *)             = []
    7825     * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
    7826     * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
    7827     * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]
    7828     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
    7829     * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
    7830     * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
    7831     * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", cd", "ef"]
    7832     * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", cd", "ef"]
    7833     * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", cd", "ef"]
    7834     * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", cd", "ef", ""]
    7835     * </pre>
    7836     *
    7837     * @param str  the String to parse, may be {@code null}
    7838     * @param separatorChars  the characters used as the delimiters,
    7839     *  {@code null} splits on whitespace
    7840     * @return an array of parsed Strings, {@code null} if null String input
    7841     * @since 2.1
    7842     */
    7843    public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
    7844        return splitWorker(str, separatorChars, -1, true);
    7845    }
    7846
    7847    /**
    7848     * <p>Splits the provided text into an array with a maximum length,
    7849     * separators specified, preserving all tokens, including empty tokens
    7850     * created by adjacent separators.</p>
    7851     *
    7852     * <p>The separator is not included in the returned String array.
    7853     * Adjacent separators are treated as separators for empty tokens.
    7854     * Adjacent separators are treated as one separator.</p>
    7855     *
    7856     * <p>A {@code null} input String returns {@code null}.
    7857     * A {@code null} separatorChars splits on whitespace.</p>
    7858     *
    7859     * <p>If more than {@code max} delimited substrings are found, the last
    7860     * returned string includes all characters after the first {@code max - 1}
    7861     * returned strings (including separator characters).</p>
    7862     *
    7863     * <pre>
    7864     * StringUtils.splitPreserveAllTokens(null, *, *)            = null
    7865     * StringUtils.splitPreserveAllTokens("", *, *)              = []
    7866     * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "de", "fg"]
    7867     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "", "", "de", "fg"]
    7868     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
    7869     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
    7870     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
    7871     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
    7872     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
    7873     * </pre>
    7874     *
    7875     * @param str  the String to parse, may be {@code null}
    7876     * @param separatorChars  the characters used as the delimiters,
    7877     *  {@code null} splits on whitespace
    7878     * @param max  the maximum number of elements to include in the
    7879     *  array. A zero or negative value implies no limit
    7880     * @return an array of parsed Strings, {@code null} if null String input
    7881     * @since 2.1
    7882     */
    7883    public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
    7884        return splitWorker(str, separatorChars, max, true);
    7885    }
    7886
    7887    /**
    7888     * Performs the logic for the {@code split} and
    7889     * {@code splitPreserveAllTokens} methods that do not return a
    7890     * maximum array length.
    7891     *
    7892     * @param str  the String to parse, may be {@code null}
    7893     * @param separatorChar the separate character
    7894     * @param preserveAllTokens if {@code true}, adjacent separators are
    7895     * treated as empty token separators; if {@code false}, adjacent
    7896     * separators are treated as one separator.
    7897     * @return an array of parsed Strings, {@code null} if null String input
    7898     */
    7899    private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
    7900        // Performance tuned for 2.0 (JDK1.4)
    7901
    7902        if (str == null) {
    7903            return null;
    7904        }
    7905        final int len = str.length();
    7906        if (len == 0) {
    7907            return ArrayUtils.EMPTY_STRING_ARRAY;
    7908        }
    7909        final List<String> list = new ArrayList<>();
    7910        int i = 0, start = 0;
    7911        boolean match = false;
    7912        boolean lastMatch = false;
    7913        while (i < len) {
    7914            if (str.charAt(i) == separatorChar) {
    7915                if (match || preserveAllTokens) {
    7916                    list.add(str.substring(start, i));
    7917                    match = false;
    7918                    lastMatch = true;
    7919                }
    7920                start = ++i;
    7921                continue;
    7922            }
    7923            lastMatch = false;
    7924            match = true;
    7925            i++;
    7926        }
    7927        if (match || preserveAllTokens && lastMatch) {
    7928            list.add(str.substring(start, i));
    7929        }
    7930        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    7931    }
    7932
    7933    /**
    7934     * Performs the logic for the {@code split} and
    7935     * {@code splitPreserveAllTokens} methods that return a maximum array
    7936     * length.
    7937     *
    7938     * @param str  the String to parse, may be {@code null}
    7939     * @param separatorChars the separate character
    7940     * @param max  the maximum number of elements to include in the
    7941     *  array. A zero or negative value implies no limit.
    7942     * @param preserveAllTokens if {@code true}, adjacent separators are
    7943     * treated as empty token separators; if {@code false}, adjacent
    7944     * separators are treated as one separator.
    7945     * @return an array of parsed Strings, {@code null} if null String input
    7946     */
    7947    private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
    7948        // Performance tuned for 2.0 (JDK1.4)
    7949        // Direct code is quicker than StringTokenizer.
    7950        // Also, StringTokenizer uses isSpace() not isWhitespace()
    7951
    7952        if (str == null) {
    7953            return null;
    7954        }
    7955        final int len = str.length();
    7956        if (len == 0) {
    7957            return ArrayUtils.EMPTY_STRING_ARRAY;
    7958        }
    7959        final List<String> list = new ArrayList<>();
    7960        int sizePlus1 = 1;
    7961        int i = 0, start = 0;
    7962        boolean match = false;
    7963        boolean lastMatch = false;
    7964        if (separatorChars == null) {
    7965            // Null separator means use whitespace
    7966            while (i < len) {
    7967                if (Character.isWhitespace(str.charAt(i))) {
    7968                    if (match || preserveAllTokens) {
    7969                        lastMatch = true;
    7970                        if (sizePlus1++ == max) {
    7971                            i = len;
    7972                            lastMatch = false;
    7973                        }
    7974                        list.add(str.substring(start, i));
    7975                        match = false;
    7976                    }
    7977                    start = ++i;
    7978                    continue;
    7979                }
    7980                lastMatch = false;
    7981                match = true;
    7982                i++;
    7983            }
    7984        } else if (separatorChars.length() == 1) {
    7985            // Optimise 1 character case
    7986            final char sep = separatorChars.charAt(0);
    7987            while (i < len) {
    7988                if (str.charAt(i) == sep) {
    7989                    if (match || preserveAllTokens) {
    7990                        lastMatch = true;
    7991                        if (sizePlus1++ == max) {
    7992                            i = len;
    7993                            lastMatch = false;
    7994                        }
    7995                        list.add(str.substring(start, i));
    7996                        match = false;
    7997                    }
    7998                    start = ++i;
    7999                    continue;
    8000                }
    8001                lastMatch = false;
    8002                match = true;
    8003                i++;
    8004            }
    8005        } else {
    8006            // standard case
    8007            while (i < len) {
    8008                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
    8009                    if (match || preserveAllTokens) {
    8010                        lastMatch = true;
    8011                        if (sizePlus1++ == max) {
    8012                            i = len;
    8013                            lastMatch = false;
    8014                        }
    8015                        list.add(str.substring(start, i));
    8016                        match = false;
    8017                    }
    8018                    start = ++i;
    8019                    continue;
    8020                }
    8021                lastMatch = false;
    8022                match = true;
    8023                i++;
    8024            }
    8025        }
    8026        if (match || preserveAllTokens && lastMatch) {
    8027            list.add(str.substring(start, i));
    8028        }
    8029        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    8030    }
    8031
    8032    /**
    8033     * <p>Check if a CharSequence starts with a specified prefix.</p>
    8034     *
    8035     * <p>{@code null}s are handled without exceptions. Two {@code null}
    8036     * references are considered to be equal. The comparison is case sensitive.</p>
    8037     *
    8038     * <pre>
    8039     * StringUtils.startsWith(null, null)      = true
    8040     * StringUtils.startsWith(null, "abc")     = false
    8041     * StringUtils.startsWith("abcdef", null)  = false
    8042     * StringUtils.startsWith("abcdef", "abc") = true
    8043     * StringUtils.startsWith("ABCDEF", "abc") = false
    8044     * </pre>
    8045     *
    8046     * @see java.lang.String#startsWith(String)
    8047     * @param str  the CharSequence to check, may be null
    8048     * @param prefix the prefix to find, may be null
    8049     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
    8050     *  both {@code null}
    8051     * @since 2.4
    8052     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
    8053     */
    8054    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
    8055        return startsWith(str, prefix, false);
    8056    }
    8057
    8058    /**
    8059     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>
    8060     *
    8061     * @see java.lang.String#startsWith(String)
    8062     * @param str  the CharSequence to check, may be null
    8063     * @param prefix the prefix to find, may be null
    8064     * @param ignoreCase indicates whether the compare should ignore case
    8065     *  (case insensitive) or not.
    8066     * @return {@code true} if the CharSequence starts with the prefix or
    8067     *  both {@code null}
    8068     */
    8069    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
    8070        if (str == null || prefix == null) {
    8071            return str == prefix;
    8072        }
    8073        if (prefix.length() > str.length()) {
    8074            return false;
    8075        }
    8076        return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
    8077    }
    8078
    8079    /**
    8080     * <p>Check if a CharSequence starts with any of the provided case-sensitive prefixes.</p>
    8081     *
    8082     * <pre>
    8083     * StringUtils.startsWithAny(null, null)      = false
    8084     * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
    8085     * StringUtils.startsWithAny("abcxyz", null)     = false
    8086     * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
    8087     * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
    8088     * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
    8089     * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
    8090     * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
    8091     * </pre>
    8092     *
    8093     * @param sequence the CharSequence to check, may be null
    8094     * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
    8095     * @see StringUtils#startsWith(CharSequence, CharSequence)
    8096     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
    8097     *   the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
    8098     * @since 2.5
    8099     * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
    8100     */
    8101    public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
    8102        if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
    8103            return false;
    8104        }
    8105        for (final CharSequence searchString : searchStrings) {
    8106            if (startsWith(sequence, searchString)) {
    8107                return true;
    8108            }
    8109        }
    8110        return false;
    8111    }
    8112
    8113    /**
    8114     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>
    8115     *
    8116     * <p>{@code null}s are handled without exceptions. Two {@code null}
    8117     * references are considered to be equal. The comparison is case insensitive.</p>
    8118     *
    8119     * <pre>
    8120     * StringUtils.startsWithIgnoreCase(null, null)      = true
    8121     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
    8122     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
    8123     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
    8124     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
    8125     * </pre>
    8126     *
    8127     * @see java.lang.String#startsWith(String)
    8128     * @param str  the CharSequence to check, may be null
    8129     * @param prefix the prefix to find, may be null
    8130     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
    8131     *  both {@code null}
    8132     * @since 2.4
    8133     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
    8134     */
    8135    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
    8136        return startsWith(str, prefix, true);
    8137    }
    8138
    8139    // Stripping
    8140    //-----------------------------------------------------------------------
    8141    /**
    8142     * <p>Strips whitespace from the start and end of a String.</p>
    8143     *
    8144     * <p>This is similar to {@link #trim(String)} but removes whitespace.
    8145     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8146     *
    8147     * <p>A {@code null} input String returns {@code null}.</p>
    8148     *
    8149     * <pre>
    8150     * StringUtils.strip(null)     = null
    8151     * StringUtils.strip("")       = ""
    8152     * StringUtils.strip("   ")    = ""
    8153     * StringUtils.strip("abc")    = "abc"
    8154     * StringUtils.strip("  abc")  = "abc"
    8155     * StringUtils.strip("abc  ")  = "abc"
    8156     * StringUtils.strip(" abc ")  = "abc"
    8157     * StringUtils.strip(" ab c ") = "ab c"
    8158     * </pre>
    8159     *
    8160     * @param str  the String to remove whitespace from, may be null
    8161     * @return the stripped String, {@code null} if null String input
    8162     */
    8163    public static String strip(final String str) {
    8164        return strip(str, null);
    8165    }
    8166
    8167    /**
    8168     * <p>Strips any of a set of characters from the start and end of a String.
    8169     * This is similar to {@link String#trim()} but allows the characters
    8170     * to be stripped to be controlled.</p>
    8171     *
    8172     * <p>A {@code null} input String returns {@code null}.
    8173     * An empty string ("") input returns the empty string.</p>
    8174     *
    8175     * <p>If the stripChars String is {@code null}, whitespace is
    8176     * stripped as defined by {@link Character#isWhitespace(char)}.
    8177     * Alternatively use {@link #strip(String)}.</p>
    8178     *
    8179     * <pre>
    8180     * StringUtils.strip(null, *)          = null
    8181     * StringUtils.strip("", *)            = ""
    8182     * StringUtils.strip("abc", null)      = "abc"
    8183     * StringUtils.strip("  abc", null)    = "abc"
    8184     * StringUtils.strip("abc  ", null)    = "abc"
    8185     * StringUtils.strip(" abc ", null)    = "abc"
    8186     * StringUtils.strip("  abcyx", "xyz") = "  abc"
    8187     * </pre>
    8188     *
    8189     * @param str  the String to remove characters from, may be null
    8190     * @param stripChars  the characters to remove, null treated as whitespace
    8191     * @return the stripped String, {@code null} if null String input
    8192     */
    8193    public static String strip(String str, final String stripChars) {
    8194        if (isEmpty(str)) {
    8195            return str;
    8196        }
    8197        str = stripStart(str, stripChars);
    8198        return stripEnd(str, stripChars);
    8199    }
    8200
    8201    /**
    8202     * <p>Removes diacritics (~= accents) from a string. The case will not be altered.</p>
    8203     * <p>For instance, '&agrave;' will be replaced by 'a'.</p>
    8204     * <p>Note that ligatures will be left as is.</p>
    8205     *
    8206     * <pre>
    8207     * StringUtils.stripAccents(null)                = null
    8208     * StringUtils.stripAccents("")                  = ""
    8209     * StringUtils.stripAccents("control")           = "control"
    8210     * StringUtils.stripAccents("&eacute;clair")     = "eclair"
    8211     * </pre>
    8212     *
    8213     * @param input String to be stripped
    8214     * @return input text with diacritics removed
    8215     *
    8216     * @since 3.0
    8217     */
    8218    // 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).
    8219    public static String stripAccents(final String input) {
    8220        if (input == null) {
    8221            return null;
    8222        }
    8223        final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));
    8224        convertRemainingAccentCharacters(decomposed);
    8225        // Note that this doesn't correctly remove ligatures...
    8226        return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
    8227    }
    8228
    8229    // StripAll
    8230    //-----------------------------------------------------------------------
    8231    /**
    8232     * <p>Strips whitespace from the start and end of every String in an array.
    8233     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8234     *
    8235     * <p>A new array is returned each time, except for length zero.
    8236     * A {@code null} array will return {@code null}.
    8237     * An empty array will return itself.
    8238     * A {@code null} array entry will be ignored.</p>
    8239     *
    8240     * <pre>
    8241     * StringUtils.stripAll(null)             = null
    8242     * StringUtils.stripAll([])               = []
    8243     * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
    8244     * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
    8245     * </pre>
    8246     *
    8247     * @param strs  the array to remove whitespace from, may be null
    8248     * @return the stripped Strings, {@code null} if null array input
    8249     */
    8250    public static String[] stripAll(final String... strs) {
    8251        return stripAll(strs, null);
    8252    }
    8253
    8254    /**
    8255     * <p>Strips any of a set of characters from the start and end of every
    8256     * String in an array.</p>
    8257     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8258     *
    8259     * <p>A new array is returned each time, except for length zero.
    8260     * A {@code null} array will return {@code null}.
    8261     * An empty array will return itself.
    8262     * A {@code null} array entry will be ignored.
    8263     * A {@code null} stripChars will strip whitespace as defined by
    8264     * {@link Character#isWhitespace(char)}.</p>
    8265     *
    8266     * <pre>
    8267     * StringUtils.stripAll(null, *)                = null
    8268     * StringUtils.stripAll([], *)                  = []
    8269     * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
    8270     * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
    8271     * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
    8272     * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
    8273     * </pre>
    8274     *
    8275     * @param strs  the array to remove characters from, may be null
    8276     * @param stripChars  the characters to remove, null treated as whitespace
    8277     * @return the stripped Strings, {@code null} if null array input
    8278     */
    8279    public static String[] stripAll(final String[] strs, final String stripChars) {
    8280        final int strsLen = ArrayUtils.getLength(strs);
    8281        if (strsLen == 0) {
    8282            return strs;
    8283        }
    8284        final String[] newArr = new String[strsLen];
    8285        for (int i = 0; i < strsLen; i++) {
    8286            newArr[i] = strip(strs[i], stripChars);
    8287        }
    8288        return newArr;
    8289    }
    8290
    8291    /**
    8292     * <p>Strips any of a set of characters from the end of a String.</p>
    8293     *
    8294     * <p>A {@code null} input String returns {@code null}.
    8295     * An empty string ("") input returns the empty string.</p>
    8296     *
    8297     * <p>If the stripChars String is {@code null}, whitespace is
    8298     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    8299     *
    8300     * <pre>
    8301     * StringUtils.stripEnd(null, *)          = null
    8302     * StringUtils.stripEnd("", *)            = ""
    8303     * StringUtils.stripEnd("abc", "")        = "abc"
    8304     * StringUtils.stripEnd("abc", null)      = "abc"
    8305     * StringUtils.stripEnd("  abc", null)    = "  abc"
    8306     * StringUtils.stripEnd("abc  ", null)    = "abc"
    8307     * StringUtils.stripEnd(" abc ", null)    = " abc"
    8308     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
    8309     * StringUtils.stripEnd("120.00", ".0")   = "12"
    8310     * </pre>
    8311     *
    8312     * @param str  the String to remove characters from, may be null
    8313     * @param stripChars  the set of characters to remove, null treated as whitespace
    8314     * @return the stripped String, {@code null} if null String input
    8315     */
    8316    public static String stripEnd(final String str, final String stripChars) {
    8317        int end = length(str);
    8318        if (end == 0) {
    8319            return str;
    8320        }
    8321
    8322        if (stripChars == null) {
    8323            while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
    8324                end--;
    8325            }
    8326        } else if (stripChars.isEmpty()) {
    8327            return str;
    8328        } else {
    8329            while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
    8330                end--;
    8331            }
    8332        }
    8333        return str.substring(0, end);
    8334    }
    8335
    8336    /**
    8337     * <p>Strips any of a set of characters from the start of a String.</p>
    8338     *
    8339     * <p>A {@code null} input String returns {@code null}.
    8340     * An empty string ("") input returns the empty string.</p>
    8341     *
    8342     * <p>If the stripChars String is {@code null}, whitespace is
    8343     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
    8344     *
    8345     * <pre>
    8346     * StringUtils.stripStart(null, *)          = null
    8347     * StringUtils.stripStart("", *)            = ""
    8348     * StringUtils.stripStart("abc", "")        = "abc"
    8349     * StringUtils.stripStart("abc", null)      = "abc"
    8350     * StringUtils.stripStart("  abc", null)    = "abc"
    8351     * StringUtils.stripStart("abc  ", null)    = "abc  "
    8352     * StringUtils.stripStart(" abc ", null)    = "abc "
    8353     * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
    8354     * </pre>
    8355     *
    8356     * @param str  the String to remove characters from, may be null
    8357     * @param stripChars  the characters to remove, null treated as whitespace
    8358     * @return the stripped String, {@code null} if null String input
    8359     */
    8360    public static String stripStart(final String str, final String stripChars) {
    8361        final int strLen = length(str);
    8362        if (strLen == 0) {
    8363            return str;
    8364        }
    8365        int start = 0;
    8366        if (stripChars == null) {
    8367            while (start != strLen && Character.isWhitespace(str.charAt(start))) {
    8368                start++;
    8369            }
    8370        } else if (stripChars.isEmpty()) {
    8371            return str;
    8372        } else {
    8373            while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
    8374                start++;
    8375            }
    8376        }
    8377        return str.substring(start);
    8378    }
    8379
    8380    /**
    8381     * <p>Strips whitespace from the start and end of a String  returning
    8382     * an empty String if {@code null} input.</p>
    8383     *
    8384     * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
    8385     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8386     *
    8387     * <pre>
    8388     * StringUtils.stripToEmpty(null)     = ""
    8389     * StringUtils.stripToEmpty("")       = ""
    8390     * StringUtils.stripToEmpty("   ")    = ""
    8391     * StringUtils.stripToEmpty("abc")    = "abc"
    8392     * StringUtils.stripToEmpty("  abc")  = "abc"
    8393     * StringUtils.stripToEmpty("abc  ")  = "abc"
    8394     * StringUtils.stripToEmpty(" abc ")  = "abc"
    8395     * StringUtils.stripToEmpty(" ab c ") = "ab c"
    8396     * </pre>
    8397     *
    8398     * @param str  the String to be stripped, may be null
    8399     * @return the trimmed String, or an empty String if {@code null} input
    8400     * @since 2.0
    8401     */
    8402    public static String stripToEmpty(final String str) {
    8403        return str == null ? EMPTY : strip(str, null);
    8404    }
    8405
    8406    /**
    8407     * <p>Strips whitespace from the start and end of a String  returning
    8408     * {@code null} if the String is empty ("") after the strip.</p>
    8409     *
    8410     * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
    8411     * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
    8412     *
    8413     * <pre>
    8414     * StringUtils.stripToNull(null)     = null
    8415     * StringUtils.stripToNull("")       = null
    8416     * StringUtils.stripToNull("   ")    = null
    8417     * StringUtils.stripToNull("abc")    = "abc"
    8418     * StringUtils.stripToNull("  abc")  = "abc"
    8419     * StringUtils.stripToNull("abc  ")  = "abc"
    8420     * StringUtils.stripToNull(" abc ")  = "abc"
    8421     * StringUtils.stripToNull(" ab c ") = "ab c"
    8422     * </pre>
    8423     *
    8424     * @param str  the String to be stripped, may be null
    8425     * @return the stripped String,
    8426     *  {@code null} if whitespace, empty or null String input
    8427     * @since 2.0
    8428     */
    8429    public static String stripToNull(String str) {
    8430        if (str == null) {
    8431            return null;
    8432        }
    8433        str = strip(str, null);
    8434        return str.isEmpty() ? null : str;
    8435    }
    8436
    8437    // Substring
    8438    //-----------------------------------------------------------------------
    8439    /**
    8440     * <p>Gets a substring from the specified String avoiding exceptions.</p>
    8441     *
    8442     * <p>A negative start position can be used to start {@code n}
    8443     * characters from the end of the String.</p>
    8444     *
    8445     * <p>A {@code null} String will return {@code null}.
    8446     * An empty ("") String will return "".</p>
    8447     *
    8448     * <pre>
    8449     * StringUtils.substring(null, *)   = null
    8450     * StringUtils.substring("", *)     = ""
    8451     * StringUtils.substring("abc", 0)  = "abc"
    8452     * StringUtils.substring("abc", 2)  = "c"
    8453     * StringUtils.substring("abc", 4)  = ""
    8454     * StringUtils.substring("abc", -2) = "bc"
    8455     * StringUtils.substring("abc", -4) = "abc"
    8456     * </pre>
    8457     *
    8458     * @param str  the String to get the substring from, may be null
    8459     * @param start  the position to start from, negative means
    8460     *  count back from the end of the String by this many characters
    8461     * @return substring from start position, {@code null} if null String input
    8462     */
    8463    public static String substring(final String str, int start) {
    8464        if (str == null) {
    8465            return null;
    8466        }
    8467
    8468        // handle negatives, which means last n characters
    8469        if (start < 0) {
    8470            start = str.length() + start; // remember start is negative
    8471        }
    8472
    8473        if (start < 0) {
    8474            start = 0;
    8475        }
    8476        if (start > str.length()) {
    8477            return EMPTY;
    8478        }
    8479
    8480        return str.substring(start);
    8481    }
    8482
    8483    /**
    8484     * <p>Gets a substring from the specified String avoiding exceptions.</p>
    8485     *
    8486     * <p>A negative start position can be used to start/end {@code n}
    8487     * characters from the end of the String.</p>
    8488     *
    8489     * <p>The returned substring starts with the character in the {@code start}
    8490     * position and ends before the {@code end} position. All position counting is
    8491     * zero-based -- i.e., to start at the beginning of the string use
    8492     * {@code start = 0}. Negative start and end positions can be used to
    8493     * specify offsets relative to the end of the String.</p>
    8494     *
    8495     * <p>If {@code start} is not strictly to the left of {@code end}, ""
    8496     * is returned.</p>
    8497     *
    8498     * <pre>
    8499     * StringUtils.substring(null, *, *)    = null
    8500     * StringUtils.substring("", * ,  *)    = "";
    8501     * StringUtils.substring("abc", 0, 2)   = "ab"
    8502     * StringUtils.substring("abc", 2, 0)   = ""
    8503     * StringUtils.substring("abc", 2, 4)   = "c"
    8504     * StringUtils.substring("abc", 4, 6)   = ""
    8505     * StringUtils.substring("abc", 2, 2)   = ""
    8506     * StringUtils.substring("abc", -2, -1) = "b"
    8507     * StringUtils.substring("abc", -4, 2)  = "ab"
    8508     * </pre>
    8509     *
    8510     * @param str  the String to get the substring from, may be null
    8511     * @param start  the position to start from, negative means
    8512     *  count back from the end of the String by this many characters
    8513     * @param end  the position to end at (exclusive), negative means
    8514     *  count back from the end of the String by this many characters
    8515     * @return substring from start position to end position,
    8516     *  {@code null} if null String input
    8517     */
    8518    public static String substring(final String str, int start, int end) {
    8519        if (str == null) {
    8520            return null;
    8521        }
    8522
    8523        // handle negatives
    8524        if (end < 0) {
    8525            end = str.length() + end; // remember end is negative
    8526        }
    8527        if (start < 0) {
    8528            start = str.length() + start; // remember start is negative
    8529        }
    8530
    8531        // check length next
    8532        if (end > str.length()) {
    8533            end = str.length();
    8534        }
    8535
    8536        // if start is greater than end, return ""
    8537        if (start > end) {
    8538            return EMPTY;
    8539        }
    8540
    8541        if (start < 0) {
    8542            start = 0;
    8543        }
    8544        if (end < 0) {
    8545            end = 0;
    8546        }
    8547
    8548        return str.substring(start, end);
    8549    }
    8550
    8551    /**
    8552     * <p>Gets the substring after the first occurrence of a separator.
    8553     * The separator is not returned.</p>
    8554     *
    8555     * <p>A {@code null} string input will return {@code null}.
    8556     * An empty ("") string input will return the empty string.
    8557     *
    8558     * <p>If nothing is found, the empty string is returned.</p>
    8559     *
    8560     * <pre>
    8561     * StringUtils.substringAfter(null, *)      = null
    8562     * StringUtils.substringAfter("", *)        = ""
    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", 32)   = "abc"
    8568     * </pre>
    8569     *
    8570     * @param str  the String to get a substring from, may be null
    8571     * @param separator  the character to search.
    8572     * @return the substring after the first occurrence of the separator,
    8573     *  {@code null} if null String input
    8574     * @since 3.11
    8575     */
    8576    public static String substringAfter(final String str, final int separator) {
    8577        if (isEmpty(str)) {
    8578            return str;
    8579        }
    8580        final int pos = str.indexOf(separator);
    8581        if (pos == INDEX_NOT_FOUND) {
    8582            return EMPTY;
    8583        }
    8584        return str.substring(pos + 1);
    8585    }
    8586
    8587    /**
    8588     * <p>Gets the substring after the first occurrence of a separator.
    8589     * The separator is not returned.</p>
    8590     *
    8591     * <p>A {@code null} string input will return {@code null}.
    8592     * An empty ("") string input will return the empty string.
    8593     * A {@code null} separator will return the empty string if the
    8594     * input string is not {@code null}.</p>
    8595     *
    8596     * <p>If nothing is found, the empty string is returned.</p>
    8597     *
    8598     * <pre>
    8599     * StringUtils.substringAfter(null, *)      = null
    8600     * StringUtils.substringAfter("", *)        = ""
    8601     * StringUtils.substringAfter(*, null)      = ""
    8602     * StringUtils.substringAfter("abc", "a")   = "bc"
    8603     * StringUtils.substringAfter("abcba", "b") = "cba"
    8604     * StringUtils.substringAfter("abc", "c")   = ""
    8605     * StringUtils.substringAfter("abc", "d")   = ""
    8606     * StringUtils.substringAfter("abc", "")    = "abc"
    8607     * </pre>
    8608     *
    8609     * @param str  the String to get a substring from, may be null
    8610     * @param separator  the String to search for, may be null
    8611     * @return the substring after the first occurrence of the separator,
    8612     *  {@code null} if null String input
    8613     * @since 2.0
    8614     */
    8615    public static String substringAfter(final String str, final String separator) {
    8616        if (isEmpty(str)) {
    8617            return str;
    8618        }
    8619        if (separator == null) {
    8620            return EMPTY;
    8621        }
    8622        final int pos = str.indexOf(separator);
    8623        if (pos == INDEX_NOT_FOUND) {
    8624            return EMPTY;
    8625        }
    8626        return str.substring(pos + separator.length());
    8627    }
    8628
    8629    // startsWith
    8630    //-----------------------------------------------------------------------
    8631
    8632    /**
    8633     * <p>Gets the substring after the last occurrence of a separator.
    8634     * The separator is not returned.</p>
    8635     *
    8636     * <p>A {@code null} string input will return {@code null}.
    8637     * An empty ("") string input will return the empty string.
    8638     *
    8639     * <p>If nothing is found, the empty string is returned.</p>
    8640     *
    8641     * <pre>
    8642     * StringUtils.substringAfterLast(null, *)      = null
    8643     * StringUtils.substringAfterLast("", *)        = ""
    8644     * StringUtils.substringAfterLast("abc", 'a')   = "bc"
    8645     * StringUtils.substringAfterLast(" bc", 32)    = "bc"
    8646     * StringUtils.substringAfterLast("abcba", 'b') = "a"
    8647     * StringUtils.substringAfterLast("abc", 'c')   = ""
    8648     * StringUtils.substringAfterLast("a", 'a')     = ""
    8649     * StringUtils.substringAfterLast("a", 'z')     = ""
    8650     * </pre>
    8651     *
    8652     * @param str  the String to get a substring from, may be null
    8653     * @param separator  the String to search for, may be null
    8654     * @return the substring after the last occurrence of the separator,
    8655     *  {@code null} if null String input
    8656     * @since 3.11
    8657     */
    8658    public static String substringAfterLast(final String str, final int separator) {
    8659        if (isEmpty(str)) {
    8660            return str;
    8661        }
    8662        final int pos = str.lastIndexOf(separator);
    8663        if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) {
    8664            return EMPTY;
    8665        }
    8666        return str.substring(pos + 1);
    8667    }
    8668
    8669    /**
    8670     * <p>Gets the substring after the last occurrence of a separator.
    8671     * The separator is not returned.</p>
    8672     *
    8673     * <p>A {@code null} string input will return {@code null}.
    8674     * An empty ("") string input will return the empty string.
    8675     * An empty or {@code null} separator will return the empty string if
    8676     * the input string is not {@code null}.</p>
    8677     *
    8678     * <p>If nothing is found, the empty string is returned.</p>
    8679     *
    8680     * <pre>
    8681     * StringUtils.substringAfterLast(null, *)      = null
    8682     * StringUtils.substringAfterLast("", *)        = ""
    8683     * StringUtils.substringAfterLast(*, "")        = ""
    8684     * StringUtils.substringAfterLast(*, null)      = ""
    8685     * StringUtils.substringAfterLast("abc", "a")   = "bc"
    8686     * StringUtils.substringAfterLast("abcba", "b") = "a"
    8687     * StringUtils.substringAfterLast("abc", "c")   = ""
    8688     * StringUtils.substringAfterLast("a", "a")     = ""
    8689     * StringUtils.substringAfterLast("a", "z")     = ""
    8690     * </pre>
    8691     *
    8692     * @param str  the String to get a substring from, may be null
    8693     * @param separator  the String to search for, may be null
    8694     * @return the substring after the last occurrence of the separator,
    8695     *  {@code null} if null String input
    8696     * @since 2.0
    8697     */
    8698    public static String substringAfterLast(final String str, final String separator) {
    8699        if (isEmpty(str)) {
    8700            return str;
    8701        }
    8702        if (isEmpty(separator)) {
    8703            return EMPTY;
    8704        }
    8705        final int pos = str.lastIndexOf(separator);
    8706        if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
    8707            return EMPTY;
    8708        }
    8709        return str.substring(pos + separator.length());
    8710    }
    8711
    8712    // SubStringAfter/SubStringBefore
    8713    //-----------------------------------------------------------------------
    8714    /**
    8715     * <p>Gets the substring before the first occurrence of a separator.
    8716     * The separator is not returned.</p>
    8717     *
    8718     * <p>A {@code null} string input will return {@code null}.
    8719     * An empty ("") string input will return the empty string.
    8720     * A {@code null} separator will return the input string.</p>
    8721     *
    8722     * <p>If nothing is found, the string input is returned.</p>
    8723     *
    8724     * <pre>
    8725     * StringUtils.substringBefore(null, *)      = null
    8726     * StringUtils.substringBefore("", *)        = ""
    8727     * StringUtils.substringBefore("abc", "a")   = ""
    8728     * StringUtils.substringBefore("abcba", "b") = "a"
    8729     * StringUtils.substringBefore("abc", "c")   = "ab"
    8730     * StringUtils.substringBefore("abc", "d")   = "abc"
    8731     * StringUtils.substringBefore("abc", "")    = ""
    8732     * StringUtils.substringBefore("abc", null)  = "abc"
    8733     * </pre>
    8734     *
    8735     * @param str  the String to get a substring from, may be null
    8736     * @param separator  the String to search for, may be null
    8737     * @return the substring before the first occurrence of the separator,
    8738     *  {@code null} if null String input
    8739     * @since 2.0
    8740     */
    8741    public static String substringBefore(final String str, final String separator) {
    8742        if (isEmpty(str) || separator == null) {
    8743            return str;
    8744        }
    8745        if (separator.isEmpty()) {
    8746            return EMPTY;
    8747        }
    8748        final int pos = str.indexOf(separator);
    8749        if (pos == INDEX_NOT_FOUND) {
    8750            return str;
    8751        }
    8752        return str.substring(0, pos);
    8753    }
    8754
    8755    /**
    8756     * <p>Gets the substring before the last occurrence of a separator.
    8757     * The separator is not returned.</p>
    8758     *
    8759     * <p>A {@code null} string input will return {@code null}.
    8760     * An empty ("") string input will return the empty string.
    8761     * An empty or {@code null} separator will return the input string.</p>
    8762     *
    8763     * <p>If nothing is found, the string input is returned.</p>
    8764     *
    8765     * <pre>
    8766     * StringUtils.substringBeforeLast(null, *)      = null
    8767     * StringUtils.substringBeforeLast("", *)        = ""
    8768     * StringUtils.substringBeforeLast("abcba", "b") = "abc"
    8769     * StringUtils.substringBeforeLast("abc", "c")   = "ab"
    8770     * StringUtils.substringBeforeLast("a", "a")     = ""
    8771     * StringUtils.substringBeforeLast("a", "z")     = "a"
    8772     * StringUtils.substringBeforeLast("a", null)    = "a"
    8773     * StringUtils.substringBeforeLast("a", "")      = "a"
    8774     * </pre>
    8775     *
    8776     * @param str  the String to get a substring from, may be null
    8777     * @param separator  the String to search for, may be null
    8778     * @return the substring before the last occurrence of the separator,
    8779     *  {@code null} if null String input
    8780     * @since 2.0
    8781     */
    8782    public static String substringBeforeLast(final String str, final String separator) {
    8783        if (isEmpty(str) || isEmpty(separator)) {
    8784            return str;
    8785        }
    8786        final int pos = str.lastIndexOf(separator);
    8787        if (pos == INDEX_NOT_FOUND) {
    8788            return str;
    8789        }
    8790        return str.substring(0, pos);
    8791    }
    8792
    8793    // Substring between
    8794    //-----------------------------------------------------------------------
    8795    /**
    8796     * <p>Gets the String that is nested in between two instances of the
    8797     * same String.</p>
    8798     *
    8799     * <p>A {@code null} input String returns {@code null}.
    8800     * A {@code null} tag returns {@code null}.</p>
    8801     *
    8802     * <pre>
    8803     * StringUtils.substringBetween(null, *)            = null
    8804     * StringUtils.substringBetween("", "")             = ""
    8805     * StringUtils.substringBetween("", "tag")          = null
    8806     * StringUtils.substringBetween("tagabctag", null)  = null
    8807     * StringUtils.substringBetween("tagabctag", "")    = ""
    8808     * StringUtils.substringBetween("tagabctag", "tag") = "abc"
    8809     * </pre>
    8810     *
    8811     * @param str  the String containing the substring, may be null
    8812     * @param tag  the String before and after the substring, may be null
    8813     * @return the substring, {@code null} if no match
    8814     * @since 2.0
    8815     */
    8816    public static String substringBetween(final String str, final String tag) {
    8817        return substringBetween(str, tag, tag);
    8818    }
    8819
    8820    // endsWith
    8821    //-----------------------------------------------------------------------
    8822
    8823    /**
    8824     * <p>Gets the String that is nested in between two Strings.
    8825     * Only the first match is returned.</p>
    8826     *
    8827     * <p>A {@code null} input String returns {@code null}.
    8828     * A {@code null} open/close returns {@code null} (no match).
    8829     * An empty ("") open and close returns an empty string.</p>
    8830     *
    8831     * <pre>
    8832     * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
    8833     * StringUtils.substringBetween(null, *, *)          = null
    8834     * StringUtils.substringBetween(*, null, *)          = null
    8835     * StringUtils.substringBetween(*, *, null)          = null
    8836     * StringUtils.substringBetween("", "", "")          = ""
    8837     * StringUtils.substringBetween("", "", "]")         = null
    8838     * StringUtils.substringBetween("", "[", "]")        = null
    8839     * StringUtils.substringBetween("yabcz", "", "")     = ""
    8840     * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
    8841     * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
    8842     * </pre>
    8843     *
    8844     * @param str  the String containing the substring, may be null
    8845     * @param open  the String before the substring, may be null
    8846     * @param close  the String after the substring, may be null
    8847     * @return the substring, {@code null} if no match
    8848     * @since 2.0
    8849     */
    8850    public static String substringBetween(final String str, final String open, final String close) {
    8851        if (!ObjectUtils.allNotNull(str, open, close)) {
    8852            return null;
    8853        }
    8854        final int start = str.indexOf(open);
    8855        if (start != INDEX_NOT_FOUND) {
    8856            final int end = str.indexOf(close, start + open.length());
    8857            if (end != INDEX_NOT_FOUND) {
    8858                return str.substring(start + open.length(), end);
    8859            }
    8860        }
    8861        return null;
    8862    }
    8863
    8864    /**
    8865     * <p>Searches a String for substrings delimited by a start and end tag,
    8866     * returning all matching substrings in an array.</p>
    8867     *
    8868     * <p>A {@code null} input String returns {@code null}.
    8869     * A {@code null} open/close returns {@code null} (no match).
    8870     * An empty ("") open/close returns {@code null} (no match).</p>
    8871     *
    8872     * <pre>
    8873     * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
    8874     * StringUtils.substringsBetween(null, *, *)            = null
    8875     * StringUtils.substringsBetween(*, null, *)            = null
    8876     * StringUtils.substringsBetween(*, *, null)            = null
    8877     * StringUtils.substringsBetween("", "[", "]")          = []
    8878     * </pre>
    8879     *
    8880     * @param str  the String containing the substrings, null returns null, empty returns empty
    8881     * @param open  the String identifying the start of the substring, empty returns null
    8882     * @param close  the String identifying the end of the substring, empty returns null
    8883     * @return a String Array of substrings, or {@code null} if no match
    8884     * @since 2.3
    8885     */
    8886    public static String[] substringsBetween(final String str, final String open, final String close) {
    8887        if (str == null || isEmpty(open) || isEmpty(close)) {
    8888            return null;
    8889        }
    8890        final int strLen = str.length();
    8891        if (strLen == 0) {
    8892            return ArrayUtils.EMPTY_STRING_ARRAY;
    8893        }
    8894        final int closeLen = close.length();
    8895        final int openLen = open.length();
    8896        final List<String> list = new ArrayList<>();
    8897        int pos = 0;
    8898        while (pos < strLen - closeLen) {
    8899            int start = str.indexOf(open, pos);
    8900            if (start < 0) {
    8901                break;
    8902            }
    8903            start += openLen;
    8904            final int end = str.indexOf(close, start);
    8905            if (end < 0) {
    8906                break;
    8907            }
    8908            list.add(str.substring(start, end));
    8909            pos = end + closeLen;
    8910        }
    8911        if (list.isEmpty()) {
    8912            return null;
    8913        }
    8914        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
    8915    }
    8916
    8917    /**
    8918     * <p>Swaps the case of a String changing upper and title case to
    8919     * lower case, and lower case to upper case.</p>
    8920     *
    8921     * <ul>
    8922     *  <li>Upper case character converts to Lower case</li>
    8923     *  <li>Title case character converts to Lower case</li>
    8924     *  <li>Lower case character converts to Upper case</li>
    8925     * </ul>
    8926     *
    8927     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}.
    8928     * A {@code null} input String returns {@code null}.</p>
    8929     *
    8930     * <pre>
    8931     * StringUtils.swapCase(null)                 = null
    8932     * StringUtils.swapCase("")                   = ""
    8933     * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
    8934     * </pre>
    8935     *
    8936     * <p>NOTE: This method changed in Lang version 2.0.
    8937     * It no longer performs a word based algorithm.
    8938     * If you only use ASCII, you will notice no change.
    8939     * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p>
    8940     *
    8941     * @param str  the String to swap case, may be null
    8942     * @return the changed String, {@code null} if null String input
    8943     */
    8944    public static String swapCase(final String str) {
    8945        if (isEmpty(str)) {
    8946            return str;
    8947        }
    8948
    8949        final int strLen = str.length();
    8950        final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
    8951        int outOffset = 0;
    8952        for (int i = 0; i < strLen; ) {
    8953            final int oldCodepoint = str.codePointAt(i);
    8954            final int newCodePoint;
    8955            if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) {
    8956                newCodePoint = Character.toLowerCase(oldCodepoint);
    8957            } else if (Character.isLowerCase(oldCodepoint)) {
    8958                newCodePoint = Character.toUpperCase(oldCodepoint);
    8959            } else {
    8960                newCodePoint = oldCodepoint;
    8961            }
    8962            newCodePoints[outOffset++] = newCodePoint;
    8963            i += Character.charCount(newCodePoint);
    8964         }
    8965        return new String(newCodePoints, 0, outOffset);
    8966    }
    8967
    8968    /**
    8969     * <p>Converts a {@code CharSequence} into an array of code points.</p>
    8970     *
    8971     * <p>Valid pairs of surrogate code units will be converted into a single supplementary
    8972     * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or
    8973     * a low surrogate not preceded by a high surrogate) will be returned as-is.</p>
    8974     *
    8975     * <pre>
    8976     * StringUtils.toCodePoints(null)   =  null
    8977     * StringUtils.toCodePoints("")     =  []  // empty array
    8978     * </pre>
    8979     *
    8980     * @param str the character sequence to convert
    8981     * @return an array of code points
    8982     * @since 3.6
    8983     */
    8984    public static int[] toCodePoints(final CharSequence str) {
    8985        if (str == null) {
    8986            return null;
    8987        }
    8988        if (str.length() == 0) {
    8989            return ArrayUtils.EMPTY_INT_ARRAY;
    8990        }
    8991
    8992        final String s = str.toString();
    8993        final int[] result = new int[s.codePointCount(0, s.length())];
    8994        int index = 0;
    8995        for (int i = 0; i < result.length; i++) {
    8996            result[i] = s.codePointAt(index);
    8997            index += Character.charCount(result[i]);
    8998        }
    8999        return result;
    9000    }
    9001
    9002    /**
    9003     * Converts a {@code byte[]} to a String using the specified character encoding.
    9004     *
    9005     * @param bytes
    9006     *            the byte array to read from
    9007     * @param charset
    9008     *            the encoding to use, if null then use the platform default
    9009     * @return a new String
    9010     * @throws NullPointerException
    9011     *             if {@code bytes} is null
    9012     * @since 3.2
    9013     * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
    9014     */
    9015    public static String toEncodedString(final byte[] bytes, final Charset charset) {
    9016        return new String(bytes, Charsets.toCharset(charset));
    9017    }
    9018
    9019    /**
    9020     * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
    9021     *
    9022     * @param source A source String or null.
    9023     * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null.
    9024     * @since 3.10
    9025     */
    9026    public static String toRootLowerCase(final String source) {
    9027        return source == null ? null : source.toLowerCase(Locale.ROOT);
    9028    }
    9029
    9030    /**
    9031     * Converts the given source String as a upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
    9032     *
    9033     * @param source A source String or null.
    9034     * @return the given source String as a upper-case using the {@link Locale#ROOT} locale or null.
    9035     * @since 3.10
    9036     */
    9037    public static String toRootUpperCase(final String source) {
    9038        return source == null ? null : source.toUpperCase(Locale.ROOT);
    9039    }
    9040
    9041    /**
    9042     * Converts a {@code byte[]} to a String using the specified character encoding.
    9043     *
    9044     * @param bytes
    9045     *            the byte array to read from
    9046     * @param charsetName
    9047     *            the encoding to use, if null then use the platform default
    9048     * @return a new String
    9049     * @throws UnsupportedEncodingException
    9050     *             If the named charset is not supported
    9051     * @throws NullPointerException
    9052     *             if the input is null
    9053     * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
    9054     * @since 3.1
    9055     */
    9056    @Deprecated
    9057    public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException {
    9058        return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset());
    9059    }
    9060
    9061    // Trim
    9062    //-----------------------------------------------------------------------
    9063    /**
    9064     * <p>Removes control characters (char &lt;= 32) from both
    9065     * ends of this String, handling {@code null} by returning
    9066     * {@code null}.</p>
    9067     *
    9068     * <p>The String is trimmed using {@link String#trim()}.
    9069     * Trim removes start and end characters &lt;= 32.
    9070     * To strip whitespace use {@link #strip(String)}.</p>
    9071     *
    9072     * <p>To trim your choice of characters, use the
    9073     * {@link #strip(String, String)} methods.</p>
    9074     *
    9075     * <pre>
    9076     * StringUtils.trim(null)          = null
    9077     * StringUtils.trim("")            = ""
    9078     * StringUtils.trim("     ")       = ""
    9079     * StringUtils.trim("abc")         = "abc"
    9080     * StringUtils.trim("    abc    ") = "abc"
    9081     * </pre>
    9082     *
    9083     * @param str  the String to be trimmed, may be null
    9084     * @return the trimmed string, {@code null} if null String input
    9085     */
    9086    public static String trim(final String str) {
    9087        return str == null ? null : str.trim();
    9088    }
    9089
    9090    /**
    9091     * <p>Removes control characters (char &lt;= 32) from both
    9092     * ends of this String returning an empty String ("") if the String
    9093     * is empty ("") after the trim or if it is {@code null}.
    9094     *
    9095     * <p>The String is trimmed using {@link String#trim()}.
    9096     * Trim removes start and end characters &lt;= 32.
    9097     * To strip whitespace use {@link #stripToEmpty(String)}.</p>
    9098     *
    9099     * <pre>
    9100     * StringUtils.trimToEmpty(null)          = ""
    9101     * StringUtils.trimToEmpty("")            = ""
    9102     * StringUtils.trimToEmpty("     ")       = ""
    9103     * StringUtils.trimToEmpty("abc")         = "abc"
    9104     * StringUtils.trimToEmpty("    abc    ") = "abc"
    9105     * </pre>
    9106     *
    9107     * @param str  the String to be trimmed, may be null
    9108     * @return the trimmed String, or an empty String if {@code null} input
    9109     * @since 2.0
    9110     */
    9111    public static String trimToEmpty(final String str) {
    9112        return str == null ? EMPTY : str.trim();
    9113    }
    9114
    9115    /**
    9116     * <p>Removes control characters (char &lt;= 32) from both
    9117     * ends of this String returning {@code null} if the String is
    9118     * empty ("") after the trim or if it is {@code null}.
    9119     *
    9120     * <p>The String is trimmed using {@link String#trim()}.
    9121     * Trim removes start and end characters &lt;= 32.
    9122     * To strip whitespace use {@link #stripToNull(String)}.</p>
    9123     *
    9124     * <pre>
    9125     * StringUtils.trimToNull(null)          = null
    9126     * StringUtils.trimToNull("")            = null
    9127     * StringUtils.trimToNull("     ")       = null
    9128     * StringUtils.trimToNull("abc")         = "abc"
    9129     * StringUtils.trimToNull("    abc    ") = "abc"
    9130     * </pre>
    9131     *
    9132     * @param str  the String to be trimmed, may be null
    9133     * @return the trimmed String,
    9134     *  {@code null} if only chars &lt;= 32, empty or null String input
    9135     * @since 2.0
    9136     */
    9137    public static String trimToNull(final String str) {
    9138        final String ts = trim(str);
    9139        return isEmpty(ts) ? null : ts;
    9140    }
    9141
    9142    /**
    9143     * <p>Truncates a String. This will turn
    9144     * "Now is the time for all good men" into "Now is the time for".</p>
    9145     *
    9146     * <p>Specifically:</p>
    9147     * <ul>
    9148     *   <li>If {@code str} is less than {@code maxWidth} characters
    9149     *       long, return it.</li>
    9150     *   <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
    9151     *   <li>If {@code maxWidth} is less than {@code 0}, throw an
    9152     *       {@code IllegalArgumentException}.</li>
    9153     *   <li>In no case will it return a String of length greater than
    9154     *       {@code maxWidth}.</li>
    9155     * </ul>
    9156     *
    9157     * <pre>
    9158     * StringUtils.truncate(null, 0)       = null
    9159     * StringUtils.truncate(null, 2)       = null
    9160     * StringUtils.truncate("", 4)         = ""
    9161     * StringUtils.truncate("abcdefg", 4)  = "abcd"
    9162     * StringUtils.truncate("abcdefg", 6)  = "abcdef"
    9163     * StringUtils.truncate("abcdefg", 7)  = "abcdefg"
    9164     * StringUtils.truncate("abcdefg", 8)  = "abcdefg"
    9165     * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
    9166     * </pre>
    9167     *
    9168     * @param str  the String to truncate, may be null
    9169     * @param maxWidth  maximum length of result String, must be positive
    9170     * @return truncated String, {@code null} if null String input
    9171     * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}
    9172     * @since 3.5
    9173     */
    9174    public static String truncate(final String str, final int maxWidth) {
    9175        return truncate(str, 0, maxWidth);
    9176    }
    9177
    9178    /**
    9179     * <p>Truncates a String. This will turn
    9180     * "Now is the time for all good men" into "is the time for all".</p>
    9181     *
    9182     * <p>Works like {@code truncate(String, int)}, but allows you to specify
    9183     * a "left edge" offset.
    9184     *
    9185     * <p>Specifically:</p>
    9186     * <ul>
    9187     *   <li>If {@code str} is less than {@code maxWidth} characters
    9188     *       long, return it.</li>
    9189     *   <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
    9190     *   <li>If {@code maxWidth} is less than {@code 0}, throw an
    9191     *       {@code IllegalArgumentException}.</li>
    9192     *   <li>If {@code offset} is less than {@code 0}, throw an
    9193     *       {@code IllegalArgumentException}.</li>
    9194     *   <li>In no case will it return a String of length greater than
    9195     *       {@code maxWidth}.</li>
    9196     * </ul>
    9197     *
    9198     * <pre>
    9199     * StringUtils.truncate(null, 0, 0) = null
    9200     * StringUtils.truncate(null, 2, 4) = null
    9201     * StringUtils.truncate("", 0, 10) = ""
    9202     * StringUtils.truncate("", 2, 10) = ""
    9203     * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
    9204     * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
    9205     * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
    9206     * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
    9207     * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
    9208     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
    9209     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
    9210     * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
    9211     * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
    9212     * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
    9213     * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
    9214     * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
    9215     * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
    9216     * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
    9217     * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
    9218     * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
    9219     * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
    9220     * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
    9221     * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
    9222     * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
    9223     * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
    9224     * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
    9225     * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
    9226     * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
    9227     * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
    9228     * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
    9229     * </pre>
    9230     *
    9231     * @param str  the String to truncate, may be null
    9232     * @param offset  left edge of source String
    9233     * @param maxWidth  maximum length of result String, must be positive
    9234     * @return truncated String, {@code null} if null String input
    9235     * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}
    9236     * @since 3.5
    9237     */
    9238    public static String truncate(final String str, final int offset, final int maxWidth) {
    9239        if (offset < 0) {
    9240            throw new IllegalArgumentException("offset cannot be negative");
    9241        }
    9242        if (maxWidth < 0) {
    9243            throw new IllegalArgumentException("maxWith cannot be negative");
    9244        }
    9245        if (str == null) {
    9246            return null;
    9247        }
    9248        if (offset > str.length()) {
    9249            return EMPTY;
    9250        }
    9251        if (str.length() > maxWidth) {
    9252            final int ix = Math.min(offset + maxWidth, str.length());
    9253            return str.substring(offset, ix);
    9254        }
    9255        return str.substring(offset);
    9256    }
    9257
    9258    /**
    9259     * <p>Uncapitalizes a String, changing the first character to lower case as
    9260     * per {@link Character#toLowerCase(int)}. No other characters are changed.</p>
    9261     *
    9262     * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}.
    9263     * A {@code null} input String returns {@code null}.</p>
    9264     *
    9265     * <pre>
    9266     * StringUtils.uncapitalize(null)  = null
    9267     * StringUtils.uncapitalize("")    = ""
    9268     * StringUtils.uncapitalize("cat") = "cat"
    9269     * StringUtils.uncapitalize("Cat") = "cat"
    9270     * StringUtils.uncapitalize("CAT") = "cAT"
    9271     * </pre>
    9272     *
    9273     * @param str the String to uncapitalize, may be null
    9274     * @return the uncapitalized String, {@code null} if null String input
    9275     * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String)
    9276     * @see #capitalize(String)
    9277     * @since 2.0
    9278     */
    9279    public static String uncapitalize(final String str) {
    9280        final int strLen = length(str);
    9281        if (strLen == 0) {
    9282            return str;
    9283        }
    9284
    9285        final int firstCodepoint = str.codePointAt(0);
    9286        final int newCodePoint = Character.toLowerCase(firstCodepoint);
    9287        if (firstCodepoint == newCodePoint) {
    9288            // already capitalized
    9289            return str;
    9290        }
    9291
    9292        final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
    9293        int outOffset = 0;
    9294        newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
    9295        for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
    9296            final int codepoint = str.codePointAt(inOffset);
    9297            newCodePoints[outOffset++] = codepoint; // copy the remaining ones
    9298            inOffset += Character.charCount(codepoint);
    9299         }
    9300        return new String(newCodePoints, 0, outOffset);
    9301    }
    9302
    9303    /**
    9304     * <p>
    9305     * Unwraps a given string from a character.
    9306     * </p>
    9307     *
    9308     * <pre>
    9309     * StringUtils.unwrap(null, null)         = null
    9310     * StringUtils.unwrap(null, '\0')         = null
    9311     * StringUtils.unwrap(null, '1')          = null
    9312     * StringUtils.unwrap("a", 'a')           = "a"
    9313     * StringUtils.unwrap("aa", 'a')           = ""
    9314     * StringUtils.unwrap("\'abc\'", '\'')    = "abc"
    9315     * StringUtils.unwrap("AABabcBAA", 'A')   = "ABabcBA"
    9316     * StringUtils.unwrap("A", '#')           = "A"
    9317     * StringUtils.unwrap("#A", '#')          = "#A"
    9318     * StringUtils.unwrap("A#", '#')          = "A#"
    9319     * </pre>
    9320     *
    9321     * @param str
    9322     *          the String to be unwrapped, can be null
    9323     * @param wrapChar
    9324     *          the character used to unwrap
    9325     * @return unwrapped String or the original string
    9326     *          if it is not quoted properly with the wrapChar
    9327     * @since 3.6
    9328     */
    9329    public static String unwrap(final String str, final char wrapChar) {
    9330        if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
    9331            return str;
    9332        }
    9333
    9334        if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
    9335            final int startIndex = 0;
    9336            final int endIndex = str.length() - 1;
    9337
    9338            return str.substring(startIndex + 1, endIndex);
    9339        }
    9340
    9341        return str;
    9342    }
    9343
    9344    /**
    9345     * <p>
    9346     * Unwraps a given string from anther string.
    9347     * </p>
    9348     *
    9349     * <pre>
    9350     * StringUtils.unwrap(null, null)         = null
    9351     * StringUtils.unwrap(null, "")           = null
    9352     * StringUtils.unwrap(null, "1")          = null
    9353     * StringUtils.unwrap("a", "a")           = "a"
    9354     * StringUtils.unwrap("aa", "a")          = ""
    9355     * StringUtils.unwrap("\'abc\'", "\'")    = "abc"
    9356     * StringUtils.unwrap("\"abc\"", "\"")    = "abc"
    9357     * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"
    9358     * StringUtils.unwrap("A", "#")           = "A"
    9359     * StringUtils.unwrap("#A", "#")          = "#A"
    9360     * StringUtils.unwrap("A#", "#")          = "A#"
    9361     * </pre>
    9362     *
    9363     * @param str
    9364     *          the String to be unwrapped, can be null
    9365     * @param wrapToken
    9366     *          the String used to unwrap
    9367     * @return unwrapped String or the original string
    9368     *          if it is not quoted properly with the wrapToken
    9369     * @since 3.6
    9370     */
    9371    public static String unwrap(final String str, final String wrapToken) {
    9372        if (isEmpty(str) || isEmpty(wrapToken) || str.length() == 1) {
    9373            return str;
    9374        }
    9375
    9376        if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) {
    9377            final int startIndex = str.indexOf(wrapToken);
    9378            final int endIndex = str.lastIndexOf(wrapToken);
    9379            final int wrapLength = wrapToken.length();
    9380
    9381            if (startIndex != -1 && endIndex != -1) {
    9382                return str.substring(startIndex + wrapLength, endIndex);
    9383            }
    9384        }
    9385
    9386        return str;
    9387    }
    9388
    9389    // Case conversion
    9390    //-----------------------------------------------------------------------
    9391    /**
    9392     * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
    9393     *
    9394     * <p>A {@code null} input String returns {@code null}.</p>
    9395     *
    9396     * <pre>
    9397     * StringUtils.upperCase(null)  = null
    9398     * StringUtils.upperCase("")    = ""
    9399     * StringUtils.upperCase("aBc") = "ABC"
    9400     * </pre>
    9401     *
    9402     * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
    9403     * the result of this method is affected by the current locale.
    9404     * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
    9405     * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
    9406     *
    9407     * @param str  the String to upper case, may be null
    9408     * @return the upper cased String, {@code null} if null String input
    9409     */
    9410    public static String upperCase(final String str) {
    9411        if (str == null) {
    9412            return null;
    9413        }
    9414        return str.toUpperCase();
    9415    }
    9416
    9417    /**
    9418     * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p>
    9419     *
    9420     * <p>A {@code null} input String returns {@code null}.</p>
    9421     *
    9422     * <pre>
    9423     * StringUtils.upperCase(null, Locale.ENGLISH)  = null
    9424     * StringUtils.upperCase("", Locale.ENGLISH)    = ""
    9425     * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
    9426     * </pre>
    9427     *
    9428     * @param str  the String to upper case, may be null
    9429     * @param locale  the locale that defines the case transformation rules, must not be null
    9430     * @return the upper cased String, {@code null} if null String input
    9431     * @since 2.5
    9432     */
    9433    public static String upperCase(final String str, final Locale locale) {
    9434        if (str == null) {
    9435            return null;
    9436        }
    9437        return str.toUpperCase(locale);
    9438    }
    9439
    9440    /**
    9441     * Returns the string representation of the {@code char} array or null.
    9442     *
    9443     * @param value the character array.
    9444     * @return a String or null
    9445     * @see String#valueOf(char[])
    9446     * @since 3.9
    9447     */
    9448    public static String valueOf(final char[] value) {
    9449        return value == null ? null : String.valueOf(value);
    9450    }
    9451
    9452    /**
    9453     * <p>
    9454     * Wraps a string with a char.
    9455     * </p>
    9456     *
    9457     * <pre>
    9458     * StringUtils.wrap(null, *)        = null
    9459     * StringUtils.wrap("", *)          = ""
    9460     * StringUtils.wrap("ab", '\0')     = "ab"
    9461     * StringUtils.wrap("ab", 'x')      = "xabx"
    9462     * StringUtils.wrap("ab", '\'')     = "'ab'"
    9463     * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
    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.4
    9472     */
    9473    public static String wrap(final String str, final char wrapWith) {
    9474
    9475        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
    9476            return str;
    9477        }
    9478
    9479        return wrapWith + str + wrapWith;
    9480    }
    9481
    9482    /**
    9483     * <p>
    9484     * Wraps a String with another String.
    9485     * </p>
    9486     *
    9487     * <p>
    9488     * A {@code null} input String returns {@code null}.
    9489     * </p>
    9490     *
    9491     * <pre>
    9492     * StringUtils.wrap(null, *)         = null
    9493     * StringUtils.wrap("", *)           = ""
    9494     * StringUtils.wrap("ab", null)      = "ab"
    9495     * StringUtils.wrap("ab", "x")       = "xabx"
    9496     * StringUtils.wrap("ab", "\"")      = "\"ab\""
    9497     * StringUtils.wrap("\"ab\"", "\"")  = "\"\"ab\"\""
    9498     * StringUtils.wrap("ab", "'")       = "'ab'"
    9499     * StringUtils.wrap("'abcd'", "'")   = "''abcd''"
    9500     * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
    9501     * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""
    9502     * </pre>
    9503     *
    9504     * @param str
    9505     *            the String to be wrapper, may be null
    9506     * @param wrapWith
    9507     *            the String that will wrap str
    9508     * @return wrapped String, {@code null} if null String input
    9509     * @since 3.4
    9510     */
    9511    public static String wrap(final String str, final String wrapWith) {
    9512
    9513        if (isEmpty(str) || isEmpty(wrapWith)) {
    9514            return str;
    9515        }
    9516
    9517        return wrapWith.concat(str).concat(wrapWith);
    9518    }
    9519
    9520    /**
    9521     * <p>
    9522     * Wraps a string with a char if that char is missing from the start or end of the given string.
    9523     * </p>
    9524     *
    9525     * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p>
    9526     *
    9527     * <pre>
    9528     * StringUtils.wrapIfMissing(null, *)        = null
    9529     * StringUtils.wrapIfMissing("", *)          = ""
    9530     * StringUtils.wrapIfMissing("ab", '\0')     = "ab"
    9531     * StringUtils.wrapIfMissing("ab", 'x')      = "xabx"
    9532     * StringUtils.wrapIfMissing("ab", '\'')     = "'ab'"
    9533     * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
    9534     * StringUtils.wrapIfMissing("/", '/')  = "/"
    9535     * StringUtils.wrapIfMissing("a/b/c", '/')  = "/a/b/c/"
    9536     * StringUtils.wrapIfMissing("/a/b/c", '/')  = "/a/b/c/"
    9537     * StringUtils.wrapIfMissing("a/b/c/", '/')  = "/a/b/c/"
    9538     * </pre>
    9539     *
    9540     * @param str
    9541     *            the string to be wrapped, may be {@code null}
    9542     * @param wrapWith
    9543     *            the char that will wrap {@code str}
    9544     * @return the wrapped string, or {@code null} if {@code str==null}
    9545     * @since 3.5
    9546     */
    9547    public static String wrapIfMissing(final String str, final char wrapWith) {
    9548        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
    9549            return str;
    9550        }
    9551        final boolean wrapStart = str.charAt(0) != wrapWith;
    9552        final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
    9553        if (!wrapStart && !wrapEnd) {
    9554            return str;
    9555        }
    9556
    9557        final StringBuilder builder = new StringBuilder(str.length() + 2);
    9558        if (wrapStart) {
    9559            builder.append(wrapWith);
    9560        }
    9561        builder.append(str);
    9562        if (wrapEnd) {
    9563            builder.append(wrapWith);
    9564        }
    9565        return builder.toString();
    9566    }
    9567
    9568    /**
    9569     * <p>
    9570     * Wraps a string with a string if that string is missing from the start or end of the given string.
    9571     * </p>
    9572     *
    9573     * <p>A new {@code String} will not be created if {@code str} is already wrapped.</p>
    9574     *
    9575     * <pre>
    9576     * StringUtils.wrapIfMissing(null, *)         = null
    9577     * StringUtils.wrapIfMissing("", *)           = ""
    9578     * StringUtils.wrapIfMissing("ab", null)      = "ab"
    9579     * StringUtils.wrapIfMissing("ab", "x")       = "xabx"
    9580     * StringUtils.wrapIfMissing("ab", "\"")      = "\"ab\""
    9581     * StringUtils.wrapIfMissing("\"ab\"", "\"")  = "\"ab\""
    9582     * StringUtils.wrapIfMissing("ab", "'")       = "'ab'"
    9583     * StringUtils.wrapIfMissing("'abcd'", "'")   = "'abcd'"
    9584     * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
    9585     * StringUtils.wrapIfMissing("'abcd'", "\"")  = "\"'abcd'\""
    9586     * StringUtils.wrapIfMissing("/", "/")  = "/"
    9587     * StringUtils.wrapIfMissing("a/b/c", "/")  = "/a/b/c/"
    9588     * StringUtils.wrapIfMissing("/a/b/c", "/")  = "/a/b/c/"
    9589     * StringUtils.wrapIfMissing("a/b/c/", "/")  = "/a/b/c/"
    9590     * </pre>
    9591     *
    9592     * @param str
    9593     *            the string to be wrapped, may be {@code null}
    9594     * @param wrapWith
    9595     *            the string that will wrap {@code str}
    9596     * @return the wrapped string, or {@code null} if {@code str==null}
    9597     * @since 3.5
    9598     */
    9599    public static String wrapIfMissing(final String str, final String wrapWith) {
    9600        if (isEmpty(str) || isEmpty(wrapWith)) {
    9601            return str;
    9602        }
    9603
    9604        final boolean wrapStart = !str.startsWith(wrapWith);
    9605        final boolean wrapEnd = !str.endsWith(wrapWith);
    9606        if (!wrapStart && !wrapEnd) {
    9607            return str;
    9608        }
    9609
    9610        final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
    9611        if (wrapStart) {
    9612            builder.append(wrapWith);
    9613        }
    9614        builder.append(str);
    9615        if (wrapEnd) {
    9616            builder.append(wrapWith);
    9617        }
    9618        return builder.toString();
    9619    }
    9620
    9621    /**
    9622     * <p>{@code StringUtils} instances should NOT be constructed in
    9623     * standard programming. Instead, the class should be used as
    9624     * {@code StringUtils.trim(" foo ");}.</p>
    9625     *
    9626     * <p>This constructor is public to permit tools that require a JavaBean
    9627     * instance to operate.</p>
    9628     */
    9629    public StringUtils() {
    9630        super();
    9631    }
    9632
    9633}