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