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 * https://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.lang3;
18
19 import java.io.UnsupportedEncodingException;
20 import java.nio.CharBuffer;
21 import java.nio.charset.Charset;
22 import java.text.Normalizer;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Objects;
29 import java.util.Set;
30 import java.util.function.Supplier;
31 import java.util.regex.Pattern;
32 import java.util.stream.Collectors;
33
34 import org.apache.commons.lang3.function.Suppliers;
35 import org.apache.commons.lang3.stream.LangCollectors;
36 import org.apache.commons.lang3.stream.Streams;
37
38 /**
39 * Operations on {@link String} that are
40 * {@code null} safe.
41 *
42 * <ul>
43 * <li><strong>IsEmpty/IsBlank</strong>
44 * - checks if a String contains text</li>
45 * <li><strong>Trim/Strip</strong>
46 * - removes leading and trailing whitespace</li>
47 * <li><strong>Equals/Compare</strong>
48 * - compares two strings in a null-safe manner</li>
49 * <li><strong>startsWith</strong>
50 * - check if a String starts with a prefix in a null-safe manner</li>
51 * <li><strong>endsWith</strong>
52 * - check if a String ends with a suffix in a null-safe manner</li>
53 * <li><strong>IndexOf/LastIndexOf/Contains</strong>
54 * - null-safe index-of checks</li>
55 * <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong>
56 * - index-of any of a set of Strings</li>
57 * <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong>
58 * - checks if String contains only/none/any of these characters</li>
59 * <li><strong>Substring/Left/Right/Mid</strong>
60 * - null-safe substring extractions</li>
61 * <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong>
62 * - substring extraction relative to other strings</li>
63 * <li><strong>Split/Join</strong>
64 * - splits a String into an array of substrings and vice versa</li>
65 * <li><strong>Remove/Delete</strong>
66 * - removes part of a String</li>
67 * <li><strong>Replace/Overlay</strong>
68 * - Searches a String and replaces one String with another</li>
69 * <li><strong>Chomp/Chop</strong>
70 * - removes the last part of a String</li>
71 * <li><strong>AppendIfMissing</strong>
72 * - appends a suffix to the end of the String if not present</li>
73 * <li><strong>PrependIfMissing</strong>
74 * - prepends a prefix to the start of the String if not present</li>
75 * <li><strong>LeftPad/RightPad/Center/Repeat</strong>
76 * - pads a String</li>
77 * <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong>
78 * - changes the case of a String</li>
79 * <li><strong>CountMatches</strong>
80 * - counts the number of occurrences of one String in another</li>
81 * <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong>
82 * - checks the characters in a String</li>
83 * <li><strong>DefaultString</strong>
84 * - protects against a null input String</li>
85 * <li><strong>Rotate</strong>
86 * - rotate (circular shift) a String</li>
87 * <li><strong>Reverse/ReverseDelimited</strong>
88 * - reverses a String</li>
89 * <li><strong>Abbreviate</strong>
90 * - abbreviates a string using ellipses or another given String</li>
91 * <li><strong>Difference</strong>
92 * - compares Strings and reports on their differences</li>
93 * <li><strong>LevenshteinDistance</strong>
94 * - the number of changes needed to change one String into another</li>
95 * </ul>
96 *
97 * <p>
98 * The {@link StringUtils} class defines certain words related to
99 * String handling.
100 * </p>
101 *
102 * <ul>
103 * <li>null - {@code null}</li>
104 * <li>empty - a zero-length string ({@code ""})</li>
105 * <li>space - the space character ({@code ' '}, char 32)</li>
106 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
107 * <li>trim - the characters <= 32 as in {@link String#trim()}</li>
108 * </ul>
109 *
110 * <p>
111 * {@link StringUtils} handles {@code null} input Strings quietly.
112 * That is to say that a {@code null} input will return {@code null}.
113 * Where a {@code boolean} or {@code int} is being returned
114 * details vary by method.
115 * </p>
116 *
117 * <p>
118 * A side effect of the {@code null} handling is that a
119 * {@link NullPointerException} should be considered a bug in
120 * {@link StringUtils}.
121 * </p>
122 *
123 * <p>
124 * Methods in this class include sample code in their Javadoc comments to explain their operation.
125 * The symbol {@code *} is used to indicate any input including {@code null}.
126 * </p>
127 *
128 * <p>
129 * #ThreadSafe#
130 * </p>
131 *
132 * @see String
133 * @since 1.0
134 */
135 //@Immutable
136 public class StringUtils {
137
138 // Performance testing notes (JDK 1.4, Jul03, scolebourne)
139 // Whitespace:
140 // Character.isWhitespace() is faster than WHITESPACE.indexOf()
141 // where WHITESPACE is a string of all whitespace characters
142 //
143 // Character access:
144 // String.charAt(n) versus toCharArray(), then array[n]
145 // String.charAt(n) is about 15% worse for a 10K string
146 // They are about equal for a length 50 string
147 // String.charAt(n) is about 4 times better for a length 3 string
148 // String.charAt(n) is best bet overall
149 //
150 // Append:
151 // String.concat about twice as fast as StringBuffer.append
152 // (not sure who tested this)
153
154 /**
155 * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 'â¦', this isn't it.
156 */
157 private static final String ELLIPSIS3 = "...";
158
159 /**
160 * A String for a space character.
161 *
162 * @since 3.2
163 */
164 public static final String SPACE = " ";
165
166 /**
167 * The empty String {@code ""}.
168 *
169 * @since 2.0
170 */
171 public static final String EMPTY = "";
172
173 /**
174 * The null String {@code null}. Package-private only.
175 */
176 static final String NULL = null;
177
178 /**
179 * A String for linefeed LF ("\n").
180 *
181 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
182 * for Character and String Literals</a>
183 * @since 3.2
184 */
185 public static final String LF = "\n";
186
187 /**
188 * A String for carriage return CR ("\r").
189 *
190 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
191 * for Character and String Literals</a>
192 * @since 3.2
193 */
194 public static final String CR = "\r";
195
196 /**
197 * Represents a failed index search.
198 *
199 * @since 2.1
200 */
201 public static final int INDEX_NOT_FOUND = -1;
202
203 /**
204 * The maximum size to which the padding constant(s) can expand.
205 */
206 private static final int PAD_LIMIT = 8192;
207
208 /**
209 * The default maximum depth at which recursive replacement will continue until no further search replacements are possible.
210 */
211 private static final int DEFAULT_TTL = 5;
212
213 /**
214 * Pattern used in {@link #stripAccents(String)}.
215 */
216 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$
217
218 /**
219 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "Now is the time for..."
220 *
221 * <p>
222 * Specifically:
223 * </p>
224 * <ul>
225 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li>
226 * <li>Else abbreviate it to {@code (substring(str, 0, max - 3) + "...")}.</li>
227 * <li>If {@code maxWidth} is less than {@code 4}, throw an {@link IllegalArgumentException}.</li>
228 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
229 * </ul>
230 *
231 * <pre>
232 * StringUtils.abbreviate(null, *) = null
233 * StringUtils.abbreviate("", 4) = ""
234 * StringUtils.abbreviate("abcdefg", 6) = "abc..."
235 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
236 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
237 * StringUtils.abbreviate("abcdefg", 4) = "a..."
238 * StringUtils.abbreviate("abcdefg", 3) = Throws {@link IllegalArgumentException}.
239 * </pre>
240 *
241 * @param str The String to check, may be null.
242 * @param maxWidth maximum length of result String, must be at least 4.
243 * @return abbreviated String, {@code null} if null String input.
244 * @throws IllegalArgumentException Thrown if the width is too small.
245 * @since 2.0
246 */
247 public static String abbreviate(final String str, final int maxWidth) {
248 return abbreviate(str, ELLIPSIS3, 0, maxWidth);
249 }
250
251 /**
252 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "...is the time for...".
253 *
254 * <p>
255 * Works like {@code abbreviate(String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to be the
256 * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result.
257 * </p>
258 * <p>
259 * In no case will it return a String of length greater than {@code maxWidth}.
260 * </p>
261 *
262 * <pre>
263 * StringUtils.abbreviate(null, *, *) = null
264 * StringUtils.abbreviate("", 0, 4) = ""
265 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
266 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..."
267 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..."
268 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..."
269 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..."
270 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..."
271 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno"
272 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
273 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
274 * StringUtils.abbreviate("abcdefghij", 0, 3) = Throws {@link IllegalArgumentException}.
275 * StringUtils.abbreviate("abcdefghij", 5, 6) = Throws {@link IllegalArgumentException}.
276 * </pre>
277 *
278 * @param str The String to check, may be null.
279 * @param offset left edge of source String.
280 * @param maxWidth maximum length of result String, must be at least 4.
281 * @return abbreviated String, {@code null} if null String input.
282 * @throws IllegalArgumentException Thrown if the width is too small.
283 * @since 2.0
284 */
285 public static String abbreviate(final String str, final int offset, final int maxWidth) {
286 return abbreviate(str, ELLIPSIS3, offset, maxWidth);
287 }
288
289 /**
290 * Abbreviates a String using another given String as replacement marker. This will convert "Now is the time for all good men" into "Now is the time for..."
291 * when "..." is the replacement marker.
292 *
293 * <p>
294 * Specifically:
295 * </p>
296 * <ul>
297 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li>
298 * <li>Else abbreviate it to {@code (substring(str, 0, max - abbrevMarker.length) + abbrevMarker)}.</li>
299 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li>
300 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
301 * </ul>
302 *
303 * <pre>
304 * StringUtils.abbreviate(null, "...", *) = null
305 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg"
306 * StringUtils.abbreviate("", "...", 4) = ""
307 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd."
308 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg"
309 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg"
310 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.."
311 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.."
312 * StringUtils.abbreviate("abcdefg", "..", 2) = Throws {@link IllegalArgumentException}.
313 * StringUtils.abbreviate("abcdefg", "...", 3) = Throws {@link IllegalArgumentException}.
314 * </pre>
315 *
316 * @param str The String to check, may be null.
317 * @param abbrevMarker The String used as replacement marker.
318 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}.
319 * @return abbreviated String, {@code null} if null String input.
320 * @throws IllegalArgumentException Thrown if the width is too small.
321 * @since 3.6
322 */
323 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
324 return abbreviate(str, abbrevMarker, 0, maxWidth);
325 }
326
327 /**
328 * Abbreviates a String using a given replacement marker. This will convert "Now is the time for all good men" into "...is the time for..." when "..." is
329 * the replacement marker.
330 * <p>
331 * Works like {@code abbreviate(String, String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to
332 * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result.
333 * </p>
334 * <p>
335 * In no case will it return a String of length greater than {@code maxWidth}.
336 * </p>
337 *
338 * <pre>
339 * StringUtils.abbreviate(null, null, *, *) = null
340 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno"
341 * StringUtils.abbreviate("", "...", 0, 4) = ""
342 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
343 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi,"
344 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi,"
345 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi,"
346 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::"
347 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..."
348 * StringUtils.abbreviate("abcdefghijklmno", "â¦", 6, 10) = "â¦ghijklmno"
349 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno"
350 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno"
351 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno"
352 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = Throws {@link IllegalArgumentException}.
353 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = Throws {@link IllegalArgumentException}.
354 * </pre>
355 *
356 * @param str The String to check, may be null.
357 * @param abbrevMarker The String used as replacement marker, for example "...", or Unicode HORIZONTAL ELLIPSIS, U+2026 'â¦'.
358 * @param offset left edge of source String.
359 * @param maxWidth maximum length of result String, must be at least 4.
360 * @return abbreviated String, {@code null} if null String input.
361 * @throws IllegalArgumentException Thrown if the width is too small.
362 * @since 3.6
363 */
364 public static String abbreviate(final String str, String abbrevMarker, final int offset, final int maxWidth) {
365 if (isEmpty(str)) {
366 return str;
367 }
368 if (abbrevMarker == null) {
369 abbrevMarker = EMPTY;
370 }
371 final int abbrevMarkerLength = abbrevMarker.length();
372 final int minAbbrevWidth = abbrevMarkerLength + 1;
373 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;
374
375 if (maxWidth < minAbbrevWidth) {
376 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
377 }
378 final int strLen = str.length();
379 if (strLen <= maxWidth) {
380 return str;
381 }
382 if (strLen - offset <= maxWidth - abbrevMarkerLength) {
383 int tailStart = strLen - (maxWidth - abbrevMarkerLength);
384 if (splitsSurrogatePair(str, tailStart)) {
385 tailStart++;
386 }
387 return abbrevMarker + str.substring(tailStart);
388 }
389 if (offset <= abbrevMarkerLength + 1) {
390 int headEnd = maxWidth - abbrevMarkerLength;
391 if (splitsSurrogatePair(str, headEnd)) {
392 headEnd--;
393 }
394 return str.substring(0, headEnd) + abbrevMarker;
395 }
396 if (maxWidth < minAbbrevWidthOffset) {
397 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
398 }
399 int from = offset;
400 if (splitsSurrogatePair(str, from)) {
401 from++;
402 }
403 return abbrevMarker + abbreviate(str.substring(from), abbrevMarker, maxWidth - abbrevMarkerLength);
404 }
405
406 /**
407 * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String.
408 *
409 * <p>
410 * This abbreviation only occurs if the following criteria is met:
411 * </p>
412 * <ul>
413 * <li>Neither the String for abbreviation nor the replacement String are null or empty</li>
414 * <li>The length to truncate to is less than the length of the supplied String</li>
415 * <li>The length to truncate to is greater than 0</li>
416 * <li>The abbreviated String will have enough room for the length supplied replacement String and the first and last characters of the supplied String for
417 * abbreviation</li>
418 * </ul>
419 * <p>
420 * Otherwise, the returned String will be the same as the supplied String for abbreviation.
421 * </p>
422 *
423 * <pre>
424 * StringUtils.abbreviateMiddle(null, null, 0) = null
425 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc"
426 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc"
427 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc"
428 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
429 * </pre>
430 *
431 * @param str The String to abbreviate, may be null.
432 * @param middle The String to replace the middle characters with, may be null.
433 * @param length The length to abbreviate {@code str} to.
434 * @return The abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
435 * @since 2.5
436 */
437 public static String abbreviateMiddle(final String str, final String middle, final int length) {
438 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) {
439 return str;
440 }
441 final int targetString = length - middle.length();
442 int startOffset = targetString / 2 + targetString % 2;
443 int endOffset = str.length() - targetString / 2;
444 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate
445 if (splitsSurrogatePair(str, startOffset)) {
446 startOffset--;
447 }
448 if (splitsSurrogatePair(str, endOffset)) {
449 endOffset++;
450 }
451 return str.substring(0, startOffset) + middle + str.substring(endOffset);
452 }
453
454 /**
455 * Appends the suffix to the end of the string if the string does not already end with any of the suffixes.
456 *
457 * <pre>
458 * StringUtils.appendIfMissing(null, null) = null
459 * StringUtils.appendIfMissing("abc", null) = "abc"
460 * StringUtils.appendIfMissing("", "xyz") = "xyz"
461 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz"
462 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
463 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
464 * </pre>
465 * <p>
466 * With additional suffixes,
467 * </p>
468 *
469 * <pre>
470 * StringUtils.appendIfMissing(null, null, null) = null
471 * StringUtils.appendIfMissing("abc", null, null) = "abc"
472 * StringUtils.appendIfMissing("", "xyz", null) = "xyz"
473 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
474 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc"
475 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz"
476 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
477 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
478 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
479 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
480 * </pre>
481 *
482 * @param str The string.
483 * @param suffix The suffix to append to the end of the string.
484 * @param suffixes Additional suffixes that are valid terminators.
485 * @return A new String if suffix was appended, the same string otherwise.
486 * @since 3.2
487 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}.
488 */
489 @Deprecated
490 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
491 return Strings.CS.appendIfMissing(str, suffix, suffixes);
492 }
493
494 /**
495 * Appends the suffix to the end of the string if the string does not
496 * already end, case-insensitive, with any of the suffixes.
497 *
498 * <pre>
499 * StringUtils.appendIfMissingIgnoreCase(null, null) = null
500 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc"
501 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz"
502 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz"
503 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
504 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
505 * </pre>
506 * <p>
507 * With additional suffixes,
508 * </p>
509 * <pre>
510 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null
511 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc"
512 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz"
513 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
514 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc"
515 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz"
516 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
517 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
518 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
519 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
520 * </pre>
521 *
522 * @param str The string.
523 * @param suffix The suffix to append to the end of the string.
524 * @param suffixes Additional suffixes that are valid terminators.
525 * @return A new String if suffix was appended, the same string otherwise.
526 * @since 3.2
527 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}.
528 */
529 @Deprecated
530 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
531 return Strings.CI.appendIfMissing(str, suffix, suffixes);
532 }
533
534 /**
535 * Computes the capacity required for a StringBuilder to hold {@code items} of {@code maxElementChars} characters plus the separators between them. The
536 * separator is assumed to be 1 character.
537 *
538 * @param count The number of items.
539 * @param maxElementChars The maximum number of characters per item.
540 * @return A StringBuilder with the appropriate capacity.
541 */
542 private static StringBuilder capacity(final int count, final byte maxElementChars) {
543 return new StringBuilder(count * maxElementChars + count - 1);
544 }
545
546 /**
547 * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed.
548 *
549 * <p>
550 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}.
551 * </p>
552 *
553 * <pre>
554 * StringUtils.capitalize(null) = null
555 * StringUtils.capitalize("") = ""
556 * StringUtils.capitalize("cat") = "Cat"
557 * StringUtils.capitalize("cAt") = "CAt"
558 * StringUtils.capitalize("'cat'") = "'cat'"
559 * </pre>
560 *
561 * @param str The String to capitalize, may be null.
562 * @return The capitalized String, {@code null} if null String input.
563 * @see org.apache.commons.text.WordUtils#capitalize(String)
564 * @see #uncapitalize(String)
565 * @since 2.0
566 */
567 public static String capitalize(final String str) {
568 if (isEmpty(str)) {
569 return str;
570 }
571 final int firstCodepoint = str.codePointAt(0);
572 final int newCodePoint = Character.toTitleCase(firstCodepoint);
573 if (firstCodepoint == newCodePoint) {
574 // already capitalized
575 return str;
576 }
577 final int[] newCodePoints = str.codePoints().toArray();
578 newCodePoints[0] = newCodePoint; // copy the first code point
579 return new String(newCodePoints, 0, newCodePoints.length);
580 }
581
582 /**
583 * Centers a String in a larger String of size {@code size} using the space character (' ').
584 *
585 * <p>
586 * If the size is less than the String length, the original String is returned. A {@code null} String returns {@code null}. A negative size is treated as
587 * zero.
588 * </p>
589 *
590 * <p>
591 * Equivalent to {@code center(str, size, " ")}.
592 * </p>
593 *
594 * <pre>
595 * StringUtils.center(null, *) = null
596 * StringUtils.center("", 4) = " "
597 * StringUtils.center("ab", -1) = "ab"
598 * StringUtils.center("ab", 4) = " ab "
599 * StringUtils.center("abcd", 2) = "abcd"
600 * StringUtils.center("a", 4) = " a "
601 * </pre>
602 *
603 * @param str The String to center, may be null.
604 * @param size The int size of new String, negative treated as zero.
605 * @return centered String, {@code null} if null String input.
606 */
607 public static String center(final String str, final int size) {
608 return center(str, size, ' ');
609 }
610
611 /**
612 * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with.
613 *
614 * <p>
615 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero.
616 * </p>
617 *
618 * <pre>
619 * StringUtils.center(null, *, *) = null
620 * StringUtils.center("", 4, ' ') = " "
621 * StringUtils.center("ab", -1, ' ') = "ab"
622 * StringUtils.center("ab", 4, ' ') = " ab "
623 * StringUtils.center("abcd", 2, ' ') = "abcd"
624 * StringUtils.center("a", 4, ' ') = " a "
625 * StringUtils.center("a", 4, 'y') = "yayy"
626 * </pre>
627 *
628 * @param str The String to center, may be null.
629 * @param size The int size of new String, negative treated as zero.
630 * @param padChar The character to pad the new String with.
631 * @return centered String, {@code null} if null String input.
632 * @since 2.0
633 */
634 public static String center(String str, final int size, final char padChar) {
635 if (str == null || size <= 0) {
636 return str;
637 }
638 final int strLen = str.length();
639 final int pads = size - strLen;
640 if (pads <= 0) {
641 return str;
642 }
643 str = leftPad(str, strLen + pads / 2, padChar);
644 return rightPad(str, size, padChar);
645 }
646
647 /**
648 * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with.
649 *
650 * <p>
651 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero.
652 * </p>
653 *
654 * <pre>
655 * StringUtils.center(null, *, *) = null
656 * StringUtils.center("", 4, " ") = " "
657 * StringUtils.center("ab", -1, " ") = "ab"
658 * StringUtils.center("ab", 4, " ") = " ab "
659 * StringUtils.center("abcd", 2, " ") = "abcd"
660 * StringUtils.center("a", 4, " ") = " a "
661 * StringUtils.center("a", 4, "yz") = "yayz"
662 * StringUtils.center("abc", 7, null) = " abc "
663 * StringUtils.center("abc", 7, "") = " abc "
664 * </pre>
665 *
666 * @param str The String to center, may be null.
667 * @param size The int size of new String, negative treated as zero.
668 * @param padStr The String to pad the new String with, must not be null or empty.
669 * @return centered String, {@code null} if null String input.
670 * @throws IllegalArgumentException Thrown if padStr is {@code null} or empty.
671 */
672 public static String center(String str, final int size, String padStr) {
673 if (str == null || size <= 0) {
674 return str;
675 }
676 if (isEmpty(padStr)) {
677 padStr = SPACE;
678 }
679 final int strLen = str.length();
680 final int pads = size - strLen;
681 if (pads <= 0) {
682 return str;
683 }
684 str = leftPad(str, strLen + pads / 2, padStr);
685 return rightPad(str, size, padStr);
686 }
687
688 private static void checkFromToIndex(final int startIndex, final int endIndex, final int length) {
689 if (startIndex < 0) {
690 throw new ArrayIndexOutOfBoundsException(startIndex);
691 }
692 if (endIndex > length) {
693 throw new ArrayIndexOutOfBoundsException(endIndex);
694 }
695 }
696
697 /**
698 * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is "{@code \n}", "{@code \r}", or
699 * "{@code \r\n}".
700 *
701 * <p>
702 * NOTE: This method changed in 2.0. It now more closely matches Perl chomp.
703 * </p>
704 *
705 * <pre>
706 * StringUtils.chomp(null) = null
707 * StringUtils.chomp("") = ""
708 * StringUtils.chomp("abc \r") = "abc "
709 * StringUtils.chomp("abc\n") = "abc"
710 * StringUtils.chomp("abc\r\n") = "abc"
711 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
712 * StringUtils.chomp("abc\n\r") = "abc\n"
713 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc"
714 * StringUtils.chomp("\r") = ""
715 * StringUtils.chomp("\n") = ""
716 * StringUtils.chomp("\r\n") = ""
717 * </pre>
718 *
719 * @param str The String to chomp a newline from, may be null.
720 * @return String without newline, {@code null} if null String input.
721 */
722 public static String chomp(final String str) {
723 if (isEmpty(str)) {
724 return str;
725 }
726 if (str.length() == 1) {
727 final char ch = str.charAt(0);
728 if (ch == CharUtils.CR || ch == CharUtils.LF) {
729 return EMPTY;
730 }
731 return str;
732 }
733 int lastIdx = str.length() - 1;
734 final char last = str.charAt(lastIdx);
735 if (last == CharUtils.LF) {
736 if (str.charAt(lastIdx - 1) == CharUtils.CR) {
737 lastIdx--;
738 }
739 } else if (last != CharUtils.CR) {
740 lastIdx++;
741 }
742 return str.substring(0, lastIdx);
743 }
744
745 /**
746 * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone.
747 *
748 * <p>
749 * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use
750 * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}.
751 * </p>
752 *
753 * <pre>
754 * StringUtils.chomp(null, *) = null
755 * StringUtils.chomp("", *) = ""
756 * StringUtils.chomp("foobar", "bar") = "foo"
757 * StringUtils.chomp("foobar", "baz") = "foobar"
758 * StringUtils.chomp("foo", "foo") = ""
759 * StringUtils.chomp("foo ", "foo") = "foo "
760 * StringUtils.chomp(" foo", "foo") = " "
761 * StringUtils.chomp("foo", "foooo") = "foo"
762 * StringUtils.chomp("foo", "") = "foo"
763 * StringUtils.chomp("foo", null) = "foo"
764 * </pre>
765 *
766 * @param str The String to chomp from, may be null.
767 * @param separator separator String, may be null.
768 * @return String without trailing separator, {@code null} if null String input.
769 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead.
770 */
771 @Deprecated
772 public static String chomp(final String str, final String separator) {
773 return Strings.CS.removeEnd(str, separator);
774 }
775
776 /**
777 * Removes the last character from a String.
778 *
779 * <p>
780 * If the String ends in {@code \r\n}, then remove both of them.
781 * </p>
782 *
783 * <pre>
784 * StringUtils.chop(null) = null
785 * StringUtils.chop("") = ""
786 * StringUtils.chop("abc \r") = "abc "
787 * StringUtils.chop("abc\n") = "abc"
788 * StringUtils.chop("abc\r\n") = "abc"
789 * StringUtils.chop("abc") = "ab"
790 * StringUtils.chop("abc\nabc") = "abc\nab"
791 * StringUtils.chop("a") = ""
792 * StringUtils.chop("\r") = ""
793 * StringUtils.chop("\n") = ""
794 * StringUtils.chop("\r\n") = ""
795 * </pre>
796 *
797 * @param str The String to chop last character from, may be null.
798 * @return String without last character, {@code null} if null String input.
799 */
800 public static String chop(final String str) {
801 if (str == null) {
802 return null;
803 }
804 final int strLen = str.length();
805 if (strLen < 2) {
806 return EMPTY;
807 }
808 final int lastIdx = strLen - 1;
809 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate
810 if (splitsSurrogatePair(str, lastIdx)) {
811 return str.substring(0, lastIdx - 1);
812 }
813 final String ret = str.substring(0, lastIdx);
814 final char last = str.charAt(lastIdx);
815 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
816 return ret.substring(0, lastIdx - 1);
817 }
818 return ret;
819 }
820
821 /**
822 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
823 * <ul>
824 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
825 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
826 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
827 * </ul>
828 *
829 * <p>
830 * This is a {@code null} safe version of:
831 * </p>
832 *
833 * <pre>
834 * str1.compareTo(str2)
835 * </pre>
836 *
837 * <p>
838 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal.
839 * </p>
840 *
841 * <pre>{@code
842 * StringUtils.compare(null, null) = 0
843 * StringUtils.compare(null , "a") < 0
844 * StringUtils.compare("a", null) > 0
845 * StringUtils.compare("abc", "abc") = 0
846 * StringUtils.compare("a", "b") < 0
847 * StringUtils.compare("b", "a") > 0
848 * StringUtils.compare("a", "B") > 0
849 * StringUtils.compare("ab", "abc") < 0
850 * }</pre>
851 *
852 * @param str1 The String to compare from.
853 * @param str2 The String to compare to.
854 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2}.
855 * @see #compare(String, String, boolean)
856 * @see String#compareTo(String)
857 * @since 3.5
858 * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}.
859 */
860 @Deprecated
861 public static int compare(final String str1, final String str2) {
862 return Strings.CS.compare(str1, str2);
863 }
864
865 /**
866 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
867 * <ul>
868 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
869 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
870 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
871 * </ul>
872 *
873 * <p>
874 * This is a {@code null} safe version of :
875 * </p>
876 *
877 * <pre>
878 * str1.compareTo(str2)
879 * </pre>
880 *
881 * <p>
882 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal.
883 * </p>
884 *
885 * <pre>{@code
886 * StringUtils.compare(null, null, *) = 0
887 * StringUtils.compare(null , "a", true) < 0
888 * StringUtils.compare(null , "a", false) > 0
889 * StringUtils.compare("a", null, true) > 0
890 * StringUtils.compare("a", null, false) < 0
891 * StringUtils.compare("abc", "abc", *) = 0
892 * StringUtils.compare("a", "b", *) < 0
893 * StringUtils.compare("b", "a", *) > 0
894 * StringUtils.compare("a", "B", *) > 0
895 * StringUtils.compare("ab", "abc", *) < 0
896 * }</pre>
897 *
898 * @param str1 The String to compare from.
899 * @param str2 The String to compare to.
900 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value.
901 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}.
902 * @see String#compareTo(String)
903 * @since 3.5
904 */
905 public static int compare(final String str1, final String str2, final boolean nullIsLess) {
906 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
907 return 0;
908 }
909 if (str1 == null) {
910 return nullIsLess ? -1 : 1;
911 }
912 if (str2 == null) {
913 return nullIsLess ? 1 : -1;
914 }
915 return str1.compareTo(str2);
916 }
917
918 /**
919 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning :
920 * <ul>
921 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
922 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
923 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
924 * </ul>
925 *
926 * <p>
927 * This is a {@code null} safe version of:
928 * </p>
929 *
930 * <pre>
931 * str1.compareToIgnoreCase(str2)
932 * </pre>
933 *
934 * <p>
935 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive.
936 * </p>
937 *
938 * <pre>{@code
939 * StringUtils.compareIgnoreCase(null, null) = 0
940 * StringUtils.compareIgnoreCase(null , "a") < 0
941 * StringUtils.compareIgnoreCase("a", null) > 0
942 * StringUtils.compareIgnoreCase("abc", "abc") = 0
943 * StringUtils.compareIgnoreCase("abc", "ABC") = 0
944 * StringUtils.compareIgnoreCase("a", "b") < 0
945 * StringUtils.compareIgnoreCase("b", "a") > 0
946 * StringUtils.compareIgnoreCase("a", "B") < 0
947 * StringUtils.compareIgnoreCase("A", "b") < 0
948 * StringUtils.compareIgnoreCase("ab", "ABC") < 0
949 * }</pre>
950 *
951 * @param str1 The String to compare from.
952 * @param str2 The String to compare to.
953 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences.
954 * @see #compareIgnoreCase(String, String, boolean)
955 * @see String#compareToIgnoreCase(String)
956 * @since 3.5
957 * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}.
958 */
959 @Deprecated
960 public static int compareIgnoreCase(final String str1, final String str2) {
961 return Strings.CI.compare(str1, str2);
962 }
963
964 /**
965 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning :
966 * <ul>
967 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
968 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
969 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
970 * </ul>
971 *
972 * <p>
973 * This is a {@code null} safe version of :
974 * </p>
975 * <pre>
976 * str1.compareToIgnoreCase(str2)
977 * </pre>
978 *
979 * <p>
980 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case
981 * insensitive.
982 * </p>
983 *
984 * <pre>{@code
985 * StringUtils.compareIgnoreCase(null, null, *) = 0
986 * StringUtils.compareIgnoreCase(null , "a", true) < 0
987 * StringUtils.compareIgnoreCase(null , "a", false) > 0
988 * StringUtils.compareIgnoreCase("a", null, true) > 0
989 * StringUtils.compareIgnoreCase("a", null, false) < 0
990 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0
991 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0
992 * StringUtils.compareIgnoreCase("a", "b", *) < 0
993 * StringUtils.compareIgnoreCase("b", "a", *) > 0
994 * StringUtils.compareIgnoreCase("a", "B", *) < 0
995 * StringUtils.compareIgnoreCase("A", "b", *) < 0
996 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0
997 * }</pre>
998 *
999 * @param str1 The String to compare from.
1000 * @param str2 The String to compare to.
1001 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value.
1002 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences.
1003 * @see String#compareToIgnoreCase(String)
1004 * @since 3.5
1005 */
1006 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
1007 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
1008 return 0;
1009 }
1010 if (str1 == null) {
1011 return nullIsLess ? -1 : 1;
1012 }
1013 if (str2 == null) {
1014 return nullIsLess ? 1 : -1;
1015 }
1016 return str1.compareToIgnoreCase(str2);
1017 }
1018
1019 /**
1020 * Tests if CharSequence contains a search CharSequence, handling {@code null}.
1021 * This method uses {@link String#indexOf(String)} if possible.
1022 *
1023 * <p>
1024 * A {@code null} CharSequence will return {@code false}.
1025 * </p>
1026 *
1027 * <pre>
1028 * StringUtils.contains(null, *) = false
1029 * StringUtils.contains(*, null) = false
1030 * StringUtils.contains("", "") = true
1031 * StringUtils.contains("abc", "") = true
1032 * StringUtils.contains("abc", "a") = true
1033 * StringUtils.contains("abc", "z") = false
1034 * </pre>
1035 *
1036 * @param seq The CharSequence to check, may be null
1037 * @param searchSeq The CharSequence to find, may be null
1038 * @return true if the CharSequence contains the search CharSequence,
1039 * false if not or {@code null} string input
1040 * @since 2.0
1041 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
1042 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}.
1043 */
1044 @Deprecated
1045 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
1046 return Strings.CS.contains(seq, searchSeq);
1047 }
1048
1049 /**
1050 * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible.
1051 *
1052 * <p>
1053 * A {@code null} or empty ("") CharSequence will return {@code false}.
1054 * </p>
1055 *
1056 * <pre>
1057 * StringUtils.contains(null, *) = false
1058 * StringUtils.contains("", *) = false
1059 * StringUtils.contains("abc", 'a') = true
1060 * StringUtils.contains("abc", 'z') = false
1061 * </pre>
1062 *
1063 * @param seq The CharSequence to check, may be null
1064 * @param searchChar The character to find
1065 * @return true if the CharSequence contains the search character, false if not or {@code null} string input
1066 * @since 2.0
1067 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
1068 */
1069 public static boolean contains(final CharSequence seq, final int searchChar) {
1070 if (isEmpty(seq)) {
1071 return false;
1072 }
1073 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
1074 }
1075
1076 /**
1077 * Tests if the CharSequence contains any character in the given set of characters.
1078 *
1079 * <p>
1080 * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}.
1081 * </p>
1082 *
1083 * <pre>
1084 * StringUtils.containsAny(null, *) = false
1085 * StringUtils.containsAny("", *) = false
1086 * StringUtils.containsAny(*, null) = false
1087 * StringUtils.containsAny(*, []) = false
1088 * StringUtils.containsAny("zzabyycdxx", 'z', 'a') = true
1089 * StringUtils.containsAny("zzabyycdxx", 'b', 'y') = true
1090 * StringUtils.containsAny("zzabyycdxx", 'z', 'y') = true
1091 * StringUtils.containsAny("aba", 'z]) = false
1092 * </pre>
1093 *
1094 * @param cs The CharSequence to check, may be null.
1095 * @param searchChars The chars to search for, may be null.
1096 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input.
1097 * @since 2.4
1098 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
1099 */
1100 public static boolean containsAny(final CharSequence cs, final char... searchChars) {
1101 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
1102 return false;
1103 }
1104 final int csLength = cs.length();
1105 final int searchLength = searchChars.length;
1106 final int csLast = csLength - 1;
1107 final int searchLast = searchLength - 1;
1108 for (int i = 0; i < csLength; i++) {
1109 final char ch = cs.charAt(i);
1110 for (int j = 0; j < searchLength; j++) {
1111 if (searchChars[j] == ch) {
1112 if (Character.isHighSurrogate(ch)
1113 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)
1114 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) {
1115 return true;
1116 }
1117 }
1118 }
1119 }
1120 return false;
1121 }
1122
1123 /**
1124 * Tests if the CharSequence contains any character in the given set of characters.
1125 *
1126 * <p>
1127 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}.
1128 * </p>
1129 *
1130 * <pre>
1131 * StringUtils.containsAny(null, *) = false
1132 * StringUtils.containsAny("", *) = false
1133 * StringUtils.containsAny(*, null) = false
1134 * StringUtils.containsAny(*, "") = false
1135 * StringUtils.containsAny("zzabyycdxx", "za") = true
1136 * StringUtils.containsAny("zzabyycdxx", "by") = true
1137 * StringUtils.containsAny("zzabyycdxx", "zy") = true
1138 * StringUtils.containsAny("zzabyycdxx", "\tx") = true
1139 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
1140 * StringUtils.containsAny("aba", "z") = false
1141 * </pre>
1142 *
1143 * @param cs The CharSequence to check, may be null.
1144 * @param searchChars The chars to search for, may be null.
1145 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input.
1146 * @since 2.4
1147 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
1148 */
1149 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
1150 if (searchChars == null) {
1151 return false;
1152 }
1153 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
1154 }
1155
1156 /**
1157 * Tests if the CharSequence contains any of the CharSequences in the given array.
1158 *
1159 * <p>
1160 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
1161 * return {@code false}.
1162 * </p>
1163 *
1164 * <pre>
1165 * StringUtils.containsAny(null, *) = false
1166 * StringUtils.containsAny("", *) = false
1167 * StringUtils.containsAny(*, null) = false
1168 * StringUtils.containsAny(*, []) = false
1169 * StringUtils.containsAny("abcd", "ab", null) = true
1170 * StringUtils.containsAny("abcd", "ab", "cd") = true
1171 * StringUtils.containsAny("abc", "d", "abc") = true
1172 * </pre>
1173 *
1174 * @param cs The CharSequence to check, may be null.
1175 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
1176 * null as well.
1177 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise.
1178 * @since 3.4
1179 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}.
1180 */
1181 @Deprecated
1182 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
1183 return Strings.CS.containsAny(cs, searchCharSequences);
1184 }
1185
1186 /**
1187 * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case.
1188 *
1189 * <p>
1190 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
1191 * return {@code false}.
1192 * </p>
1193 *
1194 * <pre>
1195 * StringUtils.containsAny(null, *) = false
1196 * StringUtils.containsAny("", *) = false
1197 * StringUtils.containsAny(*, null) = false
1198 * StringUtils.containsAny(*, []) = false
1199 * StringUtils.containsAny("abcd", "ab", null) = true
1200 * StringUtils.containsAny("abcd", "ab", "cd") = true
1201 * StringUtils.containsAny("abc", "d", "abc") = true
1202 * StringUtils.containsAny("abc", "D", "ABC") = true
1203 * StringUtils.containsAny("ABC", "d", "abc") = true
1204 * </pre>
1205 *
1206 * @param cs The CharSequence to check, may be null.
1207 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
1208 * null as well.
1209 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
1210 * @since 3.12.0
1211 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}.
1212 */
1213 @Deprecated
1214 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) {
1215 return Strings.CI.containsAny(cs, searchCharSequences);
1216 }
1217
1218 /**
1219 * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by
1220 * {@link String#equalsIgnoreCase(String)}.
1221 *
1222 * <p>
1223 * A {@code null} CharSequence will return {@code false}.
1224 * </p>
1225 *
1226 * <pre>
1227 * StringUtils.containsIgnoreCase(null, *) = false
1228 * StringUtils.containsIgnoreCase(*, null) = false
1229 * StringUtils.containsIgnoreCase("", "") = true
1230 * StringUtils.containsIgnoreCase("abc", "") = true
1231 * StringUtils.containsIgnoreCase("abc", "a") = true
1232 * StringUtils.containsIgnoreCase("abc", "z") = false
1233 * StringUtils.containsIgnoreCase("abc", "A") = true
1234 * StringUtils.containsIgnoreCase("abc", "Z") = false
1235 * </pre>
1236 *
1237 * @param str The CharSequence to check, may be null.
1238 * @param searchStr The CharSequence to find, may be null.
1239 * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input.
1240 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence).
1241 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}.
1242 */
1243 @Deprecated
1244 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
1245 return Strings.CI.contains(str, searchStr);
1246 }
1247
1248 /**
1249 * Tests that the CharSequence does not contain certain characters.
1250 *
1251 * <p>
1252 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0)
1253 * always returns true.
1254 * </p>
1255 *
1256 * <pre>
1257 * StringUtils.containsNone(null, *) = true
1258 * StringUtils.containsNone(*, null) = true
1259 * StringUtils.containsNone("", *) = true
1260 * StringUtils.containsNone("ab", '') = true
1261 * StringUtils.containsNone("abab", 'x', 'y', 'z') = true
1262 * StringUtils.containsNone("ab1", 'x', 'y', 'z') = true
1263 * StringUtils.containsNone("abz", 'x', 'y', 'z') = false
1264 * </pre>
1265 *
1266 * @param cs The CharSequence to check, may be null.
1267 * @param searchChars An array of invalid chars, may be null.
1268 * @return true if it contains none of the invalid chars, or is null.
1269 * @since 2.0
1270 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
1271 */
1272 public static boolean containsNone(final CharSequence cs, final char... searchChars) {
1273 if (cs == null || searchChars == null) {
1274 return true;
1275 }
1276 final int csLen = cs.length();
1277 final int csLast = csLen - 1;
1278 final int searchLen = searchChars.length;
1279 final int searchLast = searchLen - 1;
1280 for (int i = 0; i < csLen; i++) {
1281 final char ch = cs.charAt(i);
1282 for (int j = 0; j < searchLen; j++) {
1283 if (searchChars[j] == ch) {
1284 if (Character.isHighSurrogate(ch)
1285 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)
1286 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) {
1287 return false;
1288 }
1289 }
1290 }
1291 }
1292 return true;
1293 }
1294
1295 /**
1296 * Tests that the CharSequence does not contain certain characters.
1297 *
1298 * <p>
1299 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always
1300 * returns true.
1301 * </p>
1302 *
1303 * <pre>
1304 * StringUtils.containsNone(null, *) = true
1305 * StringUtils.containsNone(*, null) = true
1306 * StringUtils.containsNone("", *) = true
1307 * StringUtils.containsNone("ab", "") = true
1308 * StringUtils.containsNone("abab", "xyz") = true
1309 * StringUtils.containsNone("ab1", "xyz") = true
1310 * StringUtils.containsNone("abz", "xyz") = false
1311 * </pre>
1312 *
1313 * @param cs The CharSequence to check, may be null.
1314 * @param invalidChars A String of invalid chars, may be null.
1315 * @return true if it contains none of the invalid chars, or is null.
1316 * @since 2.0
1317 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
1318 */
1319 public static boolean containsNone(final CharSequence cs, final String invalidChars) {
1320 if (invalidChars == null) {
1321 return true;
1322 }
1323 return containsNone(cs, invalidChars.toCharArray());
1324 }
1325
1326 /**
1327 * Tests if the CharSequence contains only certain characters.
1328 *
1329 * <p>
1330 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0)
1331 * always returns {@code true}.
1332 * </p>
1333 *
1334 * <pre>
1335 * StringUtils.containsOnly(null, *) = false
1336 * StringUtils.containsOnly(*, null) = false
1337 * StringUtils.containsOnly("", *) = true
1338 * StringUtils.containsOnly("ab", '') = false
1339 * StringUtils.containsOnly("abab", 'a', 'b', 'c') = true
1340 * StringUtils.containsOnly("ab1", 'a', 'b', 'c') = false
1341 * StringUtils.containsOnly("abz", 'a', 'b', 'c') = false
1342 * </pre>
1343 *
1344 * @param cs The String to check, may be null.
1345 * @param valid An array of valid chars, may be null.
1346 * @return true if it only contains valid chars and is non-null.
1347 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
1348 */
1349 public static boolean containsOnly(final CharSequence cs, final char... valid) {
1350 // All these pre-checks are to maintain API with an older version
1351 if (valid == null || cs == null) {
1352 return false;
1353 }
1354 if (isEmpty(cs)) {
1355 return true;
1356 }
1357 if (valid.length == 0) {
1358 return false;
1359 }
1360 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
1361 }
1362
1363 /**
1364 * Tests if the CharSequence contains only certain characters.
1365 *
1366 * <p>
1367 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0)
1368 * always returns {@code true}.
1369 * </p>
1370 *
1371 * <pre>
1372 * StringUtils.containsOnly(null, *) = false
1373 * StringUtils.containsOnly(*, null) = false
1374 * StringUtils.containsOnly("", *) = true
1375 * StringUtils.containsOnly("ab", "") = false
1376 * StringUtils.containsOnly("abab", "abc") = true
1377 * StringUtils.containsOnly("ab1", "abc") = false
1378 * StringUtils.containsOnly("abz", "abc") = false
1379 * </pre>
1380 *
1381 * @param cs The CharSequence to check, may be null.
1382 * @param validChars A String of valid chars, may be null.
1383 * @return true if it only contains valid chars and is non-null.
1384 * @since 2.0
1385 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
1386 */
1387 public static boolean containsOnly(final CharSequence cs, final String validChars) {
1388 if (cs == null || validChars == null) {
1389 return false;
1390 }
1391 return containsOnly(cs, validChars.toCharArray());
1392 }
1393
1394 /**
1395 * Tests whether the given CharSequence contains any whitespace characters.
1396 *
1397 * <p>
1398 * Whitespace is defined by {@link Character#isWhitespace(char)}.
1399 * </p>
1400 *
1401 * <pre>
1402 * StringUtils.containsWhitespace(null) = false
1403 * StringUtils.containsWhitespace("") = false
1404 * StringUtils.containsWhitespace("ab") = false
1405 * StringUtils.containsWhitespace(" ab") = true
1406 * StringUtils.containsWhitespace("a b") = true
1407 * StringUtils.containsWhitespace("ab ") = true
1408 * </pre>
1409 *
1410 * @param seq The CharSequence to check (may be {@code null}).
1411 * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character.
1412 * @since 3.0
1413 */
1414 public static boolean containsWhitespace(final CharSequence seq) {
1415 if (isEmpty(seq)) {
1416 return false;
1417 }
1418 final int strLen = seq.length();
1419 for (int i = 0; i < strLen; i++) {
1420 if (Character.isWhitespace(seq.charAt(i))) {
1421 return true;
1422 }
1423 }
1424 return false;
1425 }
1426
1427 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
1428 for (int i = 0; i < decomposed.length(); i++) {
1429 final char charAt = decomposed.charAt(i);
1430 switch (charAt) {
1431 case '\u0141':
1432 decomposed.setCharAt(i, 'L');
1433 break;
1434 case '\u0142':
1435 decomposed.setCharAt(i, 'l');
1436 break;
1437 // D with stroke
1438 case '\u0110':
1439 // LATIN CAPITAL LETTER D WITH STROKE
1440 decomposed.setCharAt(i, 'D');
1441 break;
1442 case '\u0111':
1443 // LATIN SMALL LETTER D WITH STROKE
1444 decomposed.setCharAt(i, 'd');
1445 break;
1446 // I with bar
1447 case '\u0197':
1448 decomposed.setCharAt(i, 'I');
1449 break;
1450 case '\u0268':
1451 decomposed.setCharAt(i, 'i');
1452 break;
1453 case '\u1D7B':
1454 decomposed.setCharAt(i, 'I');
1455 break;
1456 case '\u1DA4':
1457 decomposed.setCharAt(i, 'i');
1458 break;
1459 case '\u1DA7':
1460 decomposed.setCharAt(i, 'I');
1461 break;
1462 // U with bar
1463 case '\u0244':
1464 // LATIN CAPITAL LETTER U BAR
1465 decomposed.setCharAt(i, 'U');
1466 break;
1467 case '\u0289':
1468 // LATIN SMALL LETTER U BAR
1469 decomposed.setCharAt(i, 'u');
1470 break;
1471 case '\u1D7E':
1472 // LATIN SMALL CAPITAL LETTER U WITH STROKE
1473 decomposed.setCharAt(i, 'U');
1474 break;
1475 case '\u1DB6':
1476 // MODIFIER LETTER SMALL U BAR
1477 decomposed.setCharAt(i, 'u');
1478 break;
1479 // T with stroke
1480 case '\u0166':
1481 // LATIN CAPITAL LETTER T WITH STROKE
1482 decomposed.setCharAt(i, 'T');
1483 break;
1484 case '\u0167':
1485 // LATIN SMALL LETTER T WITH STROKE
1486 decomposed.setCharAt(i, 't');
1487 break;
1488 default:
1489 break;
1490 }
1491 }
1492 }
1493
1494 /**
1495 * Counts how many times the char appears in the given string.
1496 *
1497 * <p>
1498 * A {@code null} or empty ("") String input returns {@code 0}.
1499 * </p>
1500 *
1501 * <pre>
1502 * StringUtils.countMatches(null, *) = 0
1503 * StringUtils.countMatches("", *) = 0
1504 * StringUtils.countMatches("abba", 0) = 0
1505 * StringUtils.countMatches("abba", 'a') = 2
1506 * StringUtils.countMatches("abba", 'b') = 2
1507 * StringUtils.countMatches("abba", 'x') = 0
1508 * </pre>
1509 *
1510 * @param str The CharSequence to check, may be null.
1511 * @param ch The char to count.
1512 * @return The number of occurrences, 0 if the CharSequence is {@code null}.
1513 * @since 3.4
1514 */
1515 public static int countMatches(final CharSequence str, final char ch) {
1516 if (isEmpty(str)) {
1517 return 0;
1518 }
1519 int count = 0;
1520 // We could also call str.toCharArray() for faster lookups but that would generate more garbage.
1521 for (int i = 0; i < str.length(); i++) {
1522 if (ch == str.charAt(i)) {
1523 count++;
1524 }
1525 }
1526 return count;
1527 }
1528
1529 /**
1530 * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches.
1531 *
1532 * <p>
1533 * A {@code null} or empty ("") String input returns {@code 0}.
1534 * </p>
1535 *
1536 * <pre>
1537 * StringUtils.countMatches(null, *) = 0
1538 * StringUtils.countMatches("", *) = 0
1539 * StringUtils.countMatches("abba", null) = 0
1540 * StringUtils.countMatches("abba", "") = 0
1541 * StringUtils.countMatches("abba", "a") = 2
1542 * StringUtils.countMatches("abba", "ab") = 1
1543 * StringUtils.countMatches("abba", "xxx") = 0
1544 * StringUtils.countMatches("ababa", "aba") = 1
1545 * </pre>
1546 *
1547 * @param str The CharSequence to check, may be null.
1548 * @param sub The substring to count, may be null.
1549 * @return The number of occurrences, 0 if either CharSequence is {@code null}.
1550 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
1551 */
1552 public static int countMatches(final CharSequence str, final CharSequence sub) {
1553 if (isEmpty(str) || isEmpty(sub)) {
1554 return 0;
1555 }
1556 int count = 0;
1557 int idx = 0;
1558 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
1559 count++;
1560 idx += sub.length();
1561 }
1562 return count;
1563 }
1564
1565 /**
1566 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
1567 * {@code null}), the value of {@code defaultStr}.
1568 *
1569 * <p>
1570 * Whitespace is defined by {@link Character#isWhitespace(char)}.
1571 * </p>
1572 *
1573 * <pre>
1574 * StringUtils.defaultIfBlank(null, "NULL") = "NULL"
1575 * StringUtils.defaultIfBlank("", "NULL") = "NULL"
1576 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL"
1577 * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
1578 * StringUtils.defaultIfBlank("", null) = null
1579 * </pre>
1580 *
1581 * @param <T> the specific kind of CharSequence.
1582 * @param str The CharSequence to check, may be null.
1583 * @param defaultStr The default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
1584 * {@code null}); may be null.
1585 * @return The passed in CharSequence, or the default.
1586 * @see StringUtils#defaultString(String, String)
1587 * @see #isBlank(CharSequence)
1588 */
1589 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
1590 return isBlank(str) ? defaultStr : str;
1591 }
1592
1593 /**
1594 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}.
1595 *
1596 * <pre>
1597 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
1598 * StringUtils.defaultIfEmpty("", "NULL") = "NULL"
1599 * StringUtils.defaultIfEmpty(" ", "NULL") = " "
1600 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
1601 * StringUtils.defaultIfEmpty("", null) = null
1602 * </pre>
1603 *
1604 * @param <T> the specific kind of CharSequence.
1605 * @param str The CharSequence to check, may be null.
1606 * @param defaultStr The default CharSequence to return if the input is empty ("") or {@code null}, may be null.
1607 * @return The passed in CharSequence, or the default.
1608 * @see StringUtils#defaultString(String, String)
1609 */
1610 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
1611 return isEmpty(str) ? defaultStr : str;
1612 }
1613
1614 /**
1615 * Returns either the passed in String, or if the String is {@code null}, an empty String ("").
1616 *
1617 * <pre>
1618 * StringUtils.defaultString(null) = ""
1619 * StringUtils.defaultString("") = ""
1620 * StringUtils.defaultString("bat") = "bat"
1621 * </pre>
1622 *
1623 * @param str The String to check, may be null.
1624 * @return The passed in String, or the empty String if it was {@code null}.
1625 * @see Objects#toString(Object, String)
1626 * @see String#valueOf(Object)
1627 */
1628 public static String defaultString(final String str) {
1629 return Objects.toString(str, EMPTY);
1630 }
1631
1632 /**
1633 * Returns either the given String, or if the String is {@code null}, {@code nullDefault}.
1634 *
1635 * <pre>
1636 * StringUtils.defaultString(null, "NULL") = "NULL"
1637 * StringUtils.defaultString("", "NULL") = ""
1638 * StringUtils.defaultString("bat", "NULL") = "bat"
1639 * </pre>
1640 * <p>
1641 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}:
1642 * </p>
1643 *
1644 * <pre>
1645 * Objects.toString(null, "NULL") = "NULL"
1646 * Objects.toString("", "NULL") = ""
1647 * Objects.toString("bat", "NULL") = "bat"
1648 * </pre>
1649 *
1650 * @param str The String to check, may be null.
1651 * @param nullDefault The default String to return if the input is {@code null}, may be null.
1652 * @return The passed in String, or the default if it was {@code null}.
1653 * @see Objects#toString(Object, String)
1654 * @see String#valueOf(Object)
1655 * @deprecated Use {@link Objects#toString(Object, String)}.
1656 */
1657 @Deprecated
1658 public static String defaultString(final String str, final String nullDefault) {
1659 return Objects.toString(str, nullDefault);
1660 }
1661
1662 /**
1663 * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}.
1664 *
1665 * <pre>
1666 * StringUtils.deleteWhitespace(null) = null
1667 * StringUtils.deleteWhitespace("") = ""
1668 * StringUtils.deleteWhitespace("abc") = "abc"
1669 * StringUtils.deleteWhitespace(" ab c ") = "abc"
1670 * </pre>
1671 *
1672 * @param str The String to delete whitespace from, may be null.
1673 * @return The String without whitespaces, {@code null} if null String input.
1674 */
1675 public static String deleteWhitespace(final String str) {
1676 if (isEmpty(str)) {
1677 return str;
1678 }
1679 final int sz = str.length();
1680 final char[] chs = new char[sz];
1681 int count = 0;
1682 for (int i = 0; i < sz; i++) {
1683 if (!Character.isWhitespace(str.charAt(i))) {
1684 chs[count++] = str.charAt(i);
1685 }
1686 }
1687 if (count == sz) {
1688 return str;
1689 }
1690 if (count == 0) {
1691 return EMPTY;
1692 }
1693 return new String(chs, 0, count);
1694 }
1695
1696 /**
1697 * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's
1698 * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c".
1699 *
1700 * <p>
1701 * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}.
1702 * </p>
1703 *
1704 * <pre>
1705 * StringUtils.difference(null, null) = null
1706 * StringUtils.difference("", "") = ""
1707 * StringUtils.difference("", "abc") = "abc"
1708 * StringUtils.difference("abc", "") = ""
1709 * StringUtils.difference("abc", "abc") = ""
1710 * StringUtils.difference("abc", "ab") = ""
1711 * StringUtils.difference("ab", "abxyz") = "xyz"
1712 * StringUtils.difference("abcde", "abxyz") = "xyz"
1713 * StringUtils.difference("abcde", "xyz") = "xyz"
1714 * </pre>
1715 *
1716 * @param str1 The first String, may be null.
1717 * @param str2 The second String, may be null.
1718 * @return The portion of str2 where it differs from str1; returns the empty String if they are equal.
1719 * @see #indexOfDifference(CharSequence,CharSequence)
1720 * @since 2.0
1721 */
1722 public static String difference(final String str1, final String str2) {
1723 if (str1 == null) {
1724 return str2;
1725 }
1726 if (str2 == null) {
1727 return str1;
1728 }
1729 final int at = indexOfDifference(str1, str2);
1730 if (at == INDEX_NOT_FOUND) {
1731 return EMPTY;
1732 }
1733 return str2.substring(at);
1734 }
1735
1736 /**
1737 * Tests if a CharSequence ends with a specified suffix.
1738 *
1739 * <p>
1740 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive.
1741 * </p>
1742 *
1743 * <pre>
1744 * StringUtils.endsWith(null, null) = true
1745 * StringUtils.endsWith(null, "def") = false
1746 * StringUtils.endsWith("abcdef", null) = false
1747 * StringUtils.endsWith("abcdef", "def") = true
1748 * StringUtils.endsWith("ABCDEF", "def") = false
1749 * StringUtils.endsWith("ABCDEF", "cde") = false
1750 * StringUtils.endsWith("ABCDEF", "") = true
1751 * </pre>
1752 *
1753 * @param str The CharSequence to check, may be null.
1754 * @param suffix The suffix to find, may be null.
1755 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}.
1756 * @see String#endsWith(String)
1757 * @since 2.4
1758 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
1759 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}.
1760 */
1761 @Deprecated
1762 public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
1763 return Strings.CS.endsWith(str, suffix);
1764 }
1765
1766 /**
1767 * Tests if a CharSequence ends with any of the provided case-sensitive suffixes.
1768 *
1769 * <pre>
1770 * StringUtils.endsWithAny(null, null) = false
1771 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false
1772 * StringUtils.endsWithAny("abcxyz", null) = false
1773 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
1774 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
1775 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
1776 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
1777 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
1778 * </pre>
1779 *
1780 * @param sequence The CharSequence to check, may be null.
1781 * @param searchStrings The case-sensitive CharSequences to find, may be empty or contain {@code null}.
1782 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} ends in any
1783 * of the provided case-sensitive {@code searchStrings}.
1784 * @see StringUtils#endsWith(CharSequence, CharSequence)
1785 * @since 3.0
1786 * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}.
1787 */
1788 @Deprecated
1789 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
1790 return Strings.CS.endsWithAny(sequence, searchStrings);
1791 }
1792
1793 /**
1794 * Case-insensitive check if a CharSequence ends with a specified suffix.
1795 *
1796 * <p>
1797 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive.
1798 * </p>
1799 *
1800 * <pre>
1801 * StringUtils.endsWithIgnoreCase(null, null) = true
1802 * StringUtils.endsWithIgnoreCase(null, "def") = false
1803 * StringUtils.endsWithIgnoreCase("abcdef", null) = false
1804 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
1805 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
1806 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
1807 * </pre>
1808 *
1809 * @param str The CharSequence to check, may be null
1810 * @param suffix The suffix to find, may be null
1811 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null}
1812 * @see String#endsWith(String)
1813 * @since 2.4
1814 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
1815 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)}.
1816 */
1817 @Deprecated
1818 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
1819 return Strings.CI.endsWith(str, suffix);
1820 }
1821
1822 /**
1823 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters.
1824 *
1825 * <p>
1826 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>.
1827 * </p>
1828 *
1829 * <pre>
1830 * StringUtils.equals(null, null) = true
1831 * StringUtils.equals(null, "abc") = false
1832 * StringUtils.equals("abc", null) = false
1833 * StringUtils.equals("abc", "abc") = true
1834 * StringUtils.equals("abc", "ABC") = false
1835 * </pre>
1836 *
1837 * @param cs1 The first CharSequence, may be {@code null}.
1838 * @param cs2 The second CharSequence, may be {@code null}.
1839 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}.
1840 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
1841 * @see Object#equals(Object)
1842 * @see #equalsIgnoreCase(CharSequence, CharSequence)
1843 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}.
1844 */
1845 @Deprecated
1846 public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
1847 return Strings.CS.equals(cs1, cs2);
1848 }
1849
1850 /**
1851 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the
1852 * {@code searchStrings}.
1853 *
1854 * <pre>
1855 * StringUtils.equalsAny(null, (CharSequence[]) null) = false
1856 * StringUtils.equalsAny(null, null, null) = true
1857 * StringUtils.equalsAny(null, "abc", "def") = false
1858 * StringUtils.equalsAny("abc", null, "def") = false
1859 * StringUtils.equalsAny("abc", "abc", "def") = true
1860 * StringUtils.equalsAny("abc", "ABC", "DEF") = false
1861 * </pre>
1862 *
1863 * @param string to compare, may be {@code null}.
1864 * @param searchStrings A vararg of strings, may be {@code null}.
1865 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is
1866 * null or contains no matches.
1867 * @since 3.5
1868 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}.
1869 */
1870 @Deprecated
1871 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
1872 return Strings.CS.equalsAny(string, searchStrings);
1873 }
1874
1875 /**
1876 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
1877 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.
1878 *
1879 * <pre>
1880 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
1881 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true
1882 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false
1883 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false
1884 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
1885 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
1886 * </pre>
1887 *
1888 * @param string to compare, may be {@code null}.
1889 * @param searchStrings A vararg of strings, may be {@code null}.
1890 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
1891 * {@code false} if {@code searchStrings} is null or contains no matches.
1892 * @since 3.5
1893 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI.equalsAny(CharSequence, CharSequence...)}.
1894 */
1895 @Deprecated
1896 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) {
1897 return Strings.CI.equalsAny(string, searchStrings);
1898 }
1899
1900 /**
1901 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case.
1902 *
1903 * <p>
1904 * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>.
1905 * </p>
1906 *
1907 * <pre>
1908 * StringUtils.equalsIgnoreCase(null, null) = true
1909 * StringUtils.equalsIgnoreCase(null, "abc") = false
1910 * StringUtils.equalsIgnoreCase("abc", null) = false
1911 * StringUtils.equalsIgnoreCase("abc", "abc") = true
1912 * StringUtils.equalsIgnoreCase("abc", "ABC") = true
1913 * </pre>
1914 *
1915 * @param cs1 The first CharSequence, may be {@code null}.
1916 * @param cs2 The second CharSequence, may be {@code null}.
1917 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}.
1918 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
1919 * @see #equals(CharSequence, CharSequence)
1920 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}.
1921 */
1922 @Deprecated
1923 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
1924 return Strings.CI.equals(cs1, cs2);
1925 }
1926
1927 /**
1928 * Returns the first value in the array which is not empty (""), {@code null} or whitespace only.
1929 *
1930 * <p>
1931 * Whitespace is defined by {@link Character#isWhitespace(char)}.
1932 * </p>
1933 *
1934 * <p>
1935 * If all values are blank or the array is {@code null} or empty then {@code null} is returned.
1936 * </p>
1937 *
1938 * <pre>
1939 * StringUtils.firstNonBlank(null, null, null) = null
1940 * StringUtils.firstNonBlank(null, "", " ") = null
1941 * StringUtils.firstNonBlank("abc") = "abc"
1942 * StringUtils.firstNonBlank(null, "xyz") = "xyz"
1943 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
1944 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz"
1945 * StringUtils.firstNonBlank() = null
1946 * </pre>
1947 *
1948 * @param <T> the specific kind of CharSequence.
1949 * @param values The values to test, may be {@code null} or empty.
1950 * @return The first value from {@code values} which is not blank, or {@code null} if there are no non-blank values.
1951 * @since 3.8
1952 */
1953 @SafeVarargs
1954 public static <T extends CharSequence> T firstNonBlank(final T... values) {
1955 if (values != null) {
1956 for (final T val : values) {
1957 if (isNotBlank(val)) {
1958 return val;
1959 }
1960 }
1961 }
1962 return null;
1963 }
1964
1965 /**
1966 * Returns the first value in the array which is not empty.
1967 *
1968 * <p>
1969 * If all values are empty or the array is {@code null} or empty then {@code null} is returned.
1970 * </p>
1971 *
1972 * <pre>
1973 * StringUtils.firstNonEmpty(null, null, null) = null
1974 * StringUtils.firstNonEmpty(null, null, "") = null
1975 * StringUtils.firstNonEmpty(null, "", " ") = " "
1976 * StringUtils.firstNonEmpty("abc") = "abc"
1977 * StringUtils.firstNonEmpty(null, "xyz") = "xyz"
1978 * StringUtils.firstNonEmpty("", "xyz") = "xyz"
1979 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
1980 * StringUtils.firstNonEmpty() = null
1981 * </pre>
1982 *
1983 * @param <T> the specific kind of CharSequence.
1984 * @param values The values to test, may be {@code null} or empty.
1985 * @return The first value from {@code values} which is not empty, or {@code null} if there are no non-empty values.
1986 * @since 3.8
1987 */
1988 @SafeVarargs
1989 public static <T extends CharSequence> T firstNonEmpty(final T... values) {
1990 if (values != null) {
1991 for (final T val : values) {
1992 if (isNotEmpty(val)) {
1993 return val;
1994 }
1995 }
1996 }
1997 return null;
1998 }
1999
2000 /**
2001 * Gets the bytes of the string using {@link String#getBytes(Charset)}, handling {@code null} safely.
2002 *
2003 * @param string input string.
2004 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset.
2005 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
2006 * @see String#getBytes(Charset)
2007 * @since 3.10
2008 */
2009 public static byte[] getBytes(final String string, final Charset charset) {
2010 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
2011 }
2012
2013 /**
2014 * Gets the bytes of the string using {@link String#getBytes(String)}, handling {@code null} safely.
2015 *
2016 * @param string input string.
2017 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset.
2018 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
2019 * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
2020 * @see String#getBytes(String)
2021 * @since 3.10
2022 */
2023 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
2024 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
2025 }
2026
2027 /**
2028 * Gets the initial sequence of characters common to all strings in the array.
2029 *
2030 * <p>
2031 * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -> "i am a "}
2032 * </p>
2033 *
2034 * <pre>
2035 * StringUtils.getCommonPrefix(null) = ""
2036 * StringUtils.getCommonPrefix(new String[] {}) = ""
2037 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
2038 * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
2039 * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
2040 * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
2041 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
2042 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
2043 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
2044 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
2045 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
2046 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
2047 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
2048 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
2049 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
2050 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
2051 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
2052 * </pre>
2053 *
2054 * @param strs array of String objects, entries may be null.
2055 * @return The initial sequence of characters that are common to all Strings in the array; empty String if the array is null, the elements are all null or
2056 * if there is no common prefix.
2057 * @since 2.4
2058 */
2059 public static String getCommonPrefix(final String... strs) {
2060 if (ArrayUtils.isEmpty(strs)) {
2061 return EMPTY;
2062 }
2063 final int smallestIndexOfDiff = indexOfDifference(strs);
2064 if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
2065 // all strings were identical
2066 if (strs[0] == null) {
2067 return EMPTY;
2068 }
2069 return strs[0];
2070 }
2071 if (smallestIndexOfDiff == 0) {
2072 // there were no common initial characters
2073 return EMPTY;
2074 }
2075 // we found a common initial character sequence
2076 return strs[0].substring(0, smallestIndexOfDiff);
2077 }
2078
2079 /**
2080 * Gets the Unicode digits in {@code str}, concatenated in their original order.
2081 *
2082 * <p>
2083 * An empty ("") String will be returned if no digits are found in {@code str}.
2084 * </p>
2085 *
2086 * <pre>
2087 * StringUtils.getDigits(null) = null
2088 * StringUtils.getDigits("") = ""
2089 * StringUtils.getDigits("abc") = ""
2090 * StringUtils.getDigits("1000$") = "1000"
2091 * StringUtils.getDigits("1123~45") = "112345"
2092 * StringUtils.getDigits("(541) 754-3010") = "5417543010"
2093 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
2094 * </pre>
2095 *
2096 * @param str The String to extract digits from, may be null.
2097 * @return String with only digits, or an empty ("") String if no digits are found, or {@code null} String if {@code str} is null.
2098 * @since 3.6
2099 */
2100 public static String getDigits(final String str) {
2101 if (isEmpty(str)) {
2102 return str;
2103 }
2104 final int len = str.length();
2105 final char[] buffer = new char[len];
2106 int count = 0;
2107
2108 for (int i = 0; i < len;) {
2109 final int codePoint = str.codePointAt(i);
2110 if (Character.isDigit(codePoint)) {
2111 count += Character.toChars(codePoint, buffer, count);
2112 }
2113 i += Character.charCount(codePoint);
2114 }
2115 return new String(buffer, 0, count);
2116 }
2117
2118 /**
2119 * Gets the Fuzzy Distance which indicates the similarity score between two Strings.
2120 *
2121 * <p>
2122 * This string matching algorithm is similar to the algorithms of editors such as Sublime Text, TextMate, Atom and others. One point is given for every
2123 * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity.
2124 * </p>
2125 *
2126 * <pre>
2127 * StringUtils.getFuzzyDistance(null, null, null) = Throws {@link IllegalArgumentException}
2128 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0
2129 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0
2130 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1
2131 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1
2132 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2
2133 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4
2134 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
2135 * </pre>
2136 *
2137 * @param term A full term that should be matched against, must not be null.
2138 * @param query The query that will be matched against a term, must not be null.
2139 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case.
2140 * @return result score.
2141 * @throws IllegalArgumentException Thrown if either String input {@code null} or Locale input {@code null}.
2142 * @since 3.4
2143 * @deprecated As of 3.6, use Apache Commons Text
2144 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
2145 * FuzzyScore</a> instead.
2146 */
2147 @Deprecated
2148 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
2149 if (term == null || query == null) {
2150 throw new IllegalArgumentException("Strings must not be null");
2151 }
2152 if (locale == null) {
2153 throw new IllegalArgumentException("Locale must not be null");
2154 }
2155 // fuzzy logic is case-insensitive. We normalize the Strings to lower
2156 // case right from the start. Turning characters to lower case
2157 // via Character.toLowerCase(char) is unfortunately insufficient
2158 // as it does not accept a locale.
2159 final String termLowerCase = term.toString().toLowerCase(locale);
2160 final String queryLowerCase = query.toString().toLowerCase(locale);
2161 // the resulting score
2162 int score = 0;
2163 // the position in the term which will be scanned next for potential
2164 // query character matches
2165 int termIndex = 0;
2166 // index of the previously matched character in the term
2167 int previousMatchingCharacterIndex = Integer.MIN_VALUE;
2168 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
2169 final char queryChar = queryLowerCase.charAt(queryIndex);
2170 boolean termCharacterMatchFound = false;
2171 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
2172 final char termChar = termLowerCase.charAt(termIndex);
2173 if (queryChar == termChar) {
2174 // simple character matches result in one point
2175 score++;
2176 // subsequent character matches further improve
2177 // the score.
2178 if (previousMatchingCharacterIndex + 1 == termIndex) {
2179 score += 2;
2180 }
2181 previousMatchingCharacterIndex = termIndex;
2182 // we can leave the nested loop. Every character in the
2183 // query can match at most one character in the term.
2184 termCharacterMatchFound = true;
2185 }
2186 }
2187 }
2188 return score;
2189 }
2190
2191 /**
2192 * Gets either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
2193 * {@code null}), the value supplied by {@code defaultStrSupplier}.
2194 *
2195 * <p>
2196 * Whitespace is defined by {@link Character#isWhitespace(char)}.
2197 * </p>
2198 *
2199 * <p>
2200 * The caller is responsible for thread safety and exception handling for the default value supplier.
2201 * </p>
2202 *
2203 * <pre>
2204 * {@code
2205 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL"
2206 * StringUtils.getIfBlank("", () -> "NULL") = "NULL"
2207 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL"
2208 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat"
2209 * StringUtils.getIfBlank("", () -> null) = null
2210 * StringUtils.getIfBlank("", null) = null
2211 * }</pre>
2212 *
2213 * @param <T> the specific kind of CharSequence.
2214 * @param str The CharSequence to check, may be null.
2215 * @param defaultSupplier The supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty
2216 * ({@code ""}), or {@code null}); may be null.
2217 * @return The passed in CharSequence, or the default
2218 * @see StringUtils#defaultString(String, String)
2219 * @see #isBlank(CharSequence)
2220 * @since 3.10
2221 */
2222 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
2223 return isBlank(str) ? Suppliers.get(defaultSupplier) : str;
2224 }
2225
2226 /**
2227 * Gets either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}.
2228 *
2229 * <p>
2230 * The caller is responsible for thread safety and exception handling for the default value supplier.
2231 * </p>
2232 *
2233 * <pre>
2234 * {@code
2235 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL"
2236 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL"
2237 * StringUtils.getIfEmpty(" ", () -> "NULL") = " "
2238 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat"
2239 * StringUtils.getIfEmpty("", () -> null) = null
2240 * StringUtils.getIfEmpty("", null) = null
2241 * }
2242 * </pre>
2243 *
2244 * @param <T> the specific kind of CharSequence.
2245 * @param str The CharSequence to check, may be null.
2246 * @param defaultSupplier The supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null.
2247 * @return The passed in CharSequence, or the default.
2248 * @see StringUtils#defaultString(String, String)
2249 * @since 3.10
2250 */
2251 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
2252 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str;
2253 }
2254
2255 /**
2256 * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings.
2257 *
2258 * <p>
2259 * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for
2260 * matching initial characters.
2261 * </p>
2262 *
2263 * <p>
2264 * This implementation is based on the Jaro Winkler similarity algorithm from
2265 * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.
2266 * </p>
2267 *
2268 * <pre>
2269 * StringUtils.getJaroWinklerDistance(null, null) = Throws {@link IllegalArgumentException}
2270 * StringUtils.getJaroWinklerDistance("", "") = 0.0
2271 * StringUtils.getJaroWinklerDistance("", "a") = 0.0
2272 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0
2273 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93
2274 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0
2275 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
2276 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
2277 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
2278 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88
2279 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
2280 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95
2281 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
2282 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
2283 * </pre>
2284 *
2285 * @param first The first String, must not be null.
2286 * @param second The second String, must not be null.
2287 * @return result distance.
2288 * @throws IllegalArgumentException Thrown if either String input {@code null}.
2289 * @since 3.3
2290 * @deprecated As of 3.6, use Apache Commons Text
2291 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
2292 * JaroWinklerDistance</a> instead.
2293 */
2294 @Deprecated
2295 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
2296 final double DEFAULT_SCALING_FACTOR = 0.1;
2297
2298 if (first == null || second == null) {
2299 throw new IllegalArgumentException("Strings must not be null");
2300 }
2301
2302 final int[] mtp = matches(first, second);
2303 final double m = mtp[0];
2304 if (m == 0) {
2305 return 0D;
2306 }
2307 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3;
2308 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
2309 return Math.round(jw * 100.0D) / 100.0D;
2310 }
2311
2312 /**
2313 * Gets the Levenshtein distance between two Strings.
2314 *
2315 * <p>
2316 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or
2317 * substitution).
2318 * </p>
2319 *
2320 * <p>
2321 * The implementation uses a single-dimensional array of length s.length() + 1. See
2322 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
2323 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.
2324 * </p>
2325 *
2326 * <pre>
2327 * StringUtils.getLevenshteinDistance(null, *) = Throws {@link IllegalArgumentException}
2328 * StringUtils.getLevenshteinDistance(*, null) = Throws {@link IllegalArgumentException}
2329 * StringUtils.getLevenshteinDistance("", "") = 0
2330 * StringUtils.getLevenshteinDistance("", "a") = 1
2331 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7
2332 * StringUtils.getLevenshteinDistance("frog", "fog") = 1
2333 * StringUtils.getLevenshteinDistance("fly", "ant") = 3
2334 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
2335 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
2336 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
2337 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1
2338 * </pre>
2339 *
2340 * @param s The first String, must not be null.
2341 * @param t The second String, must not be null.
2342 * @return result distance.
2343 * @throws IllegalArgumentException Thrown if either String input {@code null}.
2344 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence)
2345 * @deprecated As of 3.6, use Apache Commons Text
2346 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
2347 * LevenshteinDistance</a> instead.
2348 */
2349 @Deprecated
2350 public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
2351 if (s == null || t == null) {
2352 throw new IllegalArgumentException("Strings must not be null");
2353 }
2354
2355 int n = s.length();
2356 int m = t.length();
2357
2358 if (n == 0) {
2359 return m;
2360 }
2361 if (m == 0) {
2362 return n;
2363 }
2364
2365 if (n > m) {
2366 // swap the input strings to consume less memory
2367 final CharSequence tmp = s;
2368 s = t;
2369 t = tmp;
2370 n = m;
2371 m = t.length();
2372 }
2373
2374 final int[] p = new int[n + 1];
2375 // indexes into strings s and t
2376 int i; // iterates through s
2377 int j; // iterates through t
2378 int upperleft;
2379 int upper;
2380
2381 char jOfT; // jth character of t
2382 int cost;
2383
2384 for (i = 0; i <= n; i++) {
2385 p[i] = i;
2386 }
2387
2388 for (j = 1; j <= m; j++) {
2389 upperleft = p[0];
2390 jOfT = t.charAt(j - 1);
2391 p[0] = j;
2392
2393 for (i = 1; i <= n; i++) {
2394 upper = p[i];
2395 cost = s.charAt(i - 1) == jOfT ? 0 : 1;
2396 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
2397 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost);
2398 upperleft = upper;
2399 }
2400 }
2401
2402 return p[n];
2403 }
2404
2405 /**
2406 * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold.
2407 *
2408 * <p>
2409 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or
2410 * substitution).
2411 * </p>
2412 *
2413 * <p>
2414 * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance
2415 * algorithm.
2416 * </p>
2417 *
2418 * <pre>
2419 * StringUtils.getLevenshteinDistance(null, *, *) = Throws {@link IllegalArgumentException}
2420 * StringUtils.getLevenshteinDistance(*, null, *) = Throws {@link IllegalArgumentException}
2421 * StringUtils.getLevenshteinDistance(*, *, -1) = Throws {@link IllegalArgumentException}
2422 * StringUtils.getLevenshteinDistance("", "", 0) = 0
2423 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7
2424 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7
2425 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1
2426 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
2427 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
2428 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
2429 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
2430 * </pre>
2431 *
2432 * @param s The first String, must not be null.
2433 * @param t The second String, must not be null.
2434 * @param threshold The target threshold, must not be negative.
2435 * @return result distance, or {@code -1} if the distance would be greater than the threshold.
2436 * @throws IllegalArgumentException Thrown if either String input {@code null} or negative threshold.
2437 * @deprecated As of 3.6, use Apache Commons Text
2438 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
2439 * LevenshteinDistance</a> instead.
2440 */
2441 @Deprecated
2442 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
2443 if (s == null || t == null) {
2444 throw new IllegalArgumentException("Strings must not be null");
2445 }
2446 if (threshold < 0) {
2447 throw new IllegalArgumentException("Threshold must not be negative");
2448 }
2449
2450 /*
2451 This implementation only computes the distance if it's less than or equal to the
2452 threshold value, returning -1 if it's greater. The advantage is performance: unbounded
2453 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
2454 computing a diagonal stripe of width 2k + 1 of the cost table.
2455 It is also possible to use this to compute the unbounded Levenshtein distance by starting
2456 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
2457 d is the distance.
2458
2459 One subtlety comes from needing to ignore entries on the border of our stripe
2460 for example,
2461 p[] = |#|#|#|*
2462 d[] = *|#|#|#|
2463 We must ignore the entry to the left of the leftmost member
2464 We must ignore the entry above the rightmost member
2465
2466 Another subtlety comes from our stripe running off the matrix if the strings aren't
2467 of the same size. Since string s is always swapped to be the shorter of the two,
2468 the stripe will always run off to the upper right instead of the lower left of the matrix.
2469
2470 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
2471 In this case we're going to walk a stripe of length 3. The matrix would look like so:
2472
2473 1 2 3 4 5
2474 1 |#|#| | | |
2475 2 |#|#|#| | |
2476 3 | |#|#|#| |
2477 4 | | |#|#|#|
2478 5 | | | |#|#|
2479 6 | | | | |#|
2480 7 | | | | | |
2481
2482 Note how the stripe leads off the table as there is no possible way to turn a string of length 5
2483 into one of length 7 in edit distance of 1.
2484
2485 Additionally, this implementation decreases memory usage by using two
2486 single-dimensional arrays and swapping them back and forth instead of allocating
2487 an entire n by m matrix. This requires a few minor changes, such as immediately returning
2488 when it's detected that the stripe has run off the matrix and initially filling the arrays with
2489 large values so that entries we don't compute are ignored.
2490
2491 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
2492 */
2493
2494 int n = s.length(); // length of s
2495 int m = t.length(); // length of t
2496
2497 // if one string is empty, the edit distance is necessarily the length of the other
2498 if (n == 0) {
2499 return m <= threshold ? m : -1;
2500 }
2501 if (m == 0) {
2502 return n <= threshold ? n : -1;
2503 }
2504 if (Math.abs(n - m) > threshold) {
2505 // no need to calculate the distance if the length difference is greater than the threshold
2506 return -1;
2507 }
2508
2509 if (n > m) {
2510 // swap the two strings to consume less memory
2511 final CharSequence tmp = s;
2512 s = t;
2513 t = tmp;
2514 n = m;
2515 m = t.length();
2516 }
2517
2518 int[] p = new int[n + 1]; // 'previous' cost array, horizontally
2519 int[] d = new int[n + 1]; // cost array, horizontally
2520 int[] tmp; // placeholder to assist in swapping p and d
2521
2522 // fill in starting table values
2523 final int boundary = Math.min(n, threshold) + 1;
2524 for (int i = 0; i < boundary; i++) {
2525 p[i] = i;
2526 }
2527 // these fills ensure that the value above the rightmost entry of our
2528 // stripe will be ignored in following loop iterations
2529 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
2530 Arrays.fill(d, Integer.MAX_VALUE);
2531
2532 // iterates through t
2533 for (int j = 1; j <= m; j++) {
2534 final char jOfT = t.charAt(j - 1); // jth character of t
2535 d[0] = j;
2536
2537 // compute stripe indices, constrain to array size
2538 final int min = Math.max(1, j - threshold);
2539 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
2540
2541 // the stripe may lead off of the table if s and t are of different sizes
2542 if (min > max) {
2543 return -1;
2544 }
2545
2546 // ignore entry left of leftmost
2547 if (min > 1) {
2548 d[min - 1] = Integer.MAX_VALUE;
2549 }
2550
2551 // iterates through [min, max] in s
2552 for (int i = min; i <= max; i++) {
2553 if (s.charAt(i - 1) == jOfT) {
2554 // diagonally left and up
2555 d[i] = p[i - 1];
2556 } else {
2557 // 1 + minimum of cell to the left, to the top, diagonally left and up
2558 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
2559 }
2560 }
2561
2562 // copy current distance counts to 'previous row' distance counts
2563 tmp = p;
2564 p = d;
2565 d = tmp;
2566 }
2567
2568 // if p[n] is greater than the threshold, there's no guarantee on it being the correct
2569 // distance
2570 if (p[n] <= threshold) {
2571 return p[n];
2572 }
2573 return -1;
2574 }
2575
2576 /**
2577 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible.
2578 *
2579 * <p>
2580 * A {@code null} CharSequence will return {@code -1}.
2581 * </p>
2582 *
2583 * <pre>
2584 * StringUtils.indexOf(null, *) = -1
2585 * StringUtils.indexOf(*, null) = -1
2586 * StringUtils.indexOf("", "") = 0
2587 * StringUtils.indexOf("", *) = -1 (except when * = "")
2588 * StringUtils.indexOf("aabaabaa", "a") = 0
2589 * StringUtils.indexOf("aabaabaa", "b") = 2
2590 * StringUtils.indexOf("aabaabaa", "ab") = 1
2591 * StringUtils.indexOf("aabaabaa", "") = 0
2592 * </pre>
2593 *
2594 * @param seq The CharSequence to check, may be null.
2595 * @param searchSeq The CharSequence to find, may be null.
2596 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input.
2597 * @since 2.0
2598 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
2599 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}.
2600 */
2601 @Deprecated
2602 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
2603 return Strings.CS.indexOf(seq, searchSeq);
2604 }
2605
2606 /**
2607 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible.
2608 *
2609 * <p>
2610 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
2611 * start position greater than the string length only matches an empty search CharSequence.
2612 * </p>
2613 *
2614 * <pre>
2615 * StringUtils.indexOf(null, *, *) = -1
2616 * StringUtils.indexOf(*, null, *) = -1
2617 * StringUtils.indexOf("", "", 0) = 0
2618 * StringUtils.indexOf("", *, 0) = -1 (except when * = "")
2619 * StringUtils.indexOf("aabaabaa", "a", 0) = 0
2620 * StringUtils.indexOf("aabaabaa", "b", 0) = 2
2621 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
2622 * StringUtils.indexOf("aabaabaa", "b", 3) = 5
2623 * StringUtils.indexOf("aabaabaa", "b", 9) = -1
2624 * StringUtils.indexOf("aabaabaa", "b", -1) = 2
2625 * StringUtils.indexOf("aabaabaa", "", 2) = 2
2626 * StringUtils.indexOf("abc", "", 9) = 3
2627 * </pre>
2628 *
2629 * @param seq The CharSequence to check, may be null.
2630 * @param searchSeq The CharSequence to find, may be null.
2631 * @param startPos The start position, negative treated as zero.
2632 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input.
2633 * @since 2.0
2634 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
2635 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}.
2636 */
2637 @Deprecated
2638 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
2639 return Strings.CS.indexOf(seq, searchSeq, startPos);
2640 }
2641
2642 /**
2643 * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the
2644 * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is
2645 * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that:
2646 *
2647 * <pre>
2648 * this.charAt(<em>k</em>) == searchChar
2649 * </pre>
2650 *
2651 * <p>
2652 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that:
2653 * </p>
2654 *
2655 * <pre>
2656 * this.codePointAt(<em>k</em>) == searchChar
2657 * </pre>
2658 *
2659 * <p>
2660 * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned.
2661 * </p>
2662 *
2663 * <p>
2664 * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}.
2665 * </p>
2666 *
2667 * <pre>
2668 * StringUtils.indexOf(null, *) = -1
2669 * StringUtils.indexOf("", *) = -1
2670 * StringUtils.indexOf("aabaabaa", 'a') = 0
2671 * StringUtils.indexOf("aabaabaa", 'b') = 2
2672 * StringUtils.indexOf("aaaaaaaa", 'Z') = -1
2673 * </pre>
2674 *
2675 * @param seq The CharSequence to check, may be null.
2676 * @param searchChar The character to find.
2677 * @return The first index of the search character, -1 if no match or {@code null} string input.
2678 * @since 2.0
2679 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
2680 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
2681 */
2682 public static int indexOf(final CharSequence seq, final int searchChar) {
2683 if (isEmpty(seq)) {
2684 return INDEX_NOT_FOUND;
2685 }
2686 return CharSequenceUtils.indexOf(seq, searchChar, 0);
2687 }
2688
2689 /**
2690 * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index.
2691 * <p>
2692 * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no
2693 * smaller than {@code startPos}, then the index of the first such occurrence is returned. For values of {@code searchChar} in the range from 0 to 0xFFFF
2694 * (inclusive), this is the smallest value <em>k</em> such that:
2695 * </p>
2696 *
2697 * <pre>
2698 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos)
2699 * </pre>
2700 *
2701 * <p>
2702 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that:
2703 * </p>
2704 *
2705 * <pre>
2706 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos)
2707 * </pre>
2708 *
2709 * <p>
2710 * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned.
2711 * </p>
2712 *
2713 * <p>
2714 * There is no restriction on the value of {@code startPos}. If it is negative, it has the same effect as if it were zero: this entire string may be
2715 * searched. If it is greater than the length of this string, it has the same effect as if it were equal to the length of this string:
2716 * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}.
2717 * </p>
2718 * <p>
2719 * All indices are specified in {@code char} values (Unicode code units).
2720 * </p>
2721 *
2722 * <pre>
2723 * StringUtils.indexOf(null, *, *) = -1
2724 * StringUtils.indexOf("", *, *) = -1
2725 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2
2726 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5
2727 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1
2728 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
2729 * </pre>
2730 *
2731 * @param seq The CharSequence to check, may be null.
2732 * @param searchChar The character to find.
2733 * @param startPos The start position, negative treated as zero.
2734 * @return The first index of the search character (always ≥ startPos), -1 if no match or {@code null} string input.
2735 * @since 2.0
2736 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
2737 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
2738 */
2739 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
2740 if (isEmpty(seq)) {
2741 return INDEX_NOT_FOUND;
2742 }
2743 return CharSequenceUtils.indexOf(seq, searchChar, startPos);
2744 }
2745
2746 /**
2747 * Search a CharSequence to find the first index of any character in the given set of characters.
2748 *
2749 * <p>
2750 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2751 * </p>
2752 *
2753 * <pre>
2754 * StringUtils.indexOfAny(null, *) = -1
2755 * StringUtils.indexOfAny("", *) = -1
2756 * StringUtils.indexOfAny(*, null) = -1
2757 * StringUtils.indexOfAny(*, []) = -1
2758 * StringUtils.indexOfAny("zzabyycdxx", 'z', 'a') = 0
2759 * StringUtils.indexOfAny("zzabyycdxx", 'b', 'y') = 3
2760 * StringUtils.indexOfAny("aba", 'z') = -1
2761 * </pre>
2762 *
2763 * @param cs The CharSequence to check, may be null.
2764 * @param searchChars The chars to search for, may be null.
2765 * @return The index of any of the chars, -1 if no match or null input.
2766 * @since 2.0
2767 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
2768 */
2769 public static int indexOfAny(final CharSequence cs, final char... searchChars) {
2770 return indexOfAny(cs, 0, searchChars);
2771 }
2772
2773 /**
2774 * Find the first index of any of a set of potential substrings.
2775 *
2776 * <p>
2777 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. A {@code null} search array entry
2778 * will be ignored, but a search array containing "" will return {@code 0} if {@code str} is not null. This method uses {@link String#indexOf(String)} if
2779 * possible.
2780 * </p>
2781 *
2782 * <pre>
2783 * StringUtils.indexOfAny(null, *) = -1
2784 * StringUtils.indexOfAny(*, null) = -1
2785 * StringUtils.indexOfAny(*, []) = -1
2786 * StringUtils.indexOfAny("zzabyycdxx", "ab", "cd") = 2
2787 * StringUtils.indexOfAny("zzabyycdxx", "cd", "ab") = 2
2788 * StringUtils.indexOfAny("zzabyycdxx", "mn", "op") = -1
2789 * StringUtils.indexOfAny("zzabyycdxx", "zab", "aby") = 1
2790 * StringUtils.indexOfAny("zzabyycdxx", "") = 0
2791 * StringUtils.indexOfAny("", "") = 0
2792 * StringUtils.indexOfAny("", "a") = -1
2793 * </pre>
2794 *
2795 * @param str The CharSequence to check, may be null.
2796 * @param searchStrs The CharSequences to search for, may be null.
2797 * @return The first index of any of the searchStrs in str, -1 if no match.
2798 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
2799 */
2800 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
2801 if (str == null || searchStrs == null) {
2802 return INDEX_NOT_FOUND;
2803 }
2804 // String's can't have a MAX_VALUEth index.
2805 int ret = Integer.MAX_VALUE;
2806 int tmp;
2807 for (final CharSequence search : searchStrs) {
2808 if (search == null) {
2809 continue;
2810 }
2811 tmp = CharSequenceUtils.indexOf(str, search, 0);
2812 if (tmp == INDEX_NOT_FOUND) {
2813 continue;
2814 }
2815 if (tmp < ret) {
2816 ret = tmp;
2817 }
2818 }
2819 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
2820 }
2821
2822 /**
2823 * Search a CharSequence to find the first index of any character in the given set of characters.
2824 *
2825 * <p>
2826 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2827 * </p>
2828 * <p>
2829 * The following is the same as {@code indexOfAny(cs, 0, searchChars)}.
2830 * </p>
2831 * <pre>
2832 * StringUtils.indexOfAny(null, 0, *) = -1
2833 * StringUtils.indexOfAny("", 0, *) = -1
2834 * StringUtils.indexOfAny(*, 0, null) = -1
2835 * StringUtils.indexOfAny(*, 0, []) = -1
2836 * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0
2837 * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3
2838 * StringUtils.indexOfAny("aba", 0, ['z']) = -1
2839 * </pre>
2840 *
2841 * @param cs The CharSequence to check, may be null.
2842 * @param csStart Start searching the input {@code cs} at this index.
2843 * @param searchChars The chars to search for, may be null.
2844 * @return The index of any of the chars, -1 if no match or null input.
2845 * @since 2.0
2846 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
2847 */
2848 public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) {
2849 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
2850 return INDEX_NOT_FOUND;
2851 }
2852 final int csLen = cs.length();
2853 final int csLast = csLen - 1;
2854 final int searchLen = searchChars.length;
2855 final int searchLast = searchLen - 1;
2856 for (int i = Math.max(csStart, 0); i < csLen; i++) {
2857 final char ch = cs.charAt(i);
2858 for (int j = 0; j < searchLen; j++) {
2859 if (searchChars[j] == ch) {
2860 if (Character.isHighSurrogate(ch)
2861 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)
2862 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) {
2863 return i;
2864 }
2865 }
2866 }
2867 }
2868 return INDEX_NOT_FOUND;
2869 }
2870
2871 /**
2872 * Search a CharSequence to find the first index of any character in the given set of characters.
2873 *
2874 * <p>
2875 * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}.
2876 * </p>
2877 *
2878 * <pre>
2879 * StringUtils.indexOfAny(null, *) = -1
2880 * StringUtils.indexOfAny("", *) = -1
2881 * StringUtils.indexOfAny(*, null) = -1
2882 * StringUtils.indexOfAny(*, "") = -1
2883 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
2884 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
2885 * StringUtils.indexOfAny("aba", "z") = -1
2886 * </pre>
2887 *
2888 * @param cs The CharSequence to check, may be null.
2889 * @param searchChars The chars to search for, may be null.
2890 * @return The index of any of the chars, -1 if no match or null input.
2891 * @since 2.0
2892 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
2893 */
2894 public static int indexOfAny(final CharSequence cs, final String searchChars) {
2895 if (isEmpty(cs) || isEmpty(searchChars)) {
2896 return INDEX_NOT_FOUND;
2897 }
2898 return indexOfAny(cs, searchChars.toCharArray());
2899 }
2900
2901 /**
2902 * Searches a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in cs such that
2903 * (cs.codePointAt(i) â { x â codepoints(searchChars) })
2904 *
2905 * <p>
2906 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2907 * </p>
2908 *
2909 * <pre>
2910 * StringUtils.indexOfAnyBut(null, *) = -1
2911 * StringUtils.indexOfAnyBut("", *) = -1
2912 * StringUtils.indexOfAnyBut(*, null) = -1
2913 * StringUtils.indexOfAnyBut(*, []) = -1
2914 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
2915 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0
2916 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1
2917 * </pre>
2918 *
2919 * @param cs The CharSequence to check, may be null.
2920 * @param searchChars The chars to search for, may be null.
2921 * @return The index of any of the chars, -1 if no match or null input.
2922 * @since 2.0
2923 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
2924 */
2925 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
2926 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
2927 return INDEX_NOT_FOUND;
2928 }
2929 return indexOfAnyBut(cs, CharBuffer.wrap(searchChars));
2930 }
2931
2932 /**
2933 * Search a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in seq such that
2934 * (seq.codePointAt(i) â { x â codepoints(searchChars) })
2935 *
2936 * <p>
2937 * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}.
2938 * </p>
2939 *
2940 * <pre>
2941 * StringUtils.indexOfAnyBut(null, *) = -1
2942 * StringUtils.indexOfAnyBut("", *) = -1
2943 * StringUtils.indexOfAnyBut(*, null) = -1
2944 * StringUtils.indexOfAnyBut(*, "") = -1
2945 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
2946 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1
2947 * StringUtils.indexOfAnyBut("aba", "ab") = -1
2948 * </pre>
2949 *
2950 * @param seq The CharSequence to check, may be null.
2951 * @param searchChars The chars to search for, may be null.
2952 * @return The index of any of the chars, -1 if no match or null input.
2953 * @since 2.0
2954 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
2955 */
2956 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
2957 if (isEmpty(seq) || isEmpty(searchChars)) {
2958 return INDEX_NOT_FOUND;
2959 }
2960 final Set<Integer> searchSetCodePoints = searchChars.codePoints()
2961 .boxed().collect(Collectors.toSet());
2962 // advance character index from one interpreted codepoint to the next
2963 for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) {
2964 final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx);
2965 if (!searchSetCodePoints.contains(curSeqCodePoint)) {
2966 return curSeqCharIdx;
2967 }
2968 curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates
2969 }
2970 return INDEX_NOT_FOUND;
2971 }
2972
2973 /**
2974 * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ.
2975 *
2976 * <p>
2977 * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}
2978 * </p>
2979 *
2980 * <pre>
2981 * StringUtils.indexOfDifference(null) = -1
2982 * StringUtils.indexOfDifference(new String[] {}) = -1
2983 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
2984 * StringUtils.indexOfDifference(new String[] {null, null}) = -1
2985 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
2986 * StringUtils.indexOfDifference(new String[] {"", null}) = 0
2987 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
2988 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
2989 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
2990 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
2991 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
2992 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
2993 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
2994 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
2995 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
2996 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
2997 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
2998 * </pre>
2999 *
3000 * @param css array of CharSequences, entries may be null.
3001 * @return The index where the strings begin to differ; -1 if they are all equal.
3002 * @since 2.4
3003 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
3004 */
3005 public static int indexOfDifference(final CharSequence... css) {
3006 if (ArrayUtils.getLength(css) <= 1) {
3007 return INDEX_NOT_FOUND;
3008 }
3009 boolean anyStringNull = false;
3010 boolean allStringsNull = true;
3011 final int arrayLen = css.length;
3012 int shortestStrLen = Integer.MAX_VALUE;
3013 int longestStrLen = 0;
3014 // find the min and max string lengths; this avoids checking to make
3015 // sure we are not exceeding the length of the string each time through
3016 // the bottom loop.
3017 for (final CharSequence cs : css) {
3018 if (cs == null) {
3019 anyStringNull = true;
3020 shortestStrLen = 0;
3021 } else {
3022 allStringsNull = false;
3023 shortestStrLen = Math.min(cs.length(), shortestStrLen);
3024 longestStrLen = Math.max(cs.length(), longestStrLen);
3025 }
3026 }
3027 // handle lists containing all nulls or all empty strings
3028 if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
3029 return INDEX_NOT_FOUND;
3030 }
3031 // handle lists containing some nulls or some empty strings
3032 if (shortestStrLen == 0) {
3033 return 0;
3034 }
3035 // find the position with the first difference across all strings
3036 int firstDiff = -1;
3037 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
3038 final char comparisonChar = css[0].charAt(stringPos);
3039 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
3040 if (css[arrayPos].charAt(stringPos) != comparisonChar) {
3041 firstDiff = stringPos;
3042 break;
3043 }
3044 }
3045 if (firstDiff != -1) {
3046 break;
3047 }
3048 }
3049 if (firstDiff > 0 && Character.isLowSurrogate(css[0].charAt(firstDiff))
3050 && Character.isHighSurrogate(css[0].charAt(firstDiff - 1))) {
3051 // the difference splits a surrogate pair whose high half is common; report the start of the
3052 // pair so getCommonPrefix never slices it in half and leaves a stray high surrogate.
3053 firstDiff--;
3054 }
3055 if (firstDiff == -1 && shortestStrLen != longestStrLen) {
3056 // we compared all of the characters up to the length of the
3057 // shortest string and didn't find a match, but the string lengths
3058 // vary, so return the length of the shortest string.
3059 return shortestStrLen;
3060 }
3061 return firstDiff;
3062 }
3063
3064 /**
3065 * Compares two CharSequences, and returns the index at which the CharSequences begin to differ.
3066 *
3067 * <p>
3068 * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7}
3069 * </p>
3070 *
3071 * <pre>
3072 * StringUtils.indexOfDifference(null, null) = -1
3073 * StringUtils.indexOfDifference("", "") = -1
3074 * StringUtils.indexOfDifference("", "abc") = 0
3075 * StringUtils.indexOfDifference("abc", "") = 0
3076 * StringUtils.indexOfDifference("abc", "abc") = -1
3077 * StringUtils.indexOfDifference("ab", "abxyz") = 2
3078 * StringUtils.indexOfDifference("abcde", "abxyz") = 2
3079 * StringUtils.indexOfDifference("abcde", "xyz") = 0
3080 * </pre>
3081 *
3082 * @param cs1 The first CharSequence, may be null.
3083 * @param cs2 The second CharSequence, may be null.
3084 * @return The index where cs1 and cs2 begin to differ; -1 if they are equal.
3085 * @since 2.0
3086 * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence)
3087 */
3088 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
3089 if (cs1 == cs2) {
3090 return INDEX_NOT_FOUND;
3091 }
3092 if (cs1 == null || cs2 == null) {
3093 return 0;
3094 }
3095 int i;
3096 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
3097 if (cs1.charAt(i) != cs2.charAt(i)) {
3098 break;
3099 }
3100 }
3101 if (i > 0 && i < cs1.length() && i < cs2.length() && Character.isHighSurrogate(cs1.charAt(i - 1))
3102 && (Character.isLowSurrogate(cs1.charAt(i)) || Character.isLowSurrogate(cs2.charAt(i)))) {
3103 // the difference splits a surrogate pair whose high half is common; report the start of the
3104 // pair so difference does not return a string that begins with a stray low surrogate.
3105 i--;
3106 }
3107 if (i < cs2.length() || i < cs1.length()) {
3108 return i;
3109 }
3110 return INDEX_NOT_FOUND;
3111 }
3112
3113 /**
3114 * Case insensitive find of the first index within a CharSequence.
3115 *
3116 * <p>
3117 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
3118 * start position greater than the string length only matches an empty search CharSequence.
3119 * </p>
3120 *
3121 * <pre>
3122 * StringUtils.indexOfIgnoreCase(null, *) = -1
3123 * StringUtils.indexOfIgnoreCase(*, null) = -1
3124 * StringUtils.indexOfIgnoreCase("", "") = 0
3125 * StringUtils.indexOfIgnoreCase(" ", " ") = 0
3126 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0
3127 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2
3128 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
3129 * </pre>
3130 *
3131 * @param str The CharSequence to check, may be null.
3132 * @param searchStr The CharSequence to find, may be null.
3133 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input.
3134 * @since 2.5
3135 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
3136 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}.
3137 */
3138 @Deprecated
3139 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
3140 return Strings.CI.indexOf(str, searchStr);
3141 }
3142
3143 /**
3144 * Case insensitive find of the first index within a CharSequence from the specified position.
3145 *
3146 * <p>
3147 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
3148 * start position greater than the string length only matches an empty search CharSequence.
3149 * </p>
3150 *
3151 * <pre>
3152 * StringUtils.indexOfIgnoreCase(null, *, *) = -1
3153 * StringUtils.indexOfIgnoreCase(*, null, *) = -1
3154 * StringUtils.indexOfIgnoreCase("", "", 0) = 0
3155 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0
3156 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2
3157 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
3158 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5
3159 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1
3160 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
3161 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2
3162 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1
3163 * </pre>
3164 *
3165 * @param str The CharSequence to check, may be null.
3166 * @param searchStr The CharSequence to find, may be null.
3167 * @param startPos The start position, negative treated as zero.
3168 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input.
3169 * @since 2.5
3170 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
3171 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}.
3172 */
3173 @Deprecated
3174 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
3175 return Strings.CI.indexOf(str, searchStr, startPos);
3176 }
3177
3178 /**
3179 * Tests if all of the CharSequences are empty (""), null or whitespace only.
3180 *
3181 * <p>
3182 * Whitespace is defined by {@link Character#isWhitespace(char)}.
3183 * </p>
3184 *
3185 * <pre>
3186 * StringUtils.isAllBlank(null) = true
3187 * StringUtils.isAllBlank(null, "foo") = false
3188 * StringUtils.isAllBlank(null, null) = true
3189 * StringUtils.isAllBlank("", "bar") = false
3190 * StringUtils.isAllBlank("bob", "") = false
3191 * StringUtils.isAllBlank(" bob ", null) = false
3192 * StringUtils.isAllBlank(" ", "bar") = false
3193 * StringUtils.isAllBlank("foo", "bar") = false
3194 * StringUtils.isAllBlank(new String[] {}) = true
3195 * </pre>
3196 *
3197 * @param css The CharSequences to check, may be null or empty.
3198 * @return {@code true} if all of the CharSequences are empty or null or whitespace only.
3199 * @since 3.6
3200 */
3201 public static boolean isAllBlank(final CharSequence... css) {
3202 if (ArrayUtils.isEmpty(css)) {
3203 return true;
3204 }
3205 for (final CharSequence cs : css) {
3206 if (isNotBlank(cs)) {
3207 return false;
3208 }
3209 }
3210 return true;
3211 }
3212
3213 /**
3214 * Tests if all of the CharSequences are empty ("") or null.
3215 *
3216 * <pre>
3217 * StringUtils.isAllEmpty(null) = true
3218 * StringUtils.isAllEmpty(null, "") = true
3219 * StringUtils.isAllEmpty(new String[] {}) = true
3220 * StringUtils.isAllEmpty(null, "foo") = false
3221 * StringUtils.isAllEmpty("", "bar") = false
3222 * StringUtils.isAllEmpty("bob", "") = false
3223 * StringUtils.isAllEmpty(" bob ", null) = false
3224 * StringUtils.isAllEmpty(" ", "bar") = false
3225 * StringUtils.isAllEmpty("foo", "bar") = false
3226 * </pre>
3227 *
3228 * @param css The CharSequences to check, may be null or empty.
3229 * @return {@code true} if all of the CharSequences are empty or null.
3230 * @since 3.6
3231 */
3232 public static boolean isAllEmpty(final CharSequence... css) {
3233 if (ArrayUtils.isEmpty(css)) {
3234 return true;
3235 }
3236 for (final CharSequence cs : css) {
3237 if (isNotEmpty(cs)) {
3238 return false;
3239 }
3240 }
3241 return true;
3242 }
3243
3244 /**
3245 * Tests if the CharSequence contains only lowercase characters.
3246 *
3247 * <p>
3248 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3249 * </p>
3250 *
3251 * <pre>
3252 * StringUtils.isAllLowerCase(null) = false
3253 * StringUtils.isAllLowerCase("") = false
3254 * StringUtils.isAllLowerCase(" ") = false
3255 * StringUtils.isAllLowerCase("abc") = true
3256 * StringUtils.isAllLowerCase("abC") = false
3257 * StringUtils.isAllLowerCase("ab c") = false
3258 * StringUtils.isAllLowerCase("ab1c") = false
3259 * StringUtils.isAllLowerCase("ab/c") = false
3260 * </pre>
3261 *
3262 * @param cs The CharSequence to check, may be null.
3263 * @return {@code true} if only contains lowercase characters, and is non-null.
3264 * @since 2.5
3265 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
3266 */
3267 public static boolean isAllLowerCase(final CharSequence cs) {
3268 if (isEmpty(cs)) {
3269 return false;
3270 }
3271 final int sz = cs.length();
3272 for (int i = 0; i < sz;) {
3273 final int codePoint = Character.codePointAt(cs, i);
3274 if (!Character.isLowerCase(codePoint)) {
3275 return false;
3276 }
3277 i += Character.charCount(codePoint);
3278 }
3279 return true;
3280 }
3281
3282 /**
3283 * Tests if the CharSequence contains only uppercase characters.
3284 *
3285 * <p>
3286 * {@code null} will return {@code false}.
3287 * An empty String (length()=0) will return {@code false}.
3288 * </p>
3289 *
3290 * <pre>
3291 * StringUtils.isAllUpperCase(null) = false
3292 * StringUtils.isAllUpperCase("") = false
3293 * StringUtils.isAllUpperCase(" ") = false
3294 * StringUtils.isAllUpperCase("ABC") = true
3295 * StringUtils.isAllUpperCase("aBC") = false
3296 * StringUtils.isAllUpperCase("A C") = false
3297 * StringUtils.isAllUpperCase("A1C") = false
3298 * StringUtils.isAllUpperCase("A/C") = false
3299 * </pre>
3300 *
3301 * @param cs The CharSequence to check, may be null.
3302 * @return {@code true} if only contains uppercase characters, and is non-null.
3303 * @since 2.5
3304 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
3305 */
3306 public static boolean isAllUpperCase(final CharSequence cs) {
3307 if (isEmpty(cs)) {
3308 return false;
3309 }
3310 final int sz = cs.length();
3311 for (int i = 0; i < sz;) {
3312 final int codePoint = Character.codePointAt(cs, i);
3313 if (!Character.isUpperCase(codePoint)) {
3314 return false;
3315 }
3316 i += Character.charCount(codePoint);
3317 }
3318 return true;
3319 }
3320
3321 /**
3322 * Tests if the CharSequence contains only Unicode letters.
3323 *
3324 * <p>
3325 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3326 * </p>
3327 *
3328 * <pre>
3329 * StringUtils.isAlpha(null) = false
3330 * StringUtils.isAlpha("") = false
3331 * StringUtils.isAlpha(" ") = false
3332 * StringUtils.isAlpha("abc") = true
3333 * StringUtils.isAlpha("ab2c") = false
3334 * StringUtils.isAlpha("ab-c") = false
3335 * </pre>
3336 *
3337 * @param cs The CharSequence to check, may be null.
3338 * @return {@code true} if only contains letters, and is non-null.
3339 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
3340 * @since 3.0 Changed "" to return false and not true
3341 */
3342 public static boolean isAlpha(final CharSequence cs) {
3343 if (isEmpty(cs)) {
3344 return false;
3345 }
3346 final int sz = cs.length();
3347 for (int i = 0; i < sz;) {
3348 final int codePoint = Character.codePointAt(cs, i);
3349 if (!Character.isLetter(codePoint)) {
3350 return false;
3351 }
3352 i += Character.charCount(codePoint);
3353 }
3354 return true;
3355 }
3356
3357 /**
3358 * Tests if the CharSequence contains only Unicode letters or digits.
3359 *
3360 * <p>
3361 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3362 * </p>
3363 *
3364 * <pre>
3365 * StringUtils.isAlphanumeric(null) = false
3366 * StringUtils.isAlphanumeric("") = false
3367 * StringUtils.isAlphanumeric(" ") = false
3368 * StringUtils.isAlphanumeric("abc") = true
3369 * StringUtils.isAlphanumeric("ab c") = false
3370 * StringUtils.isAlphanumeric("ab2c") = true
3371 * StringUtils.isAlphanumeric("ab-c") = false
3372 * </pre>
3373 *
3374 * @param cs The CharSequence to check, may be null.
3375 * @return {@code true} if only contains letters or digits, and is non-null.
3376 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
3377 * @since 3.0 Changed "" to return false and not true
3378 */
3379 public static boolean isAlphanumeric(final CharSequence cs) {
3380 if (isEmpty(cs)) {
3381 return false;
3382 }
3383 final int sz = cs.length();
3384 for (int i = 0; i < sz;) {
3385 final int codePoint = Character.codePointAt(cs, i);
3386 if (!Character.isLetterOrDigit(codePoint)) {
3387 return false;
3388 }
3389 i += Character.charCount(codePoint);
3390 }
3391 return true;
3392 }
3393
3394 /**
3395 * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}).
3396 *
3397 * <p>
3398 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3399 * </p>
3400 *
3401 * <pre>
3402 * StringUtils.isAlphanumericSpace(null) = false
3403 * StringUtils.isAlphanumericSpace("") = true
3404 * StringUtils.isAlphanumericSpace(" ") = true
3405 * StringUtils.isAlphanumericSpace("abc") = true
3406 * StringUtils.isAlphanumericSpace("ab c") = true
3407 * StringUtils.isAlphanumericSpace("ab2c") = true
3408 * StringUtils.isAlphanumericSpace("ab-c") = false
3409 * </pre>
3410 *
3411 * @param cs The CharSequence to check, may be null.
3412 * @return {@code true} if only contains letters, digits or space, and is non-null.
3413 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
3414 */
3415 public static boolean isAlphanumericSpace(final CharSequence cs) {
3416 if (cs == null) {
3417 return false;
3418 }
3419 final int sz = cs.length();
3420 for (int i = 0; i < sz;) {
3421 final int codePoint = Character.codePointAt(cs, i);
3422 if (codePoint != ' ' && !Character.isLetterOrDigit(codePoint)) {
3423 return false;
3424 }
3425 i += Character.charCount(codePoint);
3426 }
3427 return true;
3428 }
3429
3430 /**
3431 * Tests if the CharSequence contains only Unicode letters and space (' ').
3432 *
3433 * <p>
3434 * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}.
3435 * </p>
3436 *
3437 * <pre>
3438 * StringUtils.isAlphaSpace(null) = false
3439 * StringUtils.isAlphaSpace("") = true
3440 * StringUtils.isAlphaSpace(" ") = true
3441 * StringUtils.isAlphaSpace("abc") = true
3442 * StringUtils.isAlphaSpace("ab c") = true
3443 * StringUtils.isAlphaSpace("ab2c") = false
3444 * StringUtils.isAlphaSpace("ab-c") = false
3445 * </pre>
3446 *
3447 * @param cs The CharSequence to check, may be null.
3448 * @return {@code true} if only contains letters and space, and is non-null.
3449 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
3450 */
3451 public static boolean isAlphaSpace(final CharSequence cs) {
3452 if (cs == null) {
3453 return false;
3454 }
3455 final int sz = cs.length();
3456 for (int i = 0; i < sz;) {
3457 final int codePoint = Character.codePointAt(cs, i);
3458 if (codePoint != ' ' && !Character.isLetter(codePoint)) {
3459 return false;
3460 }
3461 i += Character.charCount(codePoint);
3462 }
3463 return true;
3464 }
3465
3466 /**
3467 * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3468 *
3469 * <p>
3470 * Whitespace is defined by {@link Character#isWhitespace(char)}.
3471 * </p>
3472 *
3473 * <pre>
3474 * StringUtils.isAnyBlank((String) null) = true
3475 * StringUtils.isAnyBlank((String[]) null) = false
3476 * StringUtils.isAnyBlank(null, "foo") = true
3477 * StringUtils.isAnyBlank(null, null) = true
3478 * StringUtils.isAnyBlank("", "bar") = true
3479 * StringUtils.isAnyBlank("bob", "") = true
3480 * StringUtils.isAnyBlank(" bob ", null) = true
3481 * StringUtils.isAnyBlank(" ", "bar") = true
3482 * StringUtils.isAnyBlank(new String[] {}) = false
3483 * StringUtils.isAnyBlank(new String[]{""}) = true
3484 * StringUtils.isAnyBlank("foo", "bar") = false
3485 * </pre>
3486 *
3487 * @param css The CharSequences to check, may be null or empty.
3488 * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3489 * @see #isBlank(CharSequence)
3490 * @since 3.2
3491 */
3492 public static boolean isAnyBlank(final CharSequence... css) {
3493 if (ArrayUtils.isEmpty(css)) {
3494 return false;
3495 }
3496 for (final CharSequence cs : css) {
3497 if (isBlank(cs)) {
3498 return true;
3499 }
3500 }
3501 return false;
3502 }
3503
3504 /**
3505 * Tests if any of the CharSequences are empty ("") or null.
3506 *
3507 * <pre>
3508 * StringUtils.isAnyEmpty((String) null) = true
3509 * StringUtils.isAnyEmpty((String[]) null) = false
3510 * StringUtils.isAnyEmpty(null, "foo") = true
3511 * StringUtils.isAnyEmpty("", "bar") = true
3512 * StringUtils.isAnyEmpty("bob", "") = true
3513 * StringUtils.isAnyEmpty(" bob ", null) = true
3514 * StringUtils.isAnyEmpty(" ", "bar") = false
3515 * StringUtils.isAnyEmpty("foo", "bar") = false
3516 * StringUtils.isAnyEmpty(new String[]{}) = false
3517 * StringUtils.isAnyEmpty(new String[]{""}) = true
3518 * </pre>
3519 *
3520 * @param css The CharSequences to check, may be null or empty.
3521 * @return {@code true} if any of the CharSequences are empty or null.
3522 * @since 3.2
3523 */
3524 public static boolean isAnyEmpty(final CharSequence... css) {
3525 if (ArrayUtils.isEmpty(css)) {
3526 return false;
3527 }
3528 for (final CharSequence cs : css) {
3529 if (isEmpty(cs)) {
3530 return true;
3531 }
3532 }
3533 return false;
3534 }
3535
3536 /**
3537 * Tests if the CharSequence contains only ASCII printable characters.
3538 *
3539 * <p>
3540 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3541 * </p>
3542 *
3543 * <pre>
3544 * StringUtils.isAsciiPrintable(null) = false
3545 * StringUtils.isAsciiPrintable("") = true
3546 * StringUtils.isAsciiPrintable(" ") = true
3547 * StringUtils.isAsciiPrintable("Ceki") = true
3548 * StringUtils.isAsciiPrintable("ab2c") = true
3549 * StringUtils.isAsciiPrintable("!ab-c~") = true
3550 * StringUtils.isAsciiPrintable("\u0020") = true
3551 * StringUtils.isAsciiPrintable("\u0021") = true
3552 * StringUtils.isAsciiPrintable("\u007e") = true
3553 * StringUtils.isAsciiPrintable("\u007f") = false
3554 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
3555 * </pre>
3556 *
3557 * @param cs The CharSequence to check, may be null.
3558 * @return {@code true} if every character is in the range 32 through 126.
3559 * @since 2.1
3560 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
3561 */
3562 public static boolean isAsciiPrintable(final CharSequence cs) {
3563 if (cs == null) {
3564 return false;
3565 }
3566 final int sz = cs.length();
3567 for (int i = 0; i < sz; i++) {
3568 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
3569 return false;
3570 }
3571 }
3572 return true;
3573 }
3574
3575 /**
3576 * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}.
3577 *
3578 * <pre>
3579 * StringUtils.isBlank(null) = true
3580 * StringUtils.isBlank("") = true
3581 * StringUtils.isBlank(" ") = true
3582 * StringUtils.isBlank("bob") = false
3583 * StringUtils.isBlank(" bob ") = false
3584 * </pre>
3585 *
3586 * @param cs The CharSequence to check, may be null.
3587 * @return {@code true} if the CharSequence is null, empty or whitespace only.
3588 * @since 2.0
3589 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
3590 */
3591 public static boolean isBlank(final CharSequence cs) {
3592 final int strLen = length(cs);
3593 for (int i = 0; i < strLen; i++) {
3594 if (!Character.isWhitespace(cs.charAt(i))) {
3595 return false;
3596 }
3597 }
3598 return true;
3599 }
3600
3601 /**
3602 * Tests if a CharSequence is empty ("") or null.
3603 *
3604 * <pre>
3605 * StringUtils.isEmpty(null) = true
3606 * StringUtils.isEmpty("") = true
3607 * StringUtils.isEmpty(" ") = false
3608 * StringUtils.isEmpty("bob") = false
3609 * StringUtils.isEmpty(" bob ") = false
3610 * </pre>
3611 *
3612 * <p>
3613 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank().
3614 * </p>
3615 *
3616 * @param cs The CharSequence to check, may be null.
3617 * @return {@code true} if the CharSequence is empty or null.
3618 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
3619 */
3620 public static boolean isEmpty(final CharSequence cs) {
3621 return cs == null || cs.length() == 0;
3622 }
3623
3624 /**
3625 * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters.
3626 *
3627 * <p>
3628 * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}.
3629 * </p>
3630 *
3631 * <pre>
3632 * StringUtils.isMixedCase(null) = false
3633 * StringUtils.isMixedCase("") = false
3634 * StringUtils.isMixedCase(" ") = false
3635 * StringUtils.isMixedCase("ABC") = false
3636 * StringUtils.isMixedCase("abc") = false
3637 * StringUtils.isMixedCase("aBc") = true
3638 * StringUtils.isMixedCase("A c") = true
3639 * StringUtils.isMixedCase("A1c") = true
3640 * StringUtils.isMixedCase("a/C") = true
3641 * StringUtils.isMixedCase("aC\t") = true
3642 * </pre>
3643 *
3644 * @param cs The CharSequence to check, may be null.
3645 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters.
3646 * @since 3.5
3647 */
3648 public static boolean isMixedCase(final CharSequence cs) {
3649 if (isEmpty(cs) || cs.length() == 1) {
3650 return false;
3651 }
3652 boolean containsUppercase = false;
3653 boolean containsLowercase = false;
3654 final int sz = cs.length();
3655 for (int i = 0; i < sz;) {
3656 final int codePoint = Character.codePointAt(cs, i);
3657 if (Character.isUpperCase(codePoint)) {
3658 containsUppercase = true;
3659 } else if (Character.isLowerCase(codePoint)) {
3660 containsLowercase = true;
3661 }
3662 if (containsUppercase && containsLowercase) {
3663 return true;
3664 }
3665 i += Character.charCount(codePoint);
3666 }
3667 return false;
3668 }
3669
3670 /**
3671 * Tests if none of the CharSequences are empty (""), null or whitespace only.
3672 *
3673 * <p>
3674 * Whitespace is defined by {@link Character#isWhitespace(char)}.
3675 * </p>
3676 *
3677 * <pre>
3678 * StringUtils.isNoneBlank((String) null) = false
3679 * StringUtils.isNoneBlank((String[]) null) = true
3680 * StringUtils.isNoneBlank(null, "foo") = false
3681 * StringUtils.isNoneBlank(null, null) = false
3682 * StringUtils.isNoneBlank("", "bar") = false
3683 * StringUtils.isNoneBlank("bob", "") = false
3684 * StringUtils.isNoneBlank(" bob ", null) = false
3685 * StringUtils.isNoneBlank(" ", "bar") = false
3686 * StringUtils.isNoneBlank(new String[] {}) = true
3687 * StringUtils.isNoneBlank(new String[]{""}) = false
3688 * StringUtils.isNoneBlank("foo", "bar") = true
3689 * </pre>
3690 *
3691 * @param css The CharSequences to check, may be null or empty.
3692 * @return {@code true} if none of the CharSequences are empty or null or whitespace only.
3693 * @since 3.2
3694 */
3695 public static boolean isNoneBlank(final CharSequence... css) {
3696 return !isAnyBlank(css);
3697 }
3698
3699 /**
3700 * Tests if none of the CharSequences are empty ("") or null.
3701 *
3702 * <pre>
3703 * StringUtils.isNoneEmpty((String) null) = false
3704 * StringUtils.isNoneEmpty((String[]) null) = true
3705 * StringUtils.isNoneEmpty(null, "foo") = false
3706 * StringUtils.isNoneEmpty("", "bar") = false
3707 * StringUtils.isNoneEmpty("bob", "") = false
3708 * StringUtils.isNoneEmpty(" bob ", null) = false
3709 * StringUtils.isNoneEmpty(new String[] {}) = true
3710 * StringUtils.isNoneEmpty(new String[]{""}) = false
3711 * StringUtils.isNoneEmpty(" ", "bar") = true
3712 * StringUtils.isNoneEmpty("foo", "bar") = true
3713 * </pre>
3714 *
3715 * @param css The CharSequences to check, may be null or empty.
3716 * @return {@code true} if none of the CharSequences are empty or null.
3717 * @since 3.2
3718 */
3719 public static boolean isNoneEmpty(final CharSequence... css) {
3720 return !isAnyEmpty(css);
3721 }
3722
3723 /**
3724 * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3725 *
3726 * <p>
3727 * Whitespace is defined by {@link Character#isWhitespace(char)}.
3728 * </p>
3729 *
3730 * <pre>
3731 * StringUtils.isNotBlank(null) = false
3732 * StringUtils.isNotBlank("") = false
3733 * StringUtils.isNotBlank(" ") = false
3734 * StringUtils.isNotBlank("bob") = true
3735 * StringUtils.isNotBlank(" bob ") = true
3736 * </pre>
3737 *
3738 * @param cs The CharSequence to check, may be null.
3739 * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3740 * @see #isBlank(CharSequence)
3741 * @since 2.0
3742 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
3743 */
3744 public static boolean isNotBlank(final CharSequence cs) {
3745 return !isBlank(cs);
3746 }
3747
3748 /**
3749 * Tests if a CharSequence is not empty ("") and not null.
3750 *
3751 * <pre>
3752 * StringUtils.isNotEmpty(null) = false
3753 * StringUtils.isNotEmpty("") = false
3754 * StringUtils.isNotEmpty(" ") = true
3755 * StringUtils.isNotEmpty("bob") = true
3756 * StringUtils.isNotEmpty(" bob ") = true
3757 * </pre>
3758 *
3759 * @param cs The CharSequence to check, may be null.
3760 * @return {@code true} if the CharSequence is not empty and not null.
3761 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
3762 */
3763 public static boolean isNotEmpty(final CharSequence cs) {
3764 return !isEmpty(cs);
3765 }
3766
3767 /**
3768 * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false.
3769 *
3770 * <p>
3771 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3772 * </p>
3773 *
3774 * <p>
3775 * Note that the method does not allow for a leading sign, either positive or negative. Also, if a String passes the numeric test, it may still generate a
3776 * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively.
3777 * </p>
3778 *
3779 * <pre>
3780 * StringUtils.isNumeric(null) = false
3781 * StringUtils.isNumeric("") = false
3782 * StringUtils.isNumeric(" ") = false
3783 * StringUtils.isNumeric("123") = true
3784 * StringUtils.isNumeric("\u0967\u0968\u0969") = true
3785 * StringUtils.isNumeric("12 3") = false
3786 * StringUtils.isNumeric("ab2c") = false
3787 * StringUtils.isNumeric("12-3") = false
3788 * StringUtils.isNumeric("12.3") = false
3789 * StringUtils.isNumeric("-123") = false
3790 * StringUtils.isNumeric("+123") = false
3791 * </pre>
3792 *
3793 * @param cs The CharSequence to check, may be null.
3794 * @return {@code true} if only contains digits, and is non-null.
3795 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
3796 * @since 3.0 Changed "" to return false and not true
3797 */
3798 public static boolean isNumeric(final CharSequence cs) {
3799 if (isEmpty(cs)) {
3800 return false;
3801 }
3802 final int sz = cs.length();
3803 for (int i = 0; i < sz;) {
3804 final int codePoint = Character.codePointAt(cs, i);
3805 if (!Character.isDigit(codePoint)) {
3806 return false;
3807 }
3808 i += Character.charCount(codePoint);
3809 }
3810 return true;
3811 }
3812
3813 /**
3814 * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false.
3815 *
3816 * <p>
3817 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3818 * </p>
3819 *
3820 * <pre>
3821 * StringUtils.isNumericSpace(null) = false
3822 * StringUtils.isNumericSpace("") = true
3823 * StringUtils.isNumericSpace(" ") = true
3824 * StringUtils.isNumericSpace("123") = true
3825 * StringUtils.isNumericSpace("12 3") = true
3826 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true
3827 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true
3828 * StringUtils.isNumericSpace("ab2c") = false
3829 * StringUtils.isNumericSpace("12-3") = false
3830 * StringUtils.isNumericSpace("12.3") = false
3831 * </pre>
3832 *
3833 * @param cs The CharSequence to check, may be null.
3834 * @return {@code true} if only contains digits or space, and is non-null.
3835 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
3836 */
3837 public static boolean isNumericSpace(final CharSequence cs) {
3838 if (cs == null) {
3839 return false;
3840 }
3841 final int sz = cs.length();
3842 for (int i = 0; i < sz;) {
3843 final int codePoint = Character.codePointAt(cs, i);
3844 if (codePoint != ' ' && !Character.isDigit(codePoint)) {
3845 return false;
3846 }
3847 i += Character.charCount(codePoint);
3848 }
3849 return true;
3850 }
3851
3852 /**
3853 * Tests if the CharSequence contains only whitespace.
3854 *
3855 * <p>
3856 * Whitespace is defined by {@link Character#isWhitespace(char)}.
3857 * </p>
3858 *
3859 * <p>
3860 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3861 * </p>
3862 *
3863 * <pre>
3864 * StringUtils.isWhitespace(null) = false
3865 * StringUtils.isWhitespace("") = true
3866 * StringUtils.isWhitespace(" ") = true
3867 * StringUtils.isWhitespace("abc") = false
3868 * StringUtils.isWhitespace("ab2c") = false
3869 * StringUtils.isWhitespace("ab-c") = false
3870 * </pre>
3871 *
3872 * @param cs The CharSequence to check, may be null.
3873 * @return {@code true} if only contains whitespace, and is non-null.
3874 * @since 2.0
3875 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
3876 */
3877 public static boolean isWhitespace(final CharSequence cs) {
3878 if (cs == null) {
3879 return false;
3880 }
3881 final int sz = cs.length();
3882 for (int i = 0; i < sz; i++) {
3883 if (!Character.isWhitespace(cs.charAt(i))) {
3884 return false;
3885 }
3886 }
3887 return true;
3888 }
3889
3890 /**
3891 * Joins the elements of the provided array into a single String containing the provided list of elements.
3892 *
3893 * <p>
3894 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
3895 * </p>
3896 *
3897 * <pre>
3898 * StringUtils.join(null, *) = null
3899 * StringUtils.join([], *) = ""
3900 * StringUtils.join([null], *) = ""
3901 * StringUtils.join([false, false], ';') = "false;false"
3902 * </pre>
3903 *
3904 * @param array The array of values to join together, may be null.
3905 * @param delimiter The separator character to use.
3906 * @return The joined String, {@code null} if null array input.
3907 * @since 3.12.0
3908 */
3909 public static String join(final boolean[] array, final char delimiter) {
3910 if (array == null) {
3911 return null;
3912 }
3913 return join(array, delimiter, 0, array.length);
3914 }
3915
3916 /**
3917 * Joins the elements of the provided array into a single String containing the provided list of elements.
3918 *
3919 * <p>
3920 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3921 * by empty strings.
3922 * </p>
3923 *
3924 * <pre>
3925 * StringUtils.join(null, *) = null
3926 * StringUtils.join([], *) = ""
3927 * StringUtils.join([null], *) = ""
3928 * StringUtils.join([true, false, true], ';') = "true;false;true"
3929 * </pre>
3930 *
3931 * @param array
3932 * the array of values to join together, may be null.
3933 * @param delimiter
3934 * the separator character to use.
3935 * @param startIndex
3936 * the first index to start joining from. It is an error to pass in a start index past the end of the
3937 * array.
3938 * @param endIndex
3939 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
3940 * the array.
3941 * @return The joined String, {@code null} if null array input.
3942 * @since 3.12.0
3943 */
3944 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
3945 // See StringUtilsJoinBenchmark
3946 if (array == null) {
3947 return null;
3948 }
3949 checkFromToIndex(startIndex, endIndex, array.length);
3950 final int count = endIndex - startIndex;
3951 if (count <= 0) {
3952 return EMPTY;
3953 }
3954 final byte maxElementChars = 5; // "false"
3955 final StringBuilder stringBuilder = capacity(count, maxElementChars);
3956 stringBuilder.append(array[startIndex]);
3957 for (int i = startIndex + 1; i < endIndex; i++) {
3958 stringBuilder.append(delimiter).append(array[i]);
3959 }
3960 return stringBuilder.toString();
3961 }
3962
3963 /**
3964 * Joins the elements of the provided array into a single String containing the provided list of elements.
3965 *
3966 * <p>
3967 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3968 * by empty strings.
3969 * </p>
3970 *
3971 * <pre>
3972 * StringUtils.join(null, *) = null
3973 * StringUtils.join([], *) = ""
3974 * StringUtils.join([null], *) = ""
3975 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
3976 * StringUtils.join([1, 2, 3], null) = "123"
3977 * </pre>
3978 *
3979 * @param array
3980 * the array of values to join together, may be null.
3981 * @param delimiter
3982 * the separator character to use.
3983 * @return The joined String, {@code null} if null array input.
3984 * @since 3.2
3985 */
3986 public static String join(final byte[] array, final char delimiter) {
3987 if (array == null) {
3988 return null;
3989 }
3990 return join(array, delimiter, 0, array.length);
3991 }
3992
3993 /**
3994 * Joins the elements of the provided array into a single String containing the provided list of elements.
3995 *
3996 * <p>
3997 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3998 * by empty strings.
3999 * </p>
4000 *
4001 * <pre>
4002 * StringUtils.join(null, *) = null
4003 * StringUtils.join([], *) = ""
4004 * StringUtils.join([null], *) = ""
4005 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4006 * StringUtils.join([1, 2, 3], null) = "123"
4007 * </pre>
4008 *
4009 * @param array
4010 * the array of values to join together, may be null.
4011 * @param delimiter
4012 * the separator character to use.
4013 * @param startIndex
4014 * the first index to start joining from. It is an error to pass in a start index past the end of the
4015 * array.
4016 * @param endIndex
4017 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4018 * the array.
4019 * @return The joined String, {@code null} if null array input.
4020 * @since 3.2
4021 */
4022 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
4023 // See StringUtilsJoinBenchmark
4024 if (array == null) {
4025 return null;
4026 }
4027 checkFromToIndex(startIndex, endIndex, array.length);
4028 final int count = endIndex - startIndex;
4029 if (count <= 0) {
4030 return EMPTY;
4031 }
4032 final byte maxElementChars = 4; // "-128"
4033 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4034 stringBuilder.append(array[startIndex]);
4035 for (int i = startIndex + 1; i < endIndex; i++) {
4036 stringBuilder.append(delimiter).append(array[i]);
4037 }
4038 return stringBuilder.toString();
4039 }
4040
4041 /**
4042 * Joins the elements of the provided array into a single String containing the provided list of elements.
4043 *
4044 * <p>
4045 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4046 * by empty strings.
4047 * </p>
4048 *
4049 * <pre>
4050 * StringUtils.join(null, *) = null
4051 * StringUtils.join([], *) = ""
4052 * StringUtils.join([null], *) = ""
4053 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4054 * StringUtils.join([1, 2, 3], null) = "123"
4055 * </pre>
4056 *
4057 * @param array
4058 * the array of values to join together, may be null.
4059 * @param delimiter
4060 * the separator character to use.
4061 * @return The joined String, {@code null} if null array input.
4062 * @since 3.2
4063 */
4064 public static String join(final char[] array, final char delimiter) {
4065 if (array == null) {
4066 return null;
4067 }
4068 return join(array, delimiter, 0, array.length);
4069 }
4070
4071 /**
4072 * Joins the elements of the provided array into a single String containing the provided list of elements.
4073 *
4074 * <p>
4075 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4076 * by empty strings.
4077 * </p>
4078 *
4079 * <pre>
4080 * StringUtils.join(null, *) = null
4081 * StringUtils.join([], *) = ""
4082 * StringUtils.join([null], *) = ""
4083 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4084 * StringUtils.join([1, 2, 3], null) = "123"
4085 * </pre>
4086 *
4087 * @param array
4088 * the array of values to join together, may be null.
4089 * @param delimiter
4090 * the separator character to use.
4091 * @param startIndex
4092 * the first index to start joining from. It is an error to pass in a start index past the end of the
4093 * array.
4094 * @param endIndex
4095 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4096 * the array.
4097 * @return The joined String, {@code null} if null array input.
4098 * @since 3.2
4099 */
4100 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
4101 // See StringUtilsJoinBenchmark
4102 if (array == null) {
4103 return null;
4104 }
4105 checkFromToIndex(startIndex, endIndex, array.length);
4106 final int count = endIndex - startIndex;
4107 if (count <= 0) {
4108 return EMPTY;
4109 }
4110 final byte maxElementChars = 1;
4111 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4112 stringBuilder.append(array[startIndex]);
4113 for (int i = startIndex + 1; i < endIndex; i++) {
4114 stringBuilder.append(delimiter).append(array[i]);
4115 }
4116 return stringBuilder.toString();
4117 }
4118
4119 /**
4120 * Joins the elements of the provided array into a single String containing the provided list of elements.
4121 *
4122 * <p>
4123 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4124 * by empty strings.
4125 * </p>
4126 *
4127 * <pre>
4128 * StringUtils.join(null, *) = null
4129 * StringUtils.join([], *) = ""
4130 * StringUtils.join([null], *) = ""
4131 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4132 * StringUtils.join([1, 2, 3], null) = "123"
4133 * </pre>
4134 *
4135 * @param array
4136 * the array of values to join together, may be null.
4137 * @param delimiter
4138 * the separator character to use.
4139 * @return The joined String, {@code null} if null array input.
4140 * @since 3.2
4141 */
4142 public static String join(final double[] array, final char delimiter) {
4143 if (array == null) {
4144 return null;
4145 }
4146 return join(array, delimiter, 0, array.length);
4147 }
4148
4149 /**
4150 * Joins the elements of the provided array into a single String containing the provided list of elements.
4151 *
4152 * <p>
4153 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4154 * by empty strings.
4155 * </p>
4156 *
4157 * <pre>
4158 * StringUtils.join(null, *) = null
4159 * StringUtils.join([], *) = ""
4160 * StringUtils.join([null], *) = ""
4161 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4162 * StringUtils.join([1, 2, 3], null) = "123"
4163 * </pre>
4164 *
4165 * @param array
4166 * the array of values to join together, may be null.
4167 * @param delimiter
4168 * the separator character to use.
4169 * @param startIndex
4170 * the first index to start joining from. It is an error to pass in a start index past the end of the
4171 * array.
4172 * @param endIndex
4173 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4174 * the array.
4175 * @return The joined String, {@code null} if null array input.
4176 * @since 3.2
4177 */
4178 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
4179 // See StringUtilsJoinBenchmark
4180 if (array == null) {
4181 return null;
4182 }
4183 checkFromToIndex(startIndex, endIndex, array.length);
4184 final int count = endIndex - startIndex;
4185 if (count <= 0) {
4186 return EMPTY;
4187 }
4188 final byte maxElementChars = 22; // "1.7976931348623157E308"
4189 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4190 stringBuilder.append(array[startIndex]);
4191 for (int i = startIndex + 1; i < endIndex; i++) {
4192 stringBuilder.append(delimiter).append(array[i]);
4193 }
4194 return stringBuilder.toString();
4195 }
4196
4197 /**
4198 * Joins the elements of the provided array into a single String containing the provided list of elements.
4199 *
4200 * <p>
4201 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4202 * by empty strings.
4203 * </p>
4204 *
4205 * <pre>
4206 * StringUtils.join(null, *) = null
4207 * StringUtils.join([], *) = ""
4208 * StringUtils.join([null], *) = ""
4209 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4210 * StringUtils.join([1, 2, 3], null) = "123"
4211 * </pre>
4212 *
4213 * @param array
4214 * the array of values to join together, may be null.
4215 * @param delimiter
4216 * the separator character to use.
4217 * @return The joined String, {@code null} if null array input
4218 * @since 3.2
4219 */
4220 public static String join(final float[] array, final char delimiter) {
4221 if (array == null) {
4222 return null;
4223 }
4224 return join(array, delimiter, 0, array.length);
4225 }
4226
4227 /**
4228 * Joins the elements of the provided array into a single String containing the provided list of elements.
4229 *
4230 * <p>
4231 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4232 * by empty strings.
4233 * </p>
4234 *
4235 * <pre>
4236 * StringUtils.join(null, *) = null
4237 * StringUtils.join([], *) = ""
4238 * StringUtils.join([null], *) = ""
4239 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4240 * StringUtils.join([1, 2, 3], null) = "123"
4241 * </pre>
4242 *
4243 * @param array
4244 * the array of values to join together, may be null.
4245 * @param delimiter
4246 * the separator character to use.
4247 * @param startIndex
4248 * the first index to start joining from. It is an error to pass in a start index past the end of the
4249 * array.
4250 * @param endIndex
4251 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4252 * the array.
4253 * @return The joined String, {@code null} if null array input.
4254 * @since 3.2
4255 */
4256 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
4257 // See StringUtilsJoinBenchmark
4258 if (array == null) {
4259 return null;
4260 }
4261 checkFromToIndex(startIndex, endIndex, array.length);
4262 final int count = endIndex - startIndex;
4263 if (count <= 0) {
4264 return EMPTY;
4265 }
4266 final byte maxElementChars = 12; // "3.4028235E38"
4267 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4268 stringBuilder.append(array[startIndex]);
4269 for (int i = startIndex + 1; i < endIndex; i++) {
4270 stringBuilder.append(delimiter).append(array[i]);
4271 }
4272 return stringBuilder.toString();
4273 }
4274
4275 /**
4276 * Joins the elements of the provided array into a single String containing the provided list of elements.
4277 *
4278 * <p>
4279 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4280 * by empty strings.
4281 * </p>
4282 *
4283 * <pre>
4284 * StringUtils.join(null, *) = null
4285 * StringUtils.join([], *) = ""
4286 * StringUtils.join([null], *) = ""
4287 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4288 * StringUtils.join([1, 2, 3], null) = "123"
4289 * </pre>
4290 *
4291 * @param array
4292 * the array of values to join together, may be null.
4293 * @param separator
4294 * the separator character to use.
4295 * @return The joined String, {@code null} if null array input.
4296 * @since 3.2
4297 */
4298 public static String join(final int[] array, final char separator) {
4299 if (array == null) {
4300 return null;
4301 }
4302 return join(array, separator, 0, array.length);
4303 }
4304
4305 /**
4306 * Joins the elements of the provided array into a single String containing the provided list of elements.
4307 *
4308 * <p>
4309 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4310 * by empty strings.
4311 * </p>
4312 *
4313 * <pre>
4314 * StringUtils.join(null, *) = null
4315 * StringUtils.join([], *) = ""
4316 * StringUtils.join([null], *) = ""
4317 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4318 * StringUtils.join([1, 2, 3], null) = "123"
4319 * </pre>
4320 *
4321 * @param array
4322 * the array of values to join together, may be null.
4323 * @param delimiter
4324 * the separator character to use.
4325 * @param startIndex
4326 * the first index to start joining from. It is an error to pass in a start index past the end of the
4327 * array.
4328 * @param endIndex
4329 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4330 * the array.
4331 * @return The joined String, {@code null} if null array input.
4332 * @since 3.2
4333 */
4334 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) {
4335 // See StringUtilsJoinBenchmark
4336 if (array == null) {
4337 return null;
4338 }
4339 checkFromToIndex(startIndex, endIndex, array.length);
4340 final int count = endIndex - startIndex;
4341 if (count <= 0) {
4342 return EMPTY;
4343 }
4344 final byte maxElementChars = 11; // "-2147483648"
4345 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4346 stringBuilder.append(array[startIndex]);
4347 for (int i = startIndex + 1; i < endIndex; i++) {
4348 stringBuilder.append(delimiter).append(array[i]);
4349 }
4350 return stringBuilder.toString();
4351 }
4352
4353 /**
4354 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements.
4355 *
4356 * <p>
4357 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings.
4358 * </p>
4359 *
4360 * <p>
4361 * See the examples here: {@link #join(Object[],char)}.
4362 * </p>
4363 *
4364 * @param iterable The {@link Iterable} providing the values to join together, may be null.
4365 * @param separator The separator character to use.
4366 * @return The joined String, {@code null} if null iterator input.
4367 * @since 2.3
4368 */
4369 public static String join(final Iterable<?> iterable, final char separator) {
4370 return iterable != null ? join(iterable.iterator(), separator) : null;
4371 }
4372
4373 /**
4374 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements.
4375 *
4376 * <p>
4377 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String ("").
4378 * </p>
4379 *
4380 * <p>
4381 * See the examples here: {@link #join(Object[],String)}.
4382 * </p>
4383 *
4384 * @param iterable The {@link Iterable} providing the values to join together, may be null.
4385 * @param separator The separator character to use, null treated as "".
4386 * @return The joined String, {@code null} if null iterator input.
4387 * @since 2.3
4388 */
4389 public static String join(final Iterable<?> iterable, final String separator) {
4390 return iterable != null ? join(iterable.iterator(), separator) : null;
4391 }
4392
4393 /**
4394 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements.
4395 *
4396 * <p>
4397 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings.
4398 * </p>
4399 *
4400 * <p>
4401 * See the examples here: {@link #join(Object[],char)}.
4402 * </p>
4403 *
4404 * @param iterator The {@link Iterator} of values to join together, may be null.
4405 * @param separator The separator character to use.
4406 * @return The joined String, {@code null} if null iterator input.
4407 * @since 2.0
4408 */
4409 public static String join(final Iterator<?> iterator, final char separator) {
4410 // handle null, zero and one elements before building a buffer
4411 if (iterator == null) {
4412 return null;
4413 }
4414 if (!iterator.hasNext()) {
4415 return EMPTY;
4416 }
4417 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString));
4418 }
4419
4420 /**
4421 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements.
4422 *
4423 * <p>
4424 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String ("").
4425 * </p>
4426 *
4427 * <p>
4428 * See the examples here: {@link #join(Object[],String)}.
4429 * </p>
4430 *
4431 * @param iterator The {@link Iterator} of values to join together, may be null.
4432 * @param separator The separator character to use, null treated as "".
4433 * @return The joined String, {@code null} if null iterator input.
4434 */
4435 public static String join(final Iterator<?> iterator, final String separator) {
4436 // handle null, zero and one elements before building a buffer
4437 if (iterator == null) {
4438 return null;
4439 }
4440 if (!iterator.hasNext()) {
4441 return EMPTY;
4442 }
4443 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString));
4444 }
4445
4446 /**
4447 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements.
4448 *
4449 * <p>
4450 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4451 * </p>
4452 *
4453 * <pre>
4454 * StringUtils.join(null, *) = null
4455 * StringUtils.join([], *) = ""
4456 * StringUtils.join([null], *) = ""
4457 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
4458 * StringUtils.join(["a", "b", "c"], null) = "abc"
4459 * StringUtils.join([null, "", "a"], ';') = ";;a"
4460 * </pre>
4461 *
4462 * @param list The {@link List} of values to join together, may be null.
4463 * @param separator The separator character to use.
4464 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the list.
4465 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list.
4466 * @return The joined String, {@code null} if null list input.
4467 * @since 3.8
4468 */
4469 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
4470 if (list == null) {
4471 return null;
4472 }
4473 final int noOfItems = endIndex - startIndex;
4474 if (noOfItems <= 0) {
4475 return EMPTY;
4476 }
4477 final List<?> subList = list.subList(startIndex, endIndex);
4478 return join(subList.iterator(), separator);
4479 }
4480
4481 /**
4482 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements.
4483 *
4484 * <p>
4485 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4486 * </p>
4487 *
4488 * <pre>
4489 * StringUtils.join(null, *) = null
4490 * StringUtils.join([], *) = ""
4491 * StringUtils.join([null], *) = ""
4492 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
4493 * StringUtils.join(["a", "b", "c"], null) = "abc"
4494 * StringUtils.join([null, "", "a"], ';') = ";;a"
4495 * </pre>
4496 *
4497 * @param list The {@link List} of values to join together, may be null.
4498 * @param separator The separator character to use.
4499 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the list.
4500 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list.
4501 * @return The joined String, {@code null} if null list input.
4502 * @since 3.8
4503 */
4504 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
4505 if (list == null) {
4506 return null;
4507 }
4508 final int noOfItems = endIndex - startIndex;
4509 if (noOfItems <= 0) {
4510 return EMPTY;
4511 }
4512 final List<?> subList = list.subList(startIndex, endIndex);
4513 return join(subList.iterator(), separator);
4514 }
4515
4516 /**
4517 * Joins the elements of the provided array into a single String containing the provided list of elements.
4518 *
4519 * <p>
4520 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4521 * by empty strings.
4522 * </p>
4523 *
4524 * <pre>
4525 * StringUtils.join(null, *) = null
4526 * StringUtils.join([], *) = ""
4527 * StringUtils.join([null], *) = ""
4528 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4529 * StringUtils.join([1, 2, 3], null) = "123"
4530 * </pre>
4531 *
4532 * @param array
4533 * the array of values to join together, may be null.
4534 * @param separator
4535 * the separator character to use.
4536 * @return The joined String, {@code null} if null array input.
4537 * @since 3.2
4538 */
4539 public static String join(final long[] array, final char separator) {
4540 if (array == null) {
4541 return null;
4542 }
4543 return join(array, separator, 0, array.length);
4544 }
4545
4546 /**
4547 * Joins the elements of the provided array into a single String containing the provided list of elements.
4548 *
4549 * <p>
4550 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4551 * by empty strings.
4552 * </p>
4553 *
4554 * <pre>
4555 * StringUtils.join(null, *) = null
4556 * StringUtils.join([], *) = ""
4557 * StringUtils.join([null], *) = ""
4558 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4559 * StringUtils.join([1, 2, 3], null) = "123"
4560 * </pre>
4561 *
4562 * @param array
4563 * the array of values to join together, may be null.
4564 * @param delimiter
4565 * the separator character to use.
4566 * @param startIndex
4567 * the first index to start joining from. It is an error to pass in a start index past the end of the
4568 * array.
4569 * @param endIndex
4570 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4571 * the array.
4572 * @return The joined String, {@code null} if null array input.
4573 * @since 3.2
4574 */
4575 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
4576 // See StringUtilsJoinBenchmark
4577 if (array == null) {
4578 return null;
4579 }
4580 checkFromToIndex(startIndex, endIndex, array.length);
4581 final int count = endIndex - startIndex;
4582 if (count <= 0) {
4583 return EMPTY;
4584 }
4585 final byte maxElementChars = 20; // "-9223372036854775808"
4586 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4587 stringBuilder.append(array[startIndex]);
4588 for (int i = startIndex + 1; i < endIndex; i++) {
4589 stringBuilder.append(delimiter).append(array[i]);
4590 }
4591 return stringBuilder.toString();
4592 }
4593
4594 /**
4595 * Joins the elements of the provided array into a single String containing the provided list of elements.
4596 *
4597 * <p>
4598 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4599 * </p>
4600 *
4601 * <pre>
4602 * StringUtils.join(null, *) = null
4603 * StringUtils.join([], *) = ""
4604 * StringUtils.join([null], *) = ""
4605 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
4606 * StringUtils.join(["a", "b", "c"], null) = "abc"
4607 * StringUtils.join([null, "", "a"], ';') = ";;a"
4608 * </pre>
4609 *
4610 * @param array The array of values to join together, may be null.
4611 * @param delimiter The separator character to use.
4612 * @return The joined String, {@code null} if null array input.
4613 * @since 2.0
4614 */
4615 public static String join(final Object[] array, final char delimiter) {
4616 if (array == null) {
4617 return null;
4618 }
4619 return join(array, delimiter, 0, array.length);
4620 }
4621
4622 /**
4623 * Joins the elements of the provided array into a single String containing the provided list of elements.
4624 *
4625 * <p>
4626 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4627 * </p>
4628 *
4629 * <pre>
4630 * StringUtils.join(null, *) = null
4631 * StringUtils.join([], *) = ""
4632 * StringUtils.join([null], *) = ""
4633 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
4634 * StringUtils.join(["a", "b", "c"], null) = "abc"
4635 * StringUtils.join([null, "", "a"], ';') = ";;a"
4636 * </pre>
4637 *
4638 * @param array The array of values to join together, may be null.
4639 * @param delimiter The separator character to use.
4640 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the array.
4641 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the array.
4642 * @return The joined String, {@code null} if null array input.
4643 * @since 2.0
4644 */
4645 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) {
4646 return join(array, String.valueOf(delimiter), startIndex, endIndex);
4647 }
4648
4649 /**
4650 * Joins the elements of the provided array into a single String containing the provided list of elements.
4651 *
4652 * <p>
4653 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the
4654 * array are represented by empty strings.
4655 * </p>
4656 *
4657 * <pre>
4658 * StringUtils.join(null, *) = null
4659 * StringUtils.join([], *) = ""
4660 * StringUtils.join([null], *) = ""
4661 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
4662 * StringUtils.join(["a", "b", "c"], null) = "abc"
4663 * StringUtils.join(["a", "b", "c"], "") = "abc"
4664 * StringUtils.join([null, "", "a"], ',') = ",,a"
4665 * </pre>
4666 *
4667 * @param array The array of values to join together, may be null.
4668 * @param delimiter The separator character to use, null treated as "".
4669 * @return The joined String, {@code null} if null array input.
4670 */
4671 public static String join(final Object[] array, final String delimiter) {
4672 return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null;
4673 }
4674
4675 /**
4676 * Joins the elements of the provided array into a single String containing the provided list of elements.
4677 *
4678 * <p>
4679 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the
4680 * array are represented by empty strings.
4681 * </p>
4682 *
4683 * <pre>
4684 * StringUtils.join(null, *, *, *) = null
4685 * StringUtils.join([], *, *, *) = ""
4686 * StringUtils.join([null], *, *, *) = ""
4687 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c"
4688 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c"
4689 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c"
4690 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = ""
4691 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc"
4692 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc"
4693 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a"
4694 * </pre>
4695 *
4696 * @param array The array of values to join together, may be null.
4697 * @param delimiter The separator character to use, null treated as "".
4698 * @param startIndex The first index to start joining from.
4699 * @param endIndex The index to stop joining from (exclusive).
4700 * @return The joined String, {@code null} if null array input; or the empty string if {@code endIndex - startIndex <= 0}. The number of joined entries is
4701 * given by {@code endIndex - startIndex}.
4702 * @throws ArrayIndexOutOfBoundsException Thrown if<br> {@code startIndex < 0} or <br> {@code startIndex >= array.length()} or <br> {@code endIndex < 0} or
4703 * <br> {@code endIndex > array.length()}.
4704 */
4705 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) {
4706 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex))
4707 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null;
4708 }
4709
4710 /**
4711 * Joins the elements of the provided array into a single String containing the provided list of elements.
4712 *
4713 * <p>
4714 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4715 * by empty strings.
4716 * </p>
4717 *
4718 * <pre>
4719 * StringUtils.join(null, *) = null
4720 * StringUtils.join([], *) = ""
4721 * StringUtils.join([null], *) = ""
4722 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4723 * StringUtils.join([1, 2, 3], null) = "123"
4724 * </pre>
4725 *
4726 * @param array
4727 * the array of values to join together, may be null.
4728 * @param delimiter
4729 * the separator character to use.
4730 * @return The joined String, {@code null} if null array input.
4731 * @since 3.2
4732 */
4733 public static String join(final short[] array, final char delimiter) {
4734 if (array == null) {
4735 return null;
4736 }
4737 return join(array, delimiter, 0, array.length);
4738 }
4739
4740 /**
4741 * Joins the elements of the provided array into a single String containing the provided list of elements.
4742 *
4743 * <p>
4744 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4745 * by empty strings.
4746 * </p>
4747 *
4748 * <pre>
4749 * StringUtils.join(null, *) = null
4750 * StringUtils.join([], *) = ""
4751 * StringUtils.join([null], *) = ""
4752 * StringUtils.join([1, 2, 3], ';') = "1;2;3"
4753 * StringUtils.join([1, 2, 3], null) = "123"
4754 * </pre>
4755 *
4756 * @param array
4757 * the array of values to join together, may be null.
4758 * @param delimiter
4759 * the separator character to use.
4760 * @param startIndex
4761 * the first index to start joining from. It is an error to pass in a start index past the end of the
4762 * array.
4763 * @param endIndex
4764 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4765 * the array.
4766 * @return The joined String, {@code null} if null array input.
4767 * @since 3.2
4768 */
4769 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
4770 // See StringUtilsJoinBenchmark
4771 if (array == null) {
4772 return null;
4773 }
4774 checkFromToIndex(startIndex, endIndex, array.length);
4775 final int count = endIndex - startIndex;
4776 if (count <= 0) {
4777 return EMPTY;
4778 }
4779 final byte maxElementChars = 6; // "-32768"
4780 final StringBuilder stringBuilder = capacity(count, maxElementChars);
4781 stringBuilder.append(array[startIndex]);
4782 for (int i = startIndex + 1; i < endIndex; i++) {
4783 stringBuilder.append(delimiter).append(array[i]);
4784 }
4785 return stringBuilder.toString();
4786 }
4787
4788 /**
4789 * Joins the elements of the provided array into a single String containing the provided list of elements.
4790 *
4791 * <p>
4792 * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings.
4793 * </p>
4794 *
4795 * <pre>
4796 * StringUtils.join(null) = null
4797 * StringUtils.join([]) = ""
4798 * StringUtils.join([null]) = ""
4799 * StringUtils.join("a", "b", "c") = "abc"
4800 * StringUtils.join(null, "", "a") = "a"
4801 * </pre>
4802 *
4803 * @param <T> the specific type of values to join together.
4804 * @param elements The values to join together, may be null.
4805 * @return The joined String, {@code null} if null array input.
4806 * @since 2.0
4807 * @since 3.0 Changed signature to use varargs
4808 */
4809 @SafeVarargs
4810 public static <T> String join(final T... elements) {
4811 return join(elements, null);
4812 }
4813
4814 /**
4815 * Joins the elements of the provided varargs into a single String containing the provided elements.
4816 *
4817 * <p>
4818 * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings ("").
4819 * </p>
4820 *
4821 * <pre>
4822 * StringUtils.joinWith(",", "a", "b") = "a,b"
4823 * StringUtils.joinWith(",", "a", "b","") = "a,b,"
4824 * StringUtils.joinWith(",", "a", null, "b") = "a,,b"
4825 * StringUtils.joinWith(null, "a", "b") = "ab"
4826 * </pre>
4827 *
4828 * @param delimiter The separator character to use, null treated as "".
4829 * @param array The varargs providing the values to join together. {@code null} elements are treated as "".
4830 * @return The joined String.
4831 * @throws IllegalArgumentException Thrown if a null varargs is provided.
4832 * @since 3.5
4833 */
4834 public static String joinWith(final String delimiter, final Object... array) {
4835 if (array == null) {
4836 throw new IllegalArgumentException("Object varargs must not be null");
4837 }
4838 return join(array, delimiter);
4839 }
4840
4841 /**
4842 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible.
4843 *
4844 * <p>
4845 * A {@code null} CharSequence will return {@code -1}.
4846 * </p>
4847 *
4848 * <pre>
4849 * StringUtils.lastIndexOf(null, *) = -1
4850 * StringUtils.lastIndexOf(*, null) = -1
4851 * StringUtils.lastIndexOf("", "") = 0
4852 * StringUtils.lastIndexOf("aabaabaa", "a") = 7
4853 * StringUtils.lastIndexOf("aabaabaa", "b") = 5
4854 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
4855 * StringUtils.lastIndexOf("aabaabaa", "") = 8
4856 * </pre>
4857 *
4858 * @param seq The CharSequence to check, may be null.
4859 * @param searchSeq The CharSequence to find, may be null.
4860 * @return The last index of the search String, -1 if no match or {@code null} string input.
4861 * @since 2.0
4862 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
4863 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}.
4864 */
4865 @Deprecated
4866 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
4867 return Strings.CS.lastIndexOf(seq, searchSeq);
4868 }
4869
4870 /**
4871 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible.
4872 *
4873 * <p>
4874 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
4875 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works
4876 * backwards; matches starting after the start position are ignored.
4877 * </p>
4878 *
4879 * <pre>
4880 * StringUtils.lastIndexOf(null, *, *) = -1
4881 * StringUtils.lastIndexOf(*, null, *) = -1
4882 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7
4883 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5
4884 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
4885 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5
4886 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
4887 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
4888 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
4889 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1
4890 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2
4891 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2
4892 * </pre>
4893 *
4894 * @param seq The CharSequence to check, may be null.
4895 * @param searchSeq The CharSequence to find, may be null.
4896 * @param startPos The start position, negative treated as zero.
4897 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} string input.
4898 * @since 2.0
4899 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
4900 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}.
4901 */
4902 @Deprecated
4903 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
4904 return Strings.CS.lastIndexOf(seq, searchSeq, startPos);
4905 }
4906
4907 /**
4908 * Returns the index within {@code seq} of the last occurrence of the specified character. For values of {@code searchChar} in the range from 0 to 0xFFFF
4909 * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that:
4910 *
4911 * <pre>
4912 * this.charAt(<em>k</em>) == searchChar
4913 * </pre>
4914 *
4915 * <p>
4916 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that:
4917 * </p>
4918 *
4919 * <pre>
4920 * this.codePointAt(<em>k</em>) == searchChar
4921 * </pre>
4922 *
4923 * <p>
4924 * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
4925 * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character.
4926 * </p>
4927 *
4928 * <pre>
4929 * StringUtils.lastIndexOf(null, *) = -1
4930 * StringUtils.lastIndexOf("", *) = -1
4931 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
4932 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
4933 * </pre>
4934 *
4935 * @param seq The {@link CharSequence} to check, may be null.
4936 * @param searchChar The character to find.
4937 * @return The last index of the search character, -1 if no match or {@code null} string input.
4938 * @since 2.0
4939 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
4940 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
4941 */
4942 public static int lastIndexOf(final CharSequence seq, final int searchChar) {
4943 if (isEmpty(seq)) {
4944 return INDEX_NOT_FOUND;
4945 }
4946 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
4947 }
4948
4949 /**
4950 * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of
4951 * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that:
4952 *
4953 * <pre>
4954 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos)
4955 * </pre>
4956 *
4957 * <p>
4958 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that:
4959 * </p>
4960 *
4961 * <pre>
4962 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos)
4963 * </pre>
4964 *
4965 * <p>
4966 * is true. In either case, if no such character occurs in {@code seq} at or before position {@code startPos}, then {@code -1} is returned. Furthermore, a
4967 * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The
4968 * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored.
4969 * </p>
4970 *
4971 * <p>
4972 * All indices are specified in {@code char} values (Unicode code units).
4973 * </p>
4974 *
4975 * <pre>
4976 * StringUtils.lastIndexOf(null, *, *) = -1
4977 * StringUtils.lastIndexOf("", *, *) = -1
4978 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5
4979 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2
4980 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1
4981 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5
4982 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
4983 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
4984 * </pre>
4985 *
4986 * @param seq The CharSequence to check, may be null.
4987 * @param searchChar The character to find.
4988 * @param startPos The start position.
4989 * @return The last index of the search character (always ≤ startPos), -1 if no match or {@code null} string input.
4990 * @since 2.0
4991 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
4992 */
4993 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
4994 if (isEmpty(seq)) {
4995 return INDEX_NOT_FOUND;
4996 }
4997 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
4998 }
4999
5000 /**
5001 * Finds the latest index of any substring in a set of potential substrings.
5002 *
5003 * <p>
5004 * A {@code null} CharSequence will return {@code -1}. A {@code null} search array will return {@code -1}. A {@code null} or zero length search array entry
5005 * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses
5006 * {@link String#indexOf(String)} if possible
5007 * </p>
5008 *
5009 * <pre>
5010 * StringUtils.lastIndexOfAny(null, *) = -1
5011 * StringUtils.lastIndexOfAny(*, null) = -1
5012 * StringUtils.lastIndexOfAny(*, []) = -1
5013 * StringUtils.lastIndexOfAny(*, [null]) = -1
5014 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
5015 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
5016 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
5017 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
5018 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10
5019 * </pre>
5020 *
5021 * @param str The CharSequence to check, may be null.
5022 * @param searchStrs The CharSequences to search for, may be null.
5023 * @return The last index of any of the CharSequences, -1 if no match.
5024 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
5025 */
5026 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
5027 if (str == null || searchStrs == null) {
5028 return INDEX_NOT_FOUND;
5029 }
5030 int ret = INDEX_NOT_FOUND;
5031 int tmp;
5032 for (final CharSequence search : searchStrs) {
5033 if (search == null) {
5034 continue;
5035 }
5036 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
5037 if (tmp > ret) {
5038 ret = tmp;
5039 }
5040 }
5041 return ret;
5042 }
5043
5044 /**
5045 * Case insensitive find of the last index within a CharSequence.
5046 *
5047 * <p>
5048 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
5049 * the start position is negative. A start position greater than the string length searches the whole string.
5050 * </p>
5051 *
5052 * <pre>
5053 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1
5054 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1
5055 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7
5056 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5
5057 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
5058 * </pre>
5059 *
5060 * @param str The CharSequence to check, may be null.
5061 * @param searchStr The CharSequence to find, may be null.
5062 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input.
5063 * @since 2.5
5064 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
5065 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}.
5066 */
5067 @Deprecated
5068 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
5069 return Strings.CI.lastIndexOf(str, searchStr);
5070 }
5071
5072 /**
5073 * Case insensitive find of the last index within a CharSequence from the specified position.
5074 *
5075 * <p>
5076 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
5077 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works
5078 * backwards; matches starting after the start position are ignored.
5079 * </p>
5080 *
5081 * <pre>
5082 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1
5083 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1
5084 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7
5085 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5
5086 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
5087 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5
5088 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
5089 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0
5090 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1
5091 * </pre>
5092 *
5093 * @param str The CharSequence to check, may be null.
5094 * @param searchStr The CharSequence to find, may be null.
5095 * @param startPos The start position.
5096 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} input.
5097 * @since 2.5
5098 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
5099 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}.
5100 */
5101 @Deprecated
5102 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
5103 return Strings.CI.lastIndexOf(str, searchStr, startPos);
5104 }
5105
5106 /**
5107 * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}.
5108 *
5109 * <p>
5110 * A {@code null} String will return {@code -1}.
5111 * </p>
5112 *
5113 * <pre>
5114 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1
5115 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1
5116 * StringUtils.lastOrdinalIndexOf("", "", *) = 0
5117 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7
5118 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6
5119 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5
5120 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2
5121 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
5122 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
5123 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8
5124 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8
5125 * </pre>
5126 *
5127 * <p>
5128 * Note that 'tail(CharSequence str, int n)' may be implemented as:
5129 * </p>
5130 *
5131 * <pre>
5132 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
5133 * </pre>
5134 *
5135 * @param str The CharSequence to check, may be null.
5136 * @param searchStr The CharSequence to find, may be null.
5137 * @param ordinal The n-th last {@code searchStr} to find.
5138 * @return The n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5139 * @since 2.5
5140 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
5141 */
5142 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
5143 return ordinalIndexOf(str, searchStr, ordinal, true);
5144 }
5145
5146 /**
5147 * Gets the leftmost {@code len} characters of a String.
5148 *
5149 * <p>
5150 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is returned
5151 * if len is negative.
5152 * </p>
5153 *
5154 * <pre>
5155 * StringUtils.left(null, *) = null
5156 * StringUtils.left(*, -ve) = ""
5157 * StringUtils.left("", *) = ""
5158 * StringUtils.left("abc", 0) = ""
5159 * StringUtils.left("abc", 2) = "ab"
5160 * StringUtils.left("abc", 4) = "abc"
5161 * </pre>
5162 *
5163 * @param str The String to get the leftmost characters from, may be null.
5164 * @param len The length of the required String.
5165 * @return The leftmost characters, {@code null} if null String input.
5166 */
5167 public static String left(final String str, final int len) {
5168 if (str == null) {
5169 return null;
5170 }
5171 if (len < 0) {
5172 return EMPTY;
5173 }
5174 if (str.length() <= len) {
5175 return str;
5176 }
5177 int cut = len;
5178 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate
5179 if (splitsSurrogatePair(str, cut)) {
5180 cut--;
5181 }
5182 return str.substring(0, cut);
5183 }
5184
5185 /**
5186 * Left pad a String with spaces (' ').
5187 *
5188 * <p>
5189 * The String is padded to the size of {@code size}.
5190 * </p>
5191 *
5192 * <pre>
5193 * StringUtils.leftPad(null, *) = null
5194 * StringUtils.leftPad("", 3) = " "
5195 * StringUtils.leftPad("bat", 3) = "bat"
5196 * StringUtils.leftPad("bat", 5) = " bat"
5197 * StringUtils.leftPad("bat", 1) = "bat"
5198 * StringUtils.leftPad("bat", -1) = "bat"
5199 * </pre>
5200 *
5201 * @param str The String to pad out, may be null.
5202 * @param size The size to pad to.
5203 * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5204 */
5205 public static String leftPad(final String str, final int size) {
5206 return leftPad(str, size, ' ');
5207 }
5208
5209 /**
5210 * Left pad a String with a specified character.
5211 *
5212 * <p>
5213 * Pad to a size of {@code size}.
5214 * </p>
5215 *
5216 * <pre>
5217 * StringUtils.leftPad(null, *, *) = null
5218 * StringUtils.leftPad("", 3, 'z') = "zzz"
5219 * StringUtils.leftPad("bat", 3, 'z') = "bat"
5220 * StringUtils.leftPad("bat", 5, 'z') = "zzbat"
5221 * StringUtils.leftPad("bat", 1, 'z') = "bat"
5222 * StringUtils.leftPad("bat", -1, 'z') = "bat"
5223 * </pre>
5224 *
5225 * @param str The String to pad out, may be null.
5226 * @param size The size to pad to.
5227 * @param padChar The character to pad with.
5228 * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5229 * @since 2.0
5230 */
5231 public static String leftPad(final String str, final int size, final char padChar) {
5232 if (str == null || size <= str.length()) {
5233 return str;
5234 }
5235 final int pads = size - str.length();
5236 if (pads <= 0) {
5237 return str; // returns original String when possible
5238 }
5239 if (pads > PAD_LIMIT) {
5240 return leftPad(str, size, String.valueOf(padChar));
5241 }
5242 return repeat(padChar, pads).concat(str);
5243 }
5244
5245 /**
5246 * Left pad a String with a specified String.
5247 *
5248 * <p>
5249 * Pad to a size of {@code size}.
5250 * </p>
5251 *
5252 * <pre>
5253 * StringUtils.leftPad(null, *, *) = null
5254 * StringUtils.leftPad("", 3, "z") = "zzz"
5255 * StringUtils.leftPad("bat", 3, "yz") = "bat"
5256 * StringUtils.leftPad("bat", 5, "yz") = "yzbat"
5257 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat"
5258 * StringUtils.leftPad("bat", 1, "yz") = "bat"
5259 * StringUtils.leftPad("bat", -1, "yz") = "bat"
5260 * StringUtils.leftPad("bat", 5, null) = " bat"
5261 * StringUtils.leftPad("bat", 5, "") = " bat"
5262 * </pre>
5263 *
5264 * @param str The String to pad out, may be null.
5265 * @param size The size to pad to.
5266 * @param padStr The String to pad with, null or empty treated as single space.
5267 * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5268 */
5269 public static String leftPad(final String str, final int size, String padStr) {
5270 if (str == null || size <= str.length()) {
5271 return str;
5272 }
5273 if (isEmpty(padStr)) {
5274 padStr = SPACE;
5275 }
5276 final int padLen = padStr.length();
5277 final int strLen = str.length();
5278 final int pads = size - strLen;
5279 if (pads <= 0) {
5280 return str; // returns original String when possible
5281 }
5282 if (padLen == 1 && pads <= PAD_LIMIT) {
5283 return leftPad(str, size, padStr.charAt(0));
5284 }
5285 if (pads == padLen) {
5286 return padStr.concat(str);
5287 }
5288 if (pads < padLen) {
5289 return padStr.substring(0, pads).concat(str);
5290 }
5291 final char[] padding = new char[pads];
5292 final char[] padChars = padStr.toCharArray();
5293 for (int i = 0; i < pads; i++) {
5294 padding[i] = padChars[i % padLen];
5295 }
5296 return new String(padding).concat(str);
5297 }
5298
5299 /**
5300 * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}.
5301 *
5302 * @param cs A CharSequence or {@code null}.
5303 * @return CharSequence length or {@code 0} if the CharSequence is {@code null}.
5304 * @since 2.4
5305 * @since 3.0 Changed signature from length(String) to length(CharSequence)
5306 */
5307 public static int length(final CharSequence cs) {
5308 return cs == null ? 0 : cs.length();
5309 }
5310
5311 /**
5312 * Converts a String to lower case as per {@link String#toLowerCase()}.
5313 *
5314 * <p>
5315 * A {@code null} input String returns {@code null}.
5316 * </p>
5317 *
5318 * <pre>
5319 * StringUtils.lowerCase(null) = null
5320 * StringUtils.lowerCase("") = ""
5321 * StringUtils.lowerCase("aBc") = "abc"
5322 * </pre>
5323 *
5324 * <p>
5325 * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale.
5326 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g.
5327 * {@link Locale#ENGLISH}).
5328 * </p>
5329 *
5330 * @param str The String to lower case, may be null.
5331 * @return The lower cased String, {@code null} if null String input.
5332 */
5333 public static String lowerCase(final String str) {
5334 if (str == null) {
5335 return null;
5336 }
5337 return str.toLowerCase();
5338 }
5339
5340 /**
5341 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
5342 *
5343 * <p>
5344 * A {@code null} input String returns {@code null}.
5345 * </p>
5346 *
5347 * <pre>
5348 * StringUtils.lowerCase(null, Locale.ENGLISH) = null
5349 * StringUtils.lowerCase("", Locale.ENGLISH) = ""
5350 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
5351 * </pre>
5352 *
5353 * @param str The String to lower case, may be null.
5354 * @param locale The locale that defines the case transformation rules, must not be null.
5355 * @return The lower cased String, {@code null} if null String input.
5356 * @since 2.5
5357 */
5358 public static String lowerCase(final String str, final Locale locale) {
5359 if (str == null) {
5360 return null;
5361 }
5362 return str.toLowerCase(LocaleUtils.toLocale(locale));
5363 }
5364
5365 private static int[] matches(final CharSequence first, final CharSequence second) {
5366 final CharSequence max;
5367 final CharSequence min;
5368 if (first.length() > second.length()) {
5369 max = first;
5370 min = second;
5371 } else {
5372 max = second;
5373 min = first;
5374 }
5375 final int range = Math.max(max.length() / 2 - 1, 0);
5376 final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1);
5377 final boolean[] matchFlags = new boolean[max.length()];
5378 int matches = 0;
5379 for (int mi = 0; mi < min.length(); mi++) {
5380 final char c1 = min.charAt(mi);
5381 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
5382 if (!matchFlags[xi] && c1 == max.charAt(xi)) {
5383 matchIndexes[mi] = xi;
5384 matchFlags[xi] = true;
5385 matches++;
5386 break;
5387 }
5388 }
5389 }
5390 final char[] ms1 = new char[matches];
5391 final char[] ms2 = new char[matches];
5392 for (int i = 0, si = 0; i < min.length(); i++) {
5393 if (matchIndexes[i] != -1) {
5394 ms1[si] = min.charAt(i);
5395 si++;
5396 }
5397 }
5398 for (int i = 0, si = 0; i < max.length(); i++) {
5399 if (matchFlags[i]) {
5400 ms2[si] = max.charAt(i);
5401 si++;
5402 }
5403 }
5404 int transpositions = 0;
5405 for (int mi = 0; mi < ms1.length; mi++) {
5406 if (ms1[mi] != ms2[mi]) {
5407 transpositions++;
5408 }
5409 }
5410 int prefix = 0;
5411 for (int mi = 0; mi < min.length(); mi++) {
5412 if (first.charAt(mi) != second.charAt(mi)) {
5413 break;
5414 }
5415 prefix++;
5416 }
5417 return new int[] { matches, transpositions / 2, prefix, max.length() };
5418 }
5419
5420 /**
5421 * Gets {@code len} characters from the middle of a String.
5422 *
5423 * <p>
5424 * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null},
5425 * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}.
5426 * </p>
5427 *
5428 * <pre>
5429 * StringUtils.mid(null, *, *) = null
5430 * StringUtils.mid(*, *, -ve) = ""
5431 * StringUtils.mid("", 0, *) = ""
5432 * StringUtils.mid("abc", 0, 2) = "ab"
5433 * StringUtils.mid("abc", 0, 4) = "abc"
5434 * StringUtils.mid("abc", 2, 4) = "c"
5435 * StringUtils.mid("abc", 4, 2) = ""
5436 * StringUtils.mid("abc", -2, 2) = "ab"
5437 * </pre>
5438 *
5439 * @param str The String to get the characters from, may be null.
5440 * @param pos The position to start from, negative treated as zero.
5441 * @param len The length of the required String.
5442 * @return The middle characters, {@code null} if null String input.
5443 */
5444 public static String mid(final String str, int pos, final int len) {
5445 if (str == null) {
5446 return null;
5447 }
5448 if (len < 0 || pos > str.length()) {
5449 return EMPTY;
5450 }
5451 if (pos < 0) {
5452 pos = 0;
5453 }
5454 int start = pos;
5455 // keep the start off the middle of a surrogate pair so the result is never left holding a lone surrogate
5456 if (splitsSurrogatePair(str, start)) {
5457 start++;
5458 }
5459 if (str.length() - pos <= len) {
5460 return str.substring(start);
5461 }
5462 int end = pos + len;
5463 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate
5464 if (splitsSurrogatePair(str, end)) {
5465 end--;
5466 }
5467 return str.substring(start, Math.max(start, end));
5468 }
5469
5470 /**
5471 * Similar to <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize -space</a>
5472 *
5473 * <p>
5474 * This function returns the argument string with whitespace normalized by using {@code {@link #trim(String)}} to remove leading and trailing whitespace and
5475 * then replacing sequences of whitespace characters by a single space.
5476 * </p>
5477 * In XML, whitespace characters are the same as those allowed by the <a href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 |
5478 * #x9 | #xD | #xA)+
5479 * <p>
5480 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
5481 * </p>
5482 * <p>
5483 * For reference:
5484 * </p>
5485 * <ul>
5486 * <li>\x0B = vertical tab</li>
5487 * <li>\f = #xC = form feed</li>
5488 * <li>#x20 = space</li>
5489 * <li>#x9 = \t</li>
5490 * <li>#xA = \n</li>
5491 * <li>#xD = \r</li>
5492 * </ul>
5493 *
5494 * <p>
5495 * The difference is that Java's whitespace includes vertical tab and form feed, which this function will also normalize. Additionally {@code {@link
5496 * #trim(String)}} removes control characters (char <= 32) from both ends of this String.
5497 * </p>
5498 *
5499 * @param str The source String to normalize whitespaces from, may be null.
5500 * @return The modified string with whitespace normalized, {@code null} if null String input.
5501 * @see Pattern
5502 * @see #trim(String)
5503 * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a>
5504 * @since 3.0
5505 */
5506 public static String normalizeSpace(final String str) {
5507 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
5508 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
5509 if (isEmpty(str)) {
5510 return str;
5511 }
5512 final int size = str.length();
5513 final char[] newChars = new char[size];
5514 int count = 0;
5515 int whitespacesCount = 0;
5516 boolean startWhitespaces = true;
5517 for (int i = 0; i < size; i++) {
5518 final char actualChar = str.charAt(i);
5519 final boolean isWhitespace = Character.isWhitespace(actualChar);
5520 if (isWhitespace) {
5521 if (whitespacesCount == 0 && !startWhitespaces) {
5522 newChars[count++] = SPACE.charAt(0);
5523 }
5524 whitespacesCount++;
5525 } else {
5526 startWhitespaces = false;
5527 newChars[count++] = actualChar == 160 ? 32 : actualChar;
5528 whitespacesCount = 0;
5529 }
5530 }
5531 if (startWhitespaces) {
5532 return EMPTY;
5533 }
5534 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
5535 }
5536
5537 /**
5538 * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible.
5539 * <p>
5540 * <strong>Note:</strong> The code starts looking for a match at the start of the target, incrementing the starting index by one after each successful match
5541 * (unless {@code searchStr} is an empty string, in which case the position is never incremented and {@code 0} is returned immediately). This means that
5542 * matches may overlap.
5543 * </p>
5544 * <p>
5545 * A {@code null} CharSequence will return {@code -1}.
5546 * </p>
5547 *
5548 * <pre>
5549 * StringUtils.ordinalIndexOf(null, *, *) = -1
5550 * StringUtils.ordinalIndexOf(*, null, *) = -1
5551 * StringUtils.ordinalIndexOf("", "", *) = 0
5552 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
5553 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
5554 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
5555 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
5556 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
5557 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
5558 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
5559 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
5560 * </pre>
5561 *
5562 * <p>
5563 * Matches may overlap:
5564 * </p>
5565 *
5566 * <pre>
5567 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0
5568 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2
5569 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1
5570 *
5571 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
5572 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
5573 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
5574 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
5575 * </pre>
5576 *
5577 * <p>
5578 * Note that 'head(CharSequence str, int n)' may be implemented as:
5579 * </p>
5580 *
5581 * <pre>
5582 * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
5583 * </pre>
5584 *
5585 * @param str The CharSequence to check, may be null.
5586 * @param searchStr The CharSequence to find, may be null.
5587 * @param ordinal The n-th {@code searchStr} to find.
5588 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5589 * @since 2.1
5590 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
5591 */
5592 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
5593 return ordinalIndexOf(str, searchStr, ordinal, false);
5594 }
5595
5596 /**
5597 * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible.
5598 * <p>
5599 * Note that matches may overlap.
5600 * <p>
5601 *
5602 * <p>
5603 * A {@code null} CharSequence will return {@code -1}.
5604 * </p>
5605 *
5606 * @param str The CharSequence to check, may be null.
5607 * @param searchStr The CharSequence to find, may be null.
5608 * @param ordinal The n-th {@code searchStr} to find, overlapping matches are allowed.
5609 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf().
5610 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5611 */
5612 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
5613 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
5614 if (str == null || searchStr == null || ordinal <= 0) {
5615 return INDEX_NOT_FOUND;
5616 }
5617 if (isEmpty(searchStr)) {
5618 return lastIndex ? str.length() : 0;
5619 }
5620 int found = 0;
5621 // set the initial index beyond the end of the string
5622 // this is to allow for the initial index decrement/increment
5623 int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
5624 do {
5625 if (lastIndex) {
5626 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string
5627 } else {
5628 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
5629 }
5630 if (index < 0) {
5631 return index;
5632 }
5633 found++;
5634 } while (found < ordinal);
5635 return index;
5636 }
5637
5638 /**
5639 * Overlays part of a String with another String.
5640 *
5641 * <p>
5642 * A {@code null} string input returns {@code null}. A negative index is treated as zero. An index greater than the string length is treated as the string
5643 * length. The start index is always the smaller of the two indices.
5644 * </p>
5645 *
5646 * <pre>
5647 * StringUtils.overlay(null, *, *, *) = null
5648 * StringUtils.overlay("", "abc", 0, 0) = "abc"
5649 * StringUtils.overlay("abcdef", null, 2, 4) = "abef"
5650 * StringUtils.overlay("abcdef", "", 2, 4) = "abef"
5651 * StringUtils.overlay("abcdef", "", 4, 2) = "abef"
5652 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef"
5653 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef"
5654 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef"
5655 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz"
5656 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
5657 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz"
5658 * </pre>
5659 *
5660 * @param str The String to do overlaying in, may be null.
5661 * @param overlay The String to overlay, may be null.
5662 * @param start The position to start overlaying at.
5663 * @param end The position to stop overlaying before.
5664 * @return overlaid String, {@code null} if null String input.
5665 * @since 2.0
5666 */
5667 public static String overlay(final String str, String overlay, int start, int end) {
5668 if (str == null) {
5669 return null;
5670 }
5671 if (overlay == null) {
5672 overlay = EMPTY;
5673 }
5674 final int len = str.length();
5675 if (start < 0) {
5676 start = 0;
5677 }
5678 if (start > len) {
5679 start = len;
5680 }
5681 if (end < 0) {
5682 end = 0;
5683 }
5684 if (end > len) {
5685 end = len;
5686 }
5687 if (start > end) {
5688 final int temp = start;
5689 start = end;
5690 end = temp;
5691 }
5692 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate
5693 if (splitsSurrogatePair(str, start)) {
5694 start--;
5695 }
5696 if (splitsSurrogatePair(str, end)) {
5697 end++;
5698 }
5699 return str.substring(0, start) + overlay + str.substring(end);
5700 }
5701
5702 /**
5703 * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes.
5704 *
5705 * <pre>
5706 * StringUtils.prependIfMissing(null, null) = null
5707 * StringUtils.prependIfMissing("abc", null) = "abc"
5708 * StringUtils.prependIfMissing("", "xyz") = "xyz"
5709 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
5710 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
5711 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
5712 * </pre>
5713 * <p>
5714 * With additional prefixes,
5715 * </p>
5716 *
5717 * <pre>
5718 * StringUtils.prependIfMissing(null, null, null) = null
5719 * StringUtils.prependIfMissing("abc", null, null) = "abc"
5720 * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
5721 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
5722 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
5723 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
5724 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
5725 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
5726 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
5727 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
5728 * </pre>
5729 *
5730 * @param str The string.
5731 * @param prefix The prefix to prepend to the start of the string.
5732 * @param prefixes Additional prefixes that are valid.
5733 * @return A new String if prefix was prepended, the same string otherwise.
5734 * @since 3.2
5735 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence,
5736 * CharSequence...)}.
5737 */
5738 @Deprecated
5739 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
5740 return Strings.CS.prependIfMissing(str, prefix, prefixes);
5741 }
5742
5743 /**
5744 * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes.
5745 *
5746 * <pre>
5747 * StringUtils.prependIfMissingIgnoreCase(null, null) = null
5748 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
5749 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
5750 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
5751 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
5752 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
5753 * </pre>
5754 * <p>
5755 * With additional prefixes,
5756 * </p>
5757 *
5758 * <pre>
5759 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
5760 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
5761 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
5762 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
5763 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
5764 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
5765 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
5766 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
5767 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
5768 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
5769 * </pre>
5770 *
5771 * @param str The string.
5772 * @param prefix The prefix to prepend to the start of the string.
5773 * @param prefixes Additional prefixes that are valid (optional).
5774 * @return A new String if prefix was prepended, the same string otherwise.
5775 * @since 3.2
5776 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence,
5777 * CharSequence...)}.
5778 */
5779 @Deprecated
5780 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
5781 return Strings.CI.prependIfMissing(str, prefix, prefixes);
5782 }
5783
5784 /**
5785 * Removes all occurrences of a character from within the source string.
5786 *
5787 * <p>
5788 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string.
5789 * </p>
5790 *
5791 * <pre>
5792 * StringUtils.remove(null, *) = null
5793 * StringUtils.remove("", *) = ""
5794 * StringUtils.remove("queued", 'u') = "qeed"
5795 * StringUtils.remove("queued", 'z') = "queued"
5796 * </pre>
5797 *
5798 * @param str The source String to search, may be null.
5799 * @param remove The char to search for and remove, may be null.
5800 * @return The substring with the char removed if found, {@code null} if null String input.
5801 * @since 2.1
5802 */
5803 public static String remove(final String str, final char remove) {
5804 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
5805 return str;
5806 }
5807 final char[] chars = str.toCharArray();
5808 int pos = 0;
5809 for (int i = 0; i < chars.length; i++) {
5810 if (chars[i] != remove) {
5811 chars[pos++] = chars[i];
5812 }
5813 }
5814 return new String(chars, 0, pos);
5815 }
5816
5817 /**
5818 * Removes all occurrences of a substring from within the source string.
5819 *
5820 * <p>
5821 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return
5822 * the source string. An empty ("") remove string will return the source string.
5823 * </p>
5824 *
5825 * <pre>
5826 * StringUtils.remove(null, *) = null
5827 * StringUtils.remove("", *) = ""
5828 * StringUtils.remove(*, null) = *
5829 * StringUtils.remove(*, "") = *
5830 * StringUtils.remove("queued", "ue") = "qd"
5831 * StringUtils.remove("queued", "zz") = "queued"
5832 * </pre>
5833 *
5834 * @param str The source String to search, may be null.
5835 * @param remove The String to search for and remove, may be null.
5836 * @return The substring with the string removed if found, {@code null} if null String input.
5837 * @since 2.1
5838 * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}.
5839 */
5840 @Deprecated
5841 public static String remove(final String str, final String remove) {
5842 return Strings.CS.remove(str, remove);
5843 }
5844
5845 /**
5846 * Removes each substring of the text String that matches the given regular expression.
5847 *
5848 * This method is a {@code null} safe equivalent to:
5849 * <ul>
5850 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
5851 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
5852 * </ul>
5853 *
5854 * <p>
5855 * A {@code null} reference passed to this method is a no-op.
5856 * </p>
5857 *
5858 * <p>
5859 * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option
5860 * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl.
5861 * </p>
5862 *
5863 * <pre>{@code
5864 * StringUtils.removeAll(null, *) = null
5865 * StringUtils.removeAll("any", (String) null) = "any"
5866 * StringUtils.removeAll("any", "") = "any"
5867 * StringUtils.removeAll("any", ".*") = ""
5868 * StringUtils.removeAll("any", ".+") = ""
5869 * StringUtils.removeAll("abc", ".?") = ""
5870 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB"
5871 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB"
5872 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123"
5873 * }</pre>
5874 *
5875 * @param text text to remove from, may be null.
5876 * @param regex The regular expression to which this string is to be matched.
5877 * @return The text with any removes processed, {@code null} if null String input.
5878 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid.
5879 * @see #replaceAll(String, String, String)
5880 * @see #removePattern(String, String)
5881 * @see String#replaceAll(String, String)
5882 * @see java.util.regex.Pattern
5883 * @see java.util.regex.Pattern#DOTALL
5884 * @since 3.5
5885 * @deprecated Use {@link RegExUtils#removeAll(String, String)}.
5886 */
5887 @Deprecated
5888 public static String removeAll(final String text, final String regex) {
5889 return RegExUtils.removeAll(text, regex);
5890 }
5891
5892 /**
5893 * Removes a substring only if it is at the end of a source string, otherwise returns the source string.
5894 *
5895 * <p>
5896 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
5897 * the source string.
5898 * </p>
5899 *
5900 * <pre>
5901 * StringUtils.removeEnd(null, *) = null
5902 * StringUtils.removeEnd("", *) = ""
5903 * StringUtils.removeEnd(*, null) = *
5904 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com"
5905 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain"
5906 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
5907 * StringUtils.removeEnd("abc", "") = "abc"
5908 * </pre>
5909 *
5910 * @param str The source String to search, may be null.
5911 * @param remove The String to search for and remove, may be null.
5912 * @return The substring with the string removed if found, {@code null} if null String input.
5913 * @since 2.1
5914 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}.
5915 */
5916 @Deprecated
5917 public static String removeEnd(final String str, final String remove) {
5918 return Strings.CS.removeEnd(str, remove);
5919 }
5920
5921 /**
5922 * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string.
5923 *
5924 * <p>
5925 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
5926 * the source string.
5927 * </p>
5928 *
5929 * <pre>
5930 * StringUtils.removeEndIgnoreCase(null, *) = null
5931 * StringUtils.removeEndIgnoreCase("", *) = ""
5932 * StringUtils.removeEndIgnoreCase(*, null) = *
5933 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com"
5934 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain"
5935 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
5936 * StringUtils.removeEndIgnoreCase("abc", "") = "abc"
5937 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain"
5938 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain"
5939 * </pre>
5940 *
5941 * @param str The source String to search, may be null.
5942 * @param remove The String to search for (case-insensitive) and remove, may be null.
5943 * @return The substring with the string removed if found, {@code null} if null String input.
5944 * @since 2.4
5945 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}.
5946 */
5947 @Deprecated
5948 public static String removeEndIgnoreCase(final String str, final String remove) {
5949 return Strings.CI.removeEnd(str, remove);
5950 }
5951
5952 /**
5953 * Removes the first substring of the text string that matches the given regular expression.
5954 *
5955 * This method is a {@code null} safe equivalent to:
5956 * <ul>
5957 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
5958 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
5959 * </ul>
5960 *
5961 * <p>
5962 * A {@code null} reference passed to this method is a no-op.
5963 * </p>
5964 *
5965 * <p>
5966 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as
5967 * single-line mode in Perl.
5968 * </p>
5969 *
5970 * <pre>{@code
5971 * StringUtils.removeFirst(null, *) = null
5972 * StringUtils.removeFirst("any", (String) null) = "any"
5973 * StringUtils.removeFirst("any", "") = "any"
5974 * StringUtils.removeFirst("any", ".*") = ""
5975 * StringUtils.removeFirst("any", ".+") = ""
5976 * StringUtils.removeFirst("abc", ".?") = "bc"
5977 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B"
5978 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB"
5979 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123"
5980 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc"
5981 * }</pre>
5982 *
5983 * @param text text to remove from, may be null.
5984 * @param regex The regular expression to which this string is to be matched.
5985 * @return The text with the first replacement processed, {@code null} if null String input.
5986 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid.
5987 * @see #replaceFirst(String, String, String)
5988 * @see String#replaceFirst(String, String)
5989 * @see java.util.regex.Pattern
5990 * @see java.util.regex.Pattern#DOTALL
5991 * @since 3.5
5992 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String) RegExUtils.replaceFirst(String, String, EMPTY)}.
5993 */
5994 @Deprecated
5995 public static String removeFirst(final String text, final String regex) {
5996 return replaceFirst(text, regex, EMPTY);
5997 }
5998
5999 /**
6000 * Case-insensitive removal of all occurrences of a substring from within the source string.
6001 *
6002 * <p>
6003 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return
6004 * the source string. An empty ("") remove string will return the source string.
6005 * </p>
6006 *
6007 * <pre>
6008 * StringUtils.removeIgnoreCase(null, *) = null
6009 * StringUtils.removeIgnoreCase("", *) = ""
6010 * StringUtils.removeIgnoreCase(*, null) = *
6011 * StringUtils.removeIgnoreCase(*, "") = *
6012 * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
6013 * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
6014 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
6015 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
6016 * </pre>
6017 *
6018 * @param str The source String to search, may be null.
6019 * @param remove The String to search for (case-insensitive) and remove, may be null.
6020 * @return The substring with the string removed if found, {@code null} if null String input.
6021 * @since 3.5
6022 * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}.
6023 */
6024 @Deprecated
6025 public static String removeIgnoreCase(final String str, final String remove) {
6026 return Strings.CI.remove(str, remove);
6027 }
6028
6029 /**
6030 * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
6031 *
6032 * This call is a {@code null} safe equivalent to:
6033 * <ul>
6034 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li>
6035 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
6036 * </ul>
6037 *
6038 * <p>
6039 * A {@code null} reference passed to this method is a no-op.
6040 * </p>
6041 *
6042 * <pre>{@code
6043 * StringUtils.removePattern(null, *) = null
6044 * StringUtils.removePattern("any", (String) null) = "any"
6045 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB"
6046 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123"
6047 * }</pre>
6048 *
6049 * @param source The source string.
6050 * @param regex The regular expression to which this string is to be matched.
6051 * @return The resulting {@link String}.
6052 * @see #replacePattern(String, String, String)
6053 * @see String#replaceAll(String, String)
6054 * @see Pattern#DOTALL
6055 * @since 3.2
6056 * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
6057 * @deprecated Use {@link RegExUtils#removePattern(CharSequence, String)}.
6058 */
6059 @Deprecated
6060 public static String removePattern(final String source, final String regex) {
6061 return RegExUtils.removePattern(source, regex);
6062 }
6063
6064 /**
6065 * Removes a char only if it is at the beginning of a source string, otherwise returns the source string.
6066 *
6067 * <p>
6068 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search char will return
6069 * the source string.
6070 * </p>
6071 *
6072 * <pre>
6073 * StringUtils.removeStart(null, *) = null
6074 * StringUtils.removeStart("", *) = ""
6075 * StringUtils.removeStart(*, null) = *
6076 * StringUtils.removeStart("/path", '/') = "path"
6077 * StringUtils.removeStart("path", '/') = "path"
6078 * StringUtils.removeStart("path", 0) = "path"
6079 * </pre>
6080 *
6081 * @param str The source String to search, may be null.
6082 * @param remove The char to search for and remove.
6083 * @return The substring with the char removed if found, {@code null} if null String input.
6084 * @since 3.13.0
6085 */
6086 public static String removeStart(final String str, final char remove) {
6087 if (isEmpty(str)) {
6088 return str;
6089 }
6090 return str.charAt(0) == remove ? str.substring(1) : str;
6091 }
6092
6093 /**
6094 * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string.
6095 *
6096 * <p>
6097 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
6098 * the source string.
6099 * </p>
6100 *
6101 * <pre>
6102 * StringUtils.removeStart(null, *) = null
6103 * StringUtils.removeStart("", *) = ""
6104 * StringUtils.removeStart(*, null) = *
6105 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com"
6106 * StringUtils.removeStart("domain.com", "www.") = "domain.com"
6107 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
6108 * StringUtils.removeStart("abc", "") = "abc"
6109 * </pre>
6110 *
6111 * @param str The source String to search, may be null.
6112 * @param remove The String to search for and remove, may be null.
6113 * @return The substring with the string removed if found, {@code null} if null String input.
6114 * @since 2.1
6115 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}.
6116 */
6117 @Deprecated
6118 public static String removeStart(final String str, final String remove) {
6119 return Strings.CS.removeStart(str, remove);
6120 }
6121
6122 /**
6123 * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string.
6124 *
6125 * <p>
6126 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
6127 * the source string.
6128 * </p>
6129 *
6130 * <pre>
6131 * StringUtils.removeStartIgnoreCase(null, *) = null
6132 * StringUtils.removeStartIgnoreCase("", *) = ""
6133 * StringUtils.removeStartIgnoreCase(*, null) = *
6134 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com"
6135 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com"
6136 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com"
6137 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
6138 * StringUtils.removeStartIgnoreCase("abc", "") = "abc"
6139 * </pre>
6140 *
6141 * @param str The source String to search, may be null.
6142 * @param remove The String to search for (case-insensitive) and remove, may be null.
6143 * @return The substring with the string removed if found, {@code null} if null String input.
6144 * @since 2.4
6145 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}.
6146 */
6147 @Deprecated
6148 public static String removeStartIgnoreCase(final String str, final String remove) {
6149 return Strings.CI.removeStart(str, remove);
6150 }
6151
6152 /**
6153 * Returns padding using the specified delimiter repeated to a given length.
6154 *
6155 * <pre>
6156 * StringUtils.repeat('e', 0) = ""
6157 * StringUtils.repeat('e', 3) = "eee"
6158 * StringUtils.repeat('e', -2) = ""
6159 * </pre>
6160 *
6161 * <p>
6162 * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
6163 * as they require a pair of {@code char}s to be represented. If you are needing to support full I18N of your applications consider using
6164 * {@link #repeat(String, int)} instead.
6165 * </p>
6166 *
6167 * @param repeat character to repeat.
6168 * @param count number of times to repeat char, negative treated as zero.
6169 * @return String with repeated character.
6170 * @see #repeat(String, int)
6171 */
6172 public static String repeat(final char repeat, final int count) {
6173 if (count <= 0) {
6174 return EMPTY;
6175 }
6176 return new String(ArrayFill.fill(new char[count], repeat));
6177 }
6178
6179 /**
6180 * Repeats a String {@code repeat} times to form a new String.
6181 *
6182 * <pre>
6183 * StringUtils.repeat(null, 2) = null
6184 * StringUtils.repeat("", 0) = ""
6185 * StringUtils.repeat("", 2) = ""
6186 * StringUtils.repeat("a", 3) = "aaa"
6187 * StringUtils.repeat("ab", 2) = "abab"
6188 * StringUtils.repeat("a", -2) = ""
6189 * </pre>
6190 *
6191 * @param repeat The String to repeat, may be null.
6192 * @param count number of times to repeat str, negative treated as zero.
6193 * @return A new String consisting of the original String repeated, {@code null} if null String input.
6194 */
6195 public static String repeat(final String repeat, final int count) {
6196 // Performance tuned for 2.0 (JDK1.4)
6197 if (repeat == null) {
6198 return null;
6199 }
6200 if (count <= 0) {
6201 return EMPTY;
6202 }
6203 final int inputLength = repeat.length();
6204 if (count == 1 || inputLength == 0) {
6205 return repeat;
6206 }
6207 if (inputLength == 1 && count <= PAD_LIMIT) {
6208 return repeat(repeat.charAt(0), count);
6209 }
6210 final int outputLength;
6211 try {
6212 outputLength = Math.multiplyExact(inputLength, count);
6213 } catch (final Exception e) {
6214 throw new IllegalArgumentException("The requested result is too large for a String.");
6215 }
6216 switch (inputLength) {
6217 case 1:
6218 return repeat(repeat.charAt(0), count);
6219 case 2:
6220 final char ch0 = repeat.charAt(0);
6221 final char ch1 = repeat.charAt(1);
6222 final char[] output2 = new char[outputLength];
6223 for (int i = count * 2 - 2; i >= 0; i--, i--) {
6224 output2[i] = ch0;
6225 output2[i + 1] = ch1;
6226 }
6227 return new String(output2);
6228 default:
6229 final StringBuilder buf = new StringBuilder(outputLength);
6230 for (int i = 0; i < count; i++) {
6231 buf.append(repeat);
6232 }
6233 return buf.toString();
6234 }
6235 }
6236
6237 /**
6238 * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time.
6239 *
6240 * <pre>
6241 * StringUtils.repeat(null, null, 2) = null
6242 * StringUtils.repeat(null, "x", 2) = null
6243 * StringUtils.repeat("", null, 0) = ""
6244 * StringUtils.repeat("", "", 2) = ""
6245 * StringUtils.repeat("", "x", 3) = "xx"
6246 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?"
6247 * </pre>
6248 *
6249 * @param repeat The String to repeat, may be null.
6250 * @param separator The String to inject, may be null.
6251 * @param count number of times to repeat str, negative treated as zero.
6252 * @return A new String consisting of the original String repeated, {@code null} if null String input.
6253 * @since 2.5
6254 */
6255 public static String repeat(final String repeat, final String separator, final int count) {
6256 if (repeat == null || separator == null) {
6257 return repeat(repeat, count);
6258 }
6259 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
6260 final String result = repeat(repeat + separator, count);
6261 return Strings.CS.removeEnd(result, separator);
6262 }
6263
6264 /**
6265 * Replaces all occurrences of a String within another String.
6266 *
6267 * <p>
6268 * A {@code null} reference passed to this method is a no-op.
6269 * </p>
6270 *
6271 * <pre>
6272 * StringUtils.replace(null, *, *) = null
6273 * StringUtils.replace("", *, *) = ""
6274 * StringUtils.replace("any", null, *) = "any"
6275 * StringUtils.replace("any", *, null) = "any"
6276 * StringUtils.replace("any", "", *) = "any"
6277 * StringUtils.replace("aba", "a", null) = "aba"
6278 * StringUtils.replace("aba", "a", "") = "b"
6279 * StringUtils.replace("aba", "a", "z") = "zbz"
6280 * </pre>
6281 *
6282 * @param text text to search and replace in, may be null.
6283 * @param searchString The String to search for, may be null.
6284 * @param replacement The String to replace it with, may be null.
6285 * @return The text with any replacements processed, {@code null} if null String input.
6286 * @see #replace(String text, String searchString, String replacement, int max)
6287 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}.
6288 */
6289 @Deprecated
6290 public static String replace(final String text, final String searchString, final String replacement) {
6291 return Strings.CS.replace(text, searchString, replacement);
6292 }
6293
6294 /**
6295 * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String.
6296 *
6297 * <p>
6298 * A {@code null} reference passed to this method is a no-op.
6299 * </p>
6300 *
6301 * <pre>
6302 * StringUtils.replace(null, *, *, *) = null
6303 * StringUtils.replace("", *, *, *) = ""
6304 * StringUtils.replace("any", null, *, *) = "any"
6305 * StringUtils.replace("any", *, null, *) = "any"
6306 * StringUtils.replace("any", "", *, *) = "any"
6307 * StringUtils.replace("any", *, *, 0) = "any"
6308 * StringUtils.replace("abaa", "a", null, -1) = "abaa"
6309 * StringUtils.replace("abaa", "a", "", -1) = "b"
6310 * StringUtils.replace("abaa", "a", "z", 0) = "abaa"
6311 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa"
6312 * StringUtils.replace("abaa", "a", "z", 2) = "zbza"
6313 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz"
6314 * </pre>
6315 *
6316 * @param text text to search and replace in, may be null.
6317 * @param searchString The String to search for, may be null.
6318 * @param replacement The String to replace it with, may be null.
6319 * @param max maximum number of values to replace, or {@code -1} if no maximum.
6320 * @return The text with any replacements processed, {@code null} if null String input.
6321 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}.
6322 */
6323 @Deprecated
6324 public static String replace(final String text, final String searchString, final String replacement, final int max) {
6325 return Strings.CS.replace(text, searchString, replacement, max);
6326 }
6327
6328 /**
6329 * Replaces each substring of the text String that matches the given regular expression with the given replacement.
6330 *
6331 * This method is a {@code null} safe equivalent to:
6332 * <ul>
6333 * <li>{@code text.replaceAll(regex, replacement)}</li>
6334 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
6335 * </ul>
6336 *
6337 * <p>
6338 * A {@code null} reference passed to this method is a no-op.
6339 * </p>
6340 *
6341 * <p>
6342 * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL
6343 * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl.
6344 * </p>
6345 *
6346 * <pre>{@code
6347 * StringUtils.replaceAll(null, *, *) = null
6348 * StringUtils.replaceAll("any", (String) null, *) = "any"
6349 * StringUtils.replaceAll("any", *, null) = "any"
6350 * StringUtils.replaceAll("", "", "zzz") = "zzz"
6351 * StringUtils.replaceAll("", ".*", "zzz") = "zzz"
6352 * StringUtils.replaceAll("", ".+", "zzz") = ""
6353 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ"
6354 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz"
6355 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z"
6356 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123"
6357 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
6358 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
6359 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
6360 * }</pre>
6361 *
6362 * @param text text to search and replace in, may be null.
6363 * @param regex The regular expression to which this string is to be matched.
6364 * @param replacement The string to be substituted for each match.
6365 * @return The text with any replacements processed, {@code null} if null String input.
6366 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid.
6367 * @see #replacePattern(String, String, String)
6368 * @see String#replaceAll(String, String)
6369 * @see java.util.regex.Pattern
6370 * @see java.util.regex.Pattern#DOTALL
6371 * @since 3.5
6372 * @deprecated Use {@link RegExUtils#replaceAll(String, String, String)}.
6373 */
6374 @Deprecated
6375 public static String replaceAll(final String text, final String regex, final String replacement) {
6376 return RegExUtils.replaceAll(text, regex, replacement);
6377 }
6378
6379 /**
6380 * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}.
6381 *
6382 * <p>
6383 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string.
6384 * </p>
6385 *
6386 * <pre>
6387 * StringUtils.replaceChars(null, *, *) = null
6388 * StringUtils.replaceChars("", *, *) = ""
6389 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
6390 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
6391 * </pre>
6392 *
6393 * @param str String to replace characters in, may be null.
6394 * @param searchChar The character to search for, may be null.
6395 * @param replaceChar The character to replace, may be null.
6396 * @return modified String, {@code null} if null string input.
6397 * @since 2.0
6398 */
6399 public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
6400 if (str == null) {
6401 return null;
6402 }
6403 return str.replace(searchChar, replaceChar);
6404 }
6405
6406 /**
6407 * Replaces multiple characters in a String in one go. This method can also be used to delete characters.
6408 *
6409 * <p>
6410 * For example:
6411 * </p>
6412 * <pre>
6413 * replaceChars("hello", "ho", "jy") = jelly.
6414 * </pre>
6415 *
6416 * <p>
6417 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. A null or empty set of search characters returns
6418 * the input string.
6419 * </p>
6420 *
6421 * <p>
6422 * The length of the search characters should normally equal the length of the replace characters. If the search characters is longer, then the extra search
6423 * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored.
6424 * </p>
6425 *
6426 * <pre>
6427 * StringUtils.replaceChars(null, *, *) = null
6428 * StringUtils.replaceChars("", *, *) = ""
6429 * StringUtils.replaceChars("abc", null, *) = "abc"
6430 * StringUtils.replaceChars("abc", "", *) = "abc"
6431 * StringUtils.replaceChars("abc", "b", null) = "ac"
6432 * StringUtils.replaceChars("abc", "b", "") = "ac"
6433 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya"
6434 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
6435 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
6436 * </pre>
6437 *
6438 * @param str String to replace characters in, may be null.
6439 * @param searchChars A set of characters to search for, may be null.
6440 * @param replaceChars A set of characters to replace, may be null.
6441 * @return modified String, {@code null} if null string input.
6442 * @since 2.0
6443 */
6444 public static String replaceChars(final String str, final String searchChars, String replaceChars) {
6445 if (isEmpty(str) || isEmpty(searchChars)) {
6446 return str;
6447 }
6448 replaceChars = ObjectUtils.toString(replaceChars);
6449 boolean modified = false;
6450 final int replaceCharsLength = replaceChars.length();
6451 final int strLength = str.length();
6452 final StringBuilder buf = new StringBuilder(strLength);
6453 for (int i = 0; i < strLength; i++) {
6454 final char ch = str.charAt(i);
6455 final int index = searchChars.indexOf(ch);
6456 if (index >= 0) {
6457 modified = true;
6458 if (index < replaceCharsLength) {
6459 buf.append(replaceChars.charAt(index));
6460 }
6461 } else {
6462 buf.append(ch);
6463 }
6464 }
6465 if (modified) {
6466 return buf.toString();
6467 }
6468 return str;
6469 }
6470
6471 /**
6472 * Replaces all occurrences of Strings within another String.
6473 *
6474 * <p>
6475 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. This
6476 * will not repeat. For repeating replaces, call the overloaded method.
6477 * </p>
6478 *
6479 * <pre>
6480 * StringUtils.replaceEach(null, *, *) = null
6481 * StringUtils.replaceEach("", *, *) = ""
6482 * StringUtils.replaceEach("aba", null, null) = "aba"
6483 * StringUtils.replaceEach("aba", new String[0], null) = "aba"
6484 * StringUtils.replaceEach("aba", null, new String[0]) = "aba"
6485 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba"
6486 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b"
6487 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba"
6488 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
6489 * (example of how it does not repeat)
6490 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
6491 * </pre>
6492 *
6493 * @param text text to search and replace in, no-op if null.
6494 * @param searchList The Strings to search for, no-op if null.
6495 * @param replacementList The Strings to replace them with, no-op if null.
6496 * @return The text with any replacements processed, {@code null} if null String input.
6497 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0).
6498 * @since 2.4
6499 */
6500 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
6501 return replaceEachOnce(text, searchList, replacementList);
6502 }
6503
6504 /**
6505 * Replace all occurrences of Strings within another String, in a single pass. This is a private helper method for
6506 * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])}
6507 *
6508 * <p>
6509 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored.
6510 * </p>
6511 *
6512 * <pre>
6513 * StringUtils.replaceEachOnce(null, *, *) = null
6514 * StringUtils.replaceEachOnce("", *, *) = ""
6515 * StringUtils.replaceEachOnce("aba", null, null) = "aba"
6516 * StringUtils.replaceEachOnce("aba", new String[0], null) = "aba"
6517 * StringUtils.replaceEachOnce("aba", null, new String[0]) = "aba"
6518 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, null) = "aba"
6519 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, new String[]{""}) = "b"
6520 * StringUtils.replaceEachOnce("aba", new String[]{null}, new String[]{"a"}) = "aba"
6521 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
6522 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
6523 * </pre>
6524 *
6525 * <p>
6526 * When no replacement is performed, the {@code text} argument is returned unchanged (same reference); callers rely on this to detect convergence.
6527 * </p>
6528 *
6529 * @param text text to search and replace in, no-op if null.
6530 * @param searchList The Strings to search for, no-op if null.
6531 * @param replacementList The Strings to replace them with, no-op if null.
6532 * @return The text with any replacements processed, {@code null} if null String input.
6533 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0).
6534 * @since 2.4
6535 */
6536 private static String replaceEachOnce(final String text, final String[] searchList, final String[] replacementList) {
6537
6538 // Performance note: This creates very few new objects (one major goal)
6539 // let me know if there are performance requests, we can create a harness to measure
6540 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) {
6541 return text;
6542 }
6543
6544 final int searchLength = searchList.length;
6545 final int replacementLength = replacementList.length;
6546
6547 // make sure lengths are ok, these need to be equal
6548 if (searchLength != replacementLength) {
6549 throw new IllegalArgumentException("Search and Replace array lengths don't match: "
6550 + searchLength
6551 + " vs "
6552 + replacementLength);
6553 }
6554
6555 // keep track of which still have matches
6556 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
6557
6558 // index on index that the match was found
6559 int textIndex = -1;
6560 int replaceIndex = -1;
6561 int tempIndex;
6562
6563 // index of replace array that will replace the search string found
6564 // NOTE: logic duplicated below START
6565 for (int i = 0; i < searchLength; i++) {
6566 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
6567 continue;
6568 }
6569 tempIndex = text.indexOf(searchList[i]);
6570
6571 // see if we need to keep searching for this
6572 if (tempIndex == -1) {
6573 noMoreMatchesForReplIndex[i] = true;
6574 } else if (textIndex == -1 || tempIndex < textIndex) {
6575 textIndex = tempIndex;
6576 replaceIndex = i;
6577 }
6578 }
6579 // NOTE: logic mostly below END
6580
6581 // no search strings found, we are done
6582 if (textIndex == -1) {
6583 return text;
6584 }
6585
6586 int start = 0;
6587
6588 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
6589 int increase = 0;
6590
6591 // count the replacement text elements that are larger than their corresponding text being replaced
6592 for (int i = 0; i < searchList.length; i++) {
6593 if (searchList[i] == null || replacementList[i] == null) {
6594 continue;
6595 }
6596 final int greater = replacementList[i].length() - searchList[i].length();
6597 if (greater > 0) {
6598 increase += 3 * greater; // assume 3 matches
6599 }
6600 }
6601 // have upper-bound at 20% increase, then let Java take over
6602 increase = Math.min(increase, text.length() / 5);
6603
6604 final StringBuilder buf = new StringBuilder(text.length() + increase);
6605
6606 while (textIndex != -1) {
6607
6608 for (int i = start; i < textIndex; i++) {
6609 buf.append(text.charAt(i));
6610 }
6611 buf.append(replacementList[replaceIndex]);
6612
6613 start = textIndex + searchList[replaceIndex].length();
6614
6615 textIndex = -1;
6616 replaceIndex = -1;
6617 // find the next earliest match
6618 // NOTE: logic mostly duplicated above START
6619 for (int i = 0; i < searchLength; i++) {
6620 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
6621 continue;
6622 }
6623 tempIndex = text.indexOf(searchList[i], start);
6624
6625 // see if we need to keep searching for this
6626 if (tempIndex == -1) {
6627 noMoreMatchesForReplIndex[i] = true;
6628 } else if (textIndex == -1 || tempIndex < textIndex) {
6629 textIndex = tempIndex;
6630 replaceIndex = i;
6631 }
6632 }
6633 // NOTE: logic duplicated above END
6634
6635 }
6636 final int textLength = text.length();
6637 for (int i = start; i < textLength; i++) {
6638 buf.append(text.charAt(i));
6639 }
6640 return buf.toString();
6641 }
6642
6643 /**
6644 * Replaces all occurrences of Strings within another String.
6645 *
6646 * <p>
6647 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored.
6648 * </p>
6649 *
6650 * <pre>
6651 * StringUtils.replaceEachRepeatedly(null, *, *) = null
6652 * StringUtils.replaceEachRepeatedly("", *, *) = ""
6653 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
6654 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
6655 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
6656 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
6657 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
6658 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
6659 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
6660 * (example of how it repeats)
6661 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
6662 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = Throws {@link IllegalStateException}
6663 * </pre>
6664 *
6665 * @param text text to search and replace in, no-op if null.
6666 * @param searchList The Strings to search for, no-op if null.
6667 * @param replacementList The Strings to replace them with, no-op if null.
6668 * @return The text with any replacements processed, {@code null} if null String input.
6669 * @throws IllegalStateException Thrown if the search is repeating and there is an endless loop due to outputs of one being inputs to another.
6670 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0).
6671 * @since 2.4
6672 */
6673 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
6674 // The iteration budget is a fixed constant, deliberately independent of the caller-supplied
6675 // searchList length: deriving the budget from the input would let the input size choose the
6676 // recursion depth/amplification (formerly a real StackOverflowError on large search lists).
6677 String result = text;
6678 for (int timeToLive = DEFAULT_TTL; timeToLive >= 0; timeToLive--) {
6679 final String next = replaceEachOnce(result, searchList, replacementList);
6680 if (next == result) {
6681 // No replacement was performed; converged.
6682 return result;
6683 }
6684 result = next;
6685 }
6686 throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
6687 "output of one loop is the input of another");
6688 }
6689
6690 /**
6691 * Replaces the first substring of the text string that matches the given regular expression with the given replacement.
6692 *
6693 * This method is a {@code null} safe equivalent to:
6694 * <ul>
6695 * <li>{@code text.replaceFirst(regex, replacement)}</li>
6696 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
6697 * </ul>
6698 *
6699 * <p>
6700 * A {@code null} reference passed to this method is a no-op.
6701 * </p>
6702 *
6703 * <p>
6704 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as
6705 * single-line mode in Perl.
6706 * </p>
6707 *
6708 * <pre>{@code
6709 * StringUtils.replaceFirst(null, *, *) = null
6710 * StringUtils.replaceFirst("any", (String) null, *) = "any"
6711 * StringUtils.replaceFirst("any", *, null) = "any"
6712 * StringUtils.replaceFirst("", "", "zzz") = "zzz"
6713 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz"
6714 * StringUtils.replaceFirst("", ".+", "zzz") = ""
6715 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc"
6716 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>"
6717 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z"
6718 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123"
6719 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc"
6720 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc"
6721 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit"
6722 * }</pre>
6723 *
6724 * @param text text to search and replace in, may be null.
6725 * @param regex The regular expression to which this string is to be matched.
6726 * @param replacement The string to be substituted for the first match.
6727 * @return The text with the first replacement processed, {@code null} if null String input.
6728 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid.
6729 * @see String#replaceFirst(String, String)
6730 * @see java.util.regex.Pattern
6731 * @see java.util.regex.Pattern#DOTALL
6732 * @since 3.5
6733 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String)}.
6734 */
6735 @Deprecated
6736 public static String replaceFirst(final String text, final String regex, final String replacement) {
6737 return RegExUtils.replaceFirst(text, regex, replacement);
6738 }
6739
6740 /**
6741 * Case insensitively replaces all occurrences of a String within another String.
6742 *
6743 * <p>
6744 * A {@code null} reference passed to this method is a no-op.
6745 * </p>
6746 *
6747 * <pre>
6748 * StringUtils.replaceIgnoreCase(null, *, *) = null
6749 * StringUtils.replaceIgnoreCase("", *, *) = ""
6750 * StringUtils.replaceIgnoreCase("any", null, *) = "any"
6751 * StringUtils.replaceIgnoreCase("any", *, null) = "any"
6752 * StringUtils.replaceIgnoreCase("any", "", *) = "any"
6753 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba"
6754 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b"
6755 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz"
6756 * </pre>
6757 *
6758 * @param text text to search and replace in, may be null.
6759 * @param searchString The String to search for (case-insensitive), may be null.
6760 * @param replacement The String to replace it with, may be null.
6761 * @return The text with any replacements processed, {@code null} if null String input.
6762 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
6763 * @since 3.5
6764 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}.
6765 */
6766 @Deprecated
6767 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
6768 return Strings.CI.replace(text, searchString, replacement);
6769 }
6770
6771 /**
6772 * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String.
6773 *
6774 * <p>
6775 * A {@code null} reference passed to this method is a no-op.
6776 * </p>
6777 *
6778 * <pre>
6779 * StringUtils.replaceIgnoreCase(null, *, *, *) = null
6780 * StringUtils.replaceIgnoreCase("", *, *, *) = ""
6781 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any"
6782 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any"
6783 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any"
6784 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any"
6785 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
6786 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b"
6787 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa"
6788 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa"
6789 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza"
6790 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz"
6791 * </pre>
6792 *
6793 * @param text text to search and replace in, may be null.
6794 * @param searchString The String to search for (case-insensitive), may be null.
6795 * @param replacement The String to replace it with, may be null.
6796 * @param max maximum number of values to replace, or {@code -1} if no maximum.
6797 * @return The text with any replacements processed, {@code null} if null String input.
6798 * @since 3.5
6799 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}.
6800 */
6801 @Deprecated
6802 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
6803 return Strings.CI.replace(text, searchString, replacement, max);
6804 }
6805
6806 /**
6807 * Replaces a String with another String inside a larger String, once.
6808 *
6809 * <p>
6810 * A {@code null} reference passed to this method is a no-op.
6811 * </p>
6812 *
6813 * <pre>
6814 * StringUtils.replaceOnce(null, *, *) = null
6815 * StringUtils.replaceOnce("", *, *) = ""
6816 * StringUtils.replaceOnce("any", null, *) = "any"
6817 * StringUtils.replaceOnce("any", *, null) = "any"
6818 * StringUtils.replaceOnce("any", "", *) = "any"
6819 * StringUtils.replaceOnce("aba", "a", null) = "aba"
6820 * StringUtils.replaceOnce("aba", "a", "") = "ba"
6821 * StringUtils.replaceOnce("aba", "a", "z") = "zba"
6822 * </pre>
6823 *
6824 * @param text text to search and replace in, may be null.
6825 * @param searchString The String to search for, may be null.
6826 * @param replacement The String to replace with, may be null.
6827 * @return The text with any replacements processed, {@code null} if null String input.
6828 * @see #replace(String text, String searchString, String replacement, int max)
6829 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}.
6830 */
6831 @Deprecated
6832 public static String replaceOnce(final String text, final String searchString, final String replacement) {
6833 return Strings.CS.replaceOnce(text, searchString, replacement);
6834 }
6835
6836 /**
6837 * Case insensitively replaces a String with another String inside a larger String, once.
6838 *
6839 * <p>
6840 * A {@code null} reference passed to this method is a no-op.
6841 * </p>
6842 *
6843 * <pre>
6844 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null
6845 * StringUtils.replaceOnceIgnoreCase("", *, *) = ""
6846 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any"
6847 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any"
6848 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any"
6849 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba"
6850 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba"
6851 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba"
6852 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
6853 * </pre>
6854 *
6855 * @param text text to search and replace in, may be null.
6856 * @param searchString The String to search for (case-insensitive), may be null.
6857 * @param replacement The String to replace with, may be null.
6858 * @return The text with any replacements processed, {@code null} if null String input.
6859 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
6860 * @since 3.5
6861 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}.
6862 */
6863 @Deprecated
6864 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
6865 return Strings.CI.replaceOnce(text, searchString, replacement);
6866 }
6867
6868 /**
6869 * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL}
6870 * option. DOTALL is also known as single-line mode in Perl.
6871 *
6872 * This call is a {@code null} safe equivalent to:
6873 * <ul>
6874 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li>
6875 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
6876 * </ul>
6877 *
6878 * <p>
6879 * A {@code null} reference passed to this method is a no-op.
6880 * </p>
6881 *
6882 * <pre>{@code
6883 * StringUtils.replacePattern(null, *, *) = null
6884 * StringUtils.replacePattern("any", (String) null, *) = "any"
6885 * StringUtils.replacePattern("any", *, null) = "any"
6886 * StringUtils.replacePattern("", "", "zzz") = "zzz"
6887 * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
6888 * StringUtils.replacePattern("", ".+", "zzz") = ""
6889 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
6890 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
6891 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
6892 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
6893 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
6894 * }</pre>
6895 *
6896 * @param source The source string.
6897 * @param regex The regular expression to which this string is to be matched.
6898 * @param replacement The string to be substituted for each match.
6899 * @return The resulting {@link String}.
6900 * @see #replaceAll(String, String, String)
6901 * @see String#replaceAll(String, String)
6902 * @see Pattern#DOTALL
6903 * @since 3.2
6904 * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
6905 * @deprecated Use {@link RegExUtils#replacePattern(CharSequence, String, String)}.
6906 */
6907 @Deprecated
6908 public static String replacePattern(final String source, final String regex, final String replacement) {
6909 return RegExUtils.replacePattern(source, regex, replacement);
6910 }
6911
6912 /**
6913 * Reverses a String as per {@link StringBuilder#reverse()}.
6914 *
6915 * <p>
6916 * A {@code null} String returns {@code null}.
6917 * </p>
6918 *
6919 * <pre>
6920 * StringUtils.reverse(null) = null
6921 * StringUtils.reverse("") = ""
6922 * StringUtils.reverse("bat") = "tab"
6923 * </pre>
6924 *
6925 * @param str The String to reverse, may be null.
6926 * @return The reversed String, {@code null} if null String input.
6927 */
6928 public static String reverse(final String str) {
6929 if (str == null) {
6930 return null;
6931 }
6932 return new StringBuilder(str).reverse().toString();
6933 }
6934
6935 /**
6936 * Reverses a String that is delimited by a specific character.
6937 *
6938 * <p>
6939 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}).
6940 * </p>
6941 *
6942 * <pre>
6943 * StringUtils.reverseDelimited(null, *) = null
6944 * StringUtils.reverseDelimited("", *) = ""
6945 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
6946 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
6947 * </pre>
6948 *
6949 * @param str The String to reverse, may be null.
6950 * @param separatorChar The separator character to use.
6951 * @return The reversed String, {@code null} if null String input.
6952 * @since 2.0
6953 */
6954 public static String reverseDelimited(final String str, final char separatorChar) {
6955 final String[] strs = split(str, separatorChar);
6956 ArrayUtils.reverse(strs);
6957 return join(strs, separatorChar);
6958 }
6959
6960 /**
6961 * Gets the rightmost {@code len} characters of a String.
6962 *
6963 * <p>
6964 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is
6965 * returned if len is negative.
6966 * </p>
6967 *
6968 * <pre>
6969 * StringUtils.right(null, *) = null
6970 * StringUtils.right(*, -ve) = ""
6971 * StringUtils.right("", *) = ""
6972 * StringUtils.right("abc", 0) = ""
6973 * StringUtils.right("abc", 2) = "bc"
6974 * StringUtils.right("abc", 4) = "abc"
6975 * </pre>
6976 *
6977 * @param str The String to get the rightmost characters from, may be null.
6978 * @param len The length of the required String.
6979 * @return The rightmost characters, {@code null} if null String input.
6980 */
6981 public static String right(final String str, final int len) {
6982 if (str == null) {
6983 return null;
6984 }
6985 if (len < 0) {
6986 return EMPTY;
6987 }
6988 if (str.length() <= len) {
6989 return str;
6990 }
6991 int start = str.length() - len;
6992 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate
6993 if (splitsSurrogatePair(str, start)) {
6994 start++;
6995 }
6996 return str.substring(start);
6997 }
6998
6999 /**
7000 * Right pad a String with spaces (' ').
7001 *
7002 * <p>
7003 * The String is padded to the size of {@code size}.
7004 * </p>
7005 *
7006 * <pre>
7007 * StringUtils.rightPad(null, *) = null
7008 * StringUtils.rightPad("", 3) = " "
7009 * StringUtils.rightPad("bat", 3) = "bat"
7010 * StringUtils.rightPad("bat", 5) = "bat "
7011 * StringUtils.rightPad("bat", 1) = "bat"
7012 * StringUtils.rightPad("bat", -1) = "bat"
7013 * </pre>
7014 *
7015 * @param str The String to pad out, may be null.
7016 * @param size The size to pad to.
7017 * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
7018 */
7019 public static String rightPad(final String str, final int size) {
7020 return rightPad(str, size, ' ');
7021 }
7022
7023 /**
7024 * Right pad a String with a specified character.
7025 *
7026 * <p>
7027 * The String is padded to the size of {@code size}.
7028 * </p>
7029 *
7030 * <pre>
7031 * StringUtils.rightPad(null, *, *) = null
7032 * StringUtils.rightPad("", 3, 'z') = "zzz"
7033 * StringUtils.rightPad("bat", 3, 'z') = "bat"
7034 * StringUtils.rightPad("bat", 5, 'z') = "batzz"
7035 * StringUtils.rightPad("bat", 1, 'z') = "bat"
7036 * StringUtils.rightPad("bat", -1, 'z') = "bat"
7037 * </pre>
7038 *
7039 * @param str The String to pad out, may be null.
7040 * @param size The size to pad to.
7041 * @param padChar The character to pad with.
7042 * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
7043 * @since 2.0
7044 */
7045 public static String rightPad(final String str, final int size, final char padChar) {
7046 if (str == null || size <= str.length()) {
7047 return str;
7048 }
7049 final int pads = size - str.length();
7050 if (pads <= 0) {
7051 return str; // returns original String when possible
7052 }
7053 if (pads > PAD_LIMIT) {
7054 return rightPad(str, size, String.valueOf(padChar));
7055 }
7056 return str.concat(repeat(padChar, pads));
7057 }
7058
7059 /**
7060 * Right pad a String with a specified String.
7061 *
7062 * <p>
7063 * The String is padded to the size of {@code size}.
7064 * </p>
7065 *
7066 * <pre>
7067 * StringUtils.rightPad(null, *, *) = null
7068 * StringUtils.rightPad("", 3, "z") = "zzz"
7069 * StringUtils.rightPad("bat", 3, "yz") = "bat"
7070 * StringUtils.rightPad("bat", 5, "yz") = "batyz"
7071 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy"
7072 * StringUtils.rightPad("bat", 1, "yz") = "bat"
7073 * StringUtils.rightPad("bat", -1, "yz") = "bat"
7074 * StringUtils.rightPad("bat", 5, null) = "bat "
7075 * StringUtils.rightPad("bat", 5, "") = "bat "
7076 * </pre>
7077 *
7078 * @param str The String to pad out, may be null.
7079 * @param size The size to pad to.
7080 * @param padStr The String to pad with, null or empty treated as single space.
7081 * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
7082 */
7083 public static String rightPad(final String str, final int size, String padStr) {
7084 if (str == null || size <= str.length()) {
7085 return str;
7086 }
7087 if (isEmpty(padStr)) {
7088 padStr = SPACE;
7089 }
7090 final int padLen = padStr.length();
7091 final int strLen = str.length();
7092 final int pads = size - strLen;
7093 if (pads <= 0) {
7094 return str; // returns original String when possible
7095 }
7096 if (padLen == 1 && pads <= PAD_LIMIT) {
7097 return rightPad(str, size, padStr.charAt(0));
7098 }
7099 if (pads == padLen) {
7100 return str.concat(padStr);
7101 }
7102 if (pads < padLen) {
7103 return str.concat(padStr.substring(0, pads));
7104 }
7105 final char[] padding = new char[pads];
7106 final char[] padChars = padStr.toCharArray();
7107 for (int i = 0; i < pads; i++) {
7108 padding[i] = padChars[i % padLen];
7109 }
7110 return str.concat(new String(padding));
7111 }
7112
7113 /**
7114 * Rotate (circular shift) a String of {@code shift} characters.
7115 * <ul>
7116 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li>
7117 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li>
7118 * </ul>
7119 *
7120 * <pre>
7121 * StringUtils.rotate(null, *) = null
7122 * StringUtils.rotate("", *) = ""
7123 * StringUtils.rotate("abcdefg", 0) = "abcdefg"
7124 * StringUtils.rotate("abcdefg", 2) = "fgabcde"
7125 * StringUtils.rotate("abcdefg", -2) = "cdefgab"
7126 * StringUtils.rotate("abcdefg", 7) = "abcdefg"
7127 * StringUtils.rotate("abcdefg", -7) = "abcdefg"
7128 * StringUtils.rotate("abcdefg", 9) = "fgabcde"
7129 * StringUtils.rotate("abcdefg", -9) = "cdefgab"
7130 * </pre>
7131 *
7132 * @param str The String to rotate, may be null.
7133 * @param shift number of time to shift (positive : right shift, negative : left shift).
7134 * @return The rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input.
7135 * @since 3.5
7136 */
7137 public static String rotate(final String str, final int shift) {
7138 if (str == null) {
7139 return null;
7140 }
7141 final int strLen = str.length();
7142 if (shift == 0 || strLen == 0 || shift % strLen == 0) {
7143 return str;
7144 }
7145 final StringBuilder builder = new StringBuilder(strLen);
7146 final int offset = -(shift % strLen);
7147 builder.append(substring(str, offset));
7148 builder.append(substring(str, 0, offset));
7149 return builder.toString();
7150 }
7151
7152 /**
7153 * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}.
7154 *
7155 * <p>
7156 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7157 * StrTokenizer class.
7158 * </p>
7159 *
7160 * <p>
7161 * A {@code null} input String returns {@code null}.
7162 * </p>
7163 *
7164 * <pre>
7165 * StringUtils.split(null) = null
7166 * StringUtils.split("") = []
7167 * StringUtils.split("abc def") = ["abc", "def"]
7168 * StringUtils.split("abc def") = ["abc", "def"]
7169 * StringUtils.split(" abc ") = ["abc"]
7170 * </pre>
7171 *
7172 * @param str The String to parse, may be null.
7173 * @return An array of parsed Strings, {@code null} if null String input.
7174 */
7175 public static String[] split(final String str) {
7176 return split(str, null, -1);
7177 }
7178
7179 /**
7180 * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer.
7181 *
7182 * <p>
7183 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7184 * StrTokenizer class.
7185 * </p>
7186 *
7187 * <p>
7188 * A {@code null} input String returns {@code null}.
7189 * </p>
7190 *
7191 * <pre>
7192 * StringUtils.split(null, *) = null
7193 * StringUtils.split("", *) = []
7194 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
7195 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
7196 * StringUtils.split("a:b:c", '.') = ["a:b:c"]
7197 * StringUtils.split("a b c", ' ') = ["a", "b", "c"]
7198 * </pre>
7199 *
7200 * @param str The String to parse, may be null.
7201 * @param separatorChar The character used as the delimiter.
7202 * @return An array of parsed Strings, {@code null} if null String input.
7203 * @since 2.0
7204 */
7205 public static String[] split(final String str, final char separatorChar) {
7206 return splitWorker(str, separatorChar, false);
7207 }
7208
7209 /**
7210 * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer.
7211 *
7212 * <p>
7213 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7214 * StrTokenizer class.
7215 * </p>
7216 *
7217 * <p>
7218 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7219 * </p>
7220 *
7221 * <pre>
7222 * StringUtils.split(null, *) = null
7223 * StringUtils.split("", *) = []
7224 * StringUtils.split("abc def", null) = ["abc", "def"]
7225 * StringUtils.split("abc def", " ") = ["abc", "def"]
7226 * StringUtils.split("abc def", " ") = ["abc", "def"]
7227 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
7228 * </pre>
7229 *
7230 * @param str The String to parse, may be null.
7231 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace.
7232 * @return An array of parsed Strings, {@code null} if null String input.
7233 */
7234 public static String[] split(final String str, final String separatorChars) {
7235 return splitWorker(str, separatorChars, -1, false);
7236 }
7237
7238 /**
7239 * Splits the provided text into an array with a maximum length, separators specified.
7240 *
7241 * <p>
7242 * The separator is not included in the returned String array. Adjacent separators are treated as one separator.
7243 * </p>
7244 *
7245 * <p>
7246 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7247 * </p>
7248 *
7249 * <p>
7250 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned
7251 * strings (including separator characters).
7252 * </p>
7253 *
7254 * <pre>
7255 * StringUtils.split(null, *, *) = null
7256 * StringUtils.split("", *, *) = []
7257 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
7258 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
7259 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
7260 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
7261 * </pre>
7262 *
7263 * @param str The String to parse, may be null.
7264 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace.
7265 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit.
7266 * @return An array of parsed Strings, {@code null} if null String input.
7267 */
7268 public static String[] split(final String str, final String separatorChars, final int max) {
7269 return splitWorker(str, separatorChars, max, false);
7270 }
7271
7272 /**
7273 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned
7274 * as complete tokens.
7275 *
7276 * <pre>
7277 * StringUtils.splitByCharacterType(null) = null
7278 * StringUtils.splitByCharacterType("") = []
7279 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
7280 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
7281 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
7282 * StringUtils.splitByCharacterType("number5") = ["number", "5"]
7283 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"]
7284 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"]
7285 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"]
7286 * </pre>
7287 *
7288 * @param str The String to split, may be {@code null}.
7289 * @return An array of parsed Strings, {@code null} if null String input.
7290 * @see Character#getType(int)
7291 * @since 2.4
7292 */
7293 public static String[] splitByCharacterType(final String str) {
7294 return splitByCharacterType(str, false);
7295 }
7296
7297 /**
7298 * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned
7299 * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@link Character#UPPERCASE_LETTER}, if any,
7300 * immediately preceding a token of type {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any,
7301 * {@link Character#UPPERCASE_LETTER} token.
7302 *
7303 * @param str The String to split, may be {@code null}.
7304 * @param camelCase whether to use so-called "camel-case" for letter types.
7305 * @return An array of parsed Strings, {@code null} if null String input.
7306 * @since 2.4
7307 */
7308 private static String[] splitByCharacterType(final String str, final boolean camelCase) {
7309 if (str == null) {
7310 return null;
7311 }
7312 if (str.isEmpty()) {
7313 return ArrayUtils.EMPTY_STRING_ARRAY;
7314 }
7315 final char[] c = str.toCharArray();
7316 final List<String> list = new ArrayList<>();
7317 int tokenStart = 0;
7318 int currentType = Character.getType(Character.codePointAt(c, tokenStart));
7319 for (int pos = tokenStart + Character.charCount(Character.codePointAt(c, tokenStart)); pos < c.length;) {
7320 final int codePoint = Character.codePointAt(c, pos);
7321 final int type = Character.getType(codePoint);
7322 final int count = Character.charCount(codePoint);
7323 if (type == currentType) {
7324 pos += count;
7325 continue;
7326 }
7327 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
7328 final int newTokenStart = pos - Character.charCount(Character.codePointBefore(c, pos));
7329 if (newTokenStart != tokenStart) {
7330 list.add(new String(c, tokenStart, newTokenStart - tokenStart));
7331 tokenStart = newTokenStart;
7332 }
7333 } else {
7334 list.add(new String(c, tokenStart, pos - tokenStart));
7335 tokenStart = pos;
7336 }
7337 currentType = type;
7338 pos += count;
7339 }
7340 list.add(new String(c, tokenStart, c.length - tokenStart));
7341 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7342 }
7343
7344 /**
7345 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned
7346 * as complete tokens, with the following exception: the character of type {@link Character#UPPERCASE_LETTER}, if any, immediately preceding a token of type
7347 * {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@link Character#UPPERCASE_LETTER} token.
7348 *
7349 * <pre>
7350 * StringUtils.splitByCharacterTypeCamelCase(null) = null
7351 * StringUtils.splitByCharacterTypeCamelCase("") = []
7352 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
7353 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
7354 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
7355 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"]
7356 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"]
7357 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"]
7358 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"]
7359 * </pre>
7360 *
7361 * @param str The String to split, may be {@code null}.
7362 * @return An array of parsed Strings, {@code null} if null String input.
7363 * @see Character#getType(int)
7364 * @since 2.4
7365 */
7366 public static String[] splitByCharacterTypeCamelCase(final String str) {
7367 return splitByCharacterType(str, true);
7368 }
7369
7370 /**
7371 * Splits the provided text into an array, separator string specified.
7372 *
7373 * <p>
7374 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator.
7375 * </p>
7376 *
7377 * <p>
7378 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7379 * </p>
7380 *
7381 * <pre>
7382 * StringUtils.splitByWholeSeparator(null, *) = null
7383 * StringUtils.splitByWholeSeparator("", *) = []
7384 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
7385 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
7386 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"]
7387 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
7388 * </pre>
7389 *
7390 * @param str The String to parse, may be null.
7391 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7392 * @return An array of parsed Strings, {@code null} if null String was input.
7393 */
7394 public static String[] splitByWholeSeparator(final String str, final String separator) {
7395 return splitByWholeSeparatorWorker(str, separator, -1, false);
7396 }
7397
7398 /**
7399 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings.
7400 *
7401 * <p>
7402 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator.
7403 * </p>
7404 *
7405 * <p>
7406 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7407 * </p>
7408 *
7409 * <pre>
7410 * StringUtils.splitByWholeSeparator(null, *, *) = null
7411 * StringUtils.splitByWholeSeparator("", *, *) = []
7412 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
7413 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
7414 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
7415 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
7416 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
7417 * </pre>
7418 *
7419 * @param str The String to parse, may be null.
7420 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7421 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7422 * @return An array of parsed Strings, {@code null} if null String was input.
7423 */
7424 public static String[] splitByWholeSeparator(final String str, final String separator, final int max) {
7425 return splitByWholeSeparatorWorker(str, separator, max, false);
7426 }
7427
7428 /**
7429 * Splits the provided text into an array, separator string specified.
7430 *
7431 * <p>
7432 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7433 * split use the StrTokenizer class.
7434 * </p>
7435 *
7436 * <p>
7437 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7438 * </p>
7439 *
7440 * <pre>
7441 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null
7442 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = []
7443 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"]
7444 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"]
7445 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
7446 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
7447 * </pre>
7448 *
7449 * @param str The String to parse, may be null.
7450 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7451 * @return An array of parsed Strings, {@code null} if null String was input.
7452 * @since 2.4
7453 */
7454 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
7455 return splitByWholeSeparatorWorker(str, separator, -1, true);
7456 }
7457
7458 /**
7459 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings.
7460 *
7461 * <p>
7462 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7463 * split use the StrTokenizer class.
7464 * </p>
7465 *
7466 * <p>
7467 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7468 * </p>
7469 *
7470 * <pre>
7471 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null
7472 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = []
7473 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"]
7474 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"]
7475 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
7476 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
7477 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
7478 * </pre>
7479 *
7480 * @param str The String to parse, may be null.
7481 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7482 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7483 * @return An array of parsed Strings, {@code null} if null String was input.
7484 * @since 2.4
7485 */
7486 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
7487 return splitByWholeSeparatorWorker(str, separator, max, true);
7488 }
7489
7490 /**
7491 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
7492 *
7493 * @param str The String to parse, may be {@code null}.
7494 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7495 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7496 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7497 * one separator.
7498 * @return An array of parsed Strings, {@code null} if null String input.
7499 * @since 2.4
7500 */
7501 private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) {
7502 if (str == null) {
7503 return null;
7504 }
7505 final int len = str.length();
7506 if (len == 0) {
7507 return ArrayUtils.EMPTY_STRING_ARRAY;
7508 }
7509 if (separator == null || EMPTY.equals(separator)) {
7510 // Split on whitespace.
7511 return splitWorker(str, null, max, preserveAllTokens);
7512 }
7513 final int separatorLength = separator.length();
7514 final ArrayList<String> substrings = new ArrayList<>();
7515 int numberOfSubstrings = 0;
7516 int beg = 0;
7517 int end = 0;
7518 while (end < len) {
7519 end = str.indexOf(separator, beg);
7520 if (end > -1) {
7521 if (end > beg) {
7522 numberOfSubstrings += 1;
7523 if (numberOfSubstrings == max) {
7524 end = len;
7525 substrings.add(str.substring(beg));
7526 } else {
7527 // The following is OK, because String.substring( beg, end ) excludes
7528 // the character at the position 'end'.
7529 substrings.add(str.substring(beg, end));
7530 // Set the starting point for the next search.
7531 // The following is equivalent to beg = end + (separatorLength - 1) + 1,
7532 // which is the right calculation:
7533 beg = end + separatorLength;
7534 }
7535 } else {
7536 // We found a consecutive occurrence of the separator, so skip it.
7537 if (preserveAllTokens) {
7538 numberOfSubstrings += 1;
7539 if (numberOfSubstrings == max) {
7540 end = len;
7541 substrings.add(str.substring(beg));
7542 } else {
7543 substrings.add(EMPTY);
7544 }
7545 }
7546 beg = end + separatorLength;
7547 }
7548 } else {
7549 // String.substring( beg ) goes from 'beg' to the end of the String.
7550 // beg == len means the String ended on a separator, so the trailing
7551 // token is empty and must be dropped unless empty tokens are preserved.
7552 if (preserveAllTokens || beg < len) {
7553 substrings.add(str.substring(beg));
7554 }
7555 end = len;
7556 }
7557 }
7558 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7559 }
7560
7561 /**
7562 * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators.
7563 * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}.
7564 *
7565 * <p>
7566 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7567 * split use the StrTokenizer class.
7568 * </p>
7569 *
7570 * <p>
7571 * A {@code null} input String returns {@code null}.
7572 * </p>
7573 *
7574 * <pre>
7575 * StringUtils.splitPreserveAllTokens(null) = null
7576 * StringUtils.splitPreserveAllTokens("") = []
7577 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]
7578 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]
7579 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]
7580 * </pre>
7581 *
7582 * @param str The String to parse, may be {@code null}.
7583 * @return An array of parsed Strings, {@code null} if null String input.
7584 * @since 2.1
7585 */
7586 public static String[] splitPreserveAllTokens(final String str) {
7587 return splitWorker(str, null, -1, true);
7588 }
7589
7590 /**
7591 * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an
7592 * alternative to using StringTokenizer.
7593 *
7594 * <p>
7595 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7596 * split use the StrTokenizer class.
7597 * </p>
7598 *
7599 * <p>
7600 * A {@code null} input String returns {@code null}.
7601 * </p>
7602 *
7603 * <pre>
7604 * StringUtils.splitPreserveAllTokens(null, *) = null
7605 * StringUtils.splitPreserveAllTokens("", *) = []
7606 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"]
7607 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"]
7608 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"]
7609 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
7610 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"]
7611 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""]
7612 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""]
7613 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "a", "b", "c"]
7614 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", "a", "b", "c"]
7615 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", "a", "b", "c", ""]
7616 * </pre>
7617 *
7618 * @param str The String to parse, may be {@code null}.
7619 * @param separatorChar The character used as the delimiter, {@code null} splits on whitespace.
7620 * @return An array of parsed Strings, {@code null} if null String input.
7621 * @since 2.1
7622 */
7623 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
7624 return splitWorker(str, separatorChar, true);
7625 }
7626
7627 /**
7628 * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an
7629 * alternative to using StringTokenizer.
7630 *
7631 * <p>
7632 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7633 * split use the StrTokenizer class.
7634 * </p>
7635 *
7636 * <p>
7637 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7638 * </p>
7639 *
7640 * <pre>
7641 * StringUtils.splitPreserveAllTokens(null, *) = null
7642 * StringUtils.splitPreserveAllTokens("", *) = []
7643 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"]
7644 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"]
7645 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", "def"]
7646 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
7647 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""]
7648 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
7649 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", "cd", "ef"]
7650 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", "cd", "ef"]
7651 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", "cd", "ef"]
7652 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", "cd", "ef", ""]
7653 * </pre>
7654 *
7655 * @param str The String to parse, may be {@code null}.
7656 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace.
7657 * @return An array of parsed Strings, {@code null} if null String input.
7658 * @since 2.1
7659 */
7660 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
7661 return splitWorker(str, separatorChars, -1, true);
7662 }
7663
7664 /**
7665 * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent
7666 * separators.
7667 *
7668 * <p>
7669 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are
7670 * treated as one separator.
7671 * </p>
7672 *
7673 * <p>
7674 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7675 * </p>
7676 *
7677 * <p>
7678 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned
7679 * strings (including separator characters).
7680 * </p>
7681 *
7682 * <pre>
7683 * StringUtils.splitPreserveAllTokens(null, *, *) = null
7684 * StringUtils.splitPreserveAllTokens("", *, *) = []
7685 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"]
7686 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"]
7687 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
7688 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
7689 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"]
7690 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"]
7691 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"]
7692 * </pre>
7693 *
7694 * @param str The String to parse, may be {@code null}.
7695 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace.
7696 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit.
7697 * @return An array of parsed Strings, {@code null} if null String input.
7698 * @since 2.1
7699 */
7700 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
7701 return splitWorker(str, separatorChars, max, true);
7702 }
7703
7704 /**
7705 * Tests whether a {@link String#substring} boundary at {@code index} would fall between the two halves of a surrogate pair, that is the char before
7706 * {@code index} is a high surrogate and the char at {@code index} is its low surrogate. Slicing there leaves a lone surrogate in the result.
7707 *
7708 * @param str The String being sliced.
7709 * @param index A candidate substring boundary, in {@code char} units.
7710 * @return whether slicing at {@code index} would split a surrogate pair.
7711 */
7712 private static boolean splitsSurrogatePair(final String str, final int index) {
7713 return index > 0 && index < str.length() && Character.isHighSurrogate(str.charAt(index - 1)) && Character.isLowSurrogate(str.charAt(index));
7714 }
7715
7716 /**
7717 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length.
7718 *
7719 * @param str The String to parse, may be {@code null}.
7720 * @param separatorChar The separate character.
7721 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7722 * one separator.
7723 * @return An array of parsed Strings, {@code null} if null String input.
7724 */
7725 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
7726 // Performance tuned for 2.0 (JDK1.4)
7727 if (str == null) {
7728 return null;
7729 }
7730 final int len = str.length();
7731 if (len == 0) {
7732 return ArrayUtils.EMPTY_STRING_ARRAY;
7733 }
7734 final List<String> list = new ArrayList<>();
7735 int i = 0;
7736 int start = 0;
7737 boolean match = false;
7738 boolean lastMatch = false;
7739 while (i < len) {
7740 if (str.charAt(i) == separatorChar) {
7741 if (match || preserveAllTokens) {
7742 list.add(str.substring(start, i));
7743 match = false;
7744 lastMatch = true;
7745 }
7746 start = ++i;
7747 continue;
7748 }
7749 lastMatch = false;
7750 match = true;
7751 i++;
7752 }
7753 if (match || preserveAllTokens && lastMatch) {
7754 list.add(str.substring(start, i));
7755 }
7756 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7757 }
7758
7759 /**
7760 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length.
7761 *
7762 * @param str The String to parse, may be {@code null}.
7763 * @param separatorChars The separate character.
7764 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit.
7765 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7766 * one separator.
7767 * @return An array of parsed Strings, {@code null} if null String input.
7768 */
7769 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
7770 // Performance tuned for 2.0 (JDK1.4)
7771 // Direct code is quicker than StringTokenizer.
7772 // Also, StringTokenizer uses isSpace() not isWhitespace()
7773 if (str == null) {
7774 return null;
7775 }
7776 final int len = str.length();
7777 if (len == 0) {
7778 return ArrayUtils.EMPTY_STRING_ARRAY;
7779 }
7780 final List<String> list = new ArrayList<>();
7781 int sizePlus1 = 1;
7782 int i = 0;
7783 int start = 0;
7784 boolean match = false;
7785 boolean lastMatch = false;
7786 if (separatorChars == null) {
7787 // Null separator means use whitespace
7788 while (i < len) {
7789 if (Character.isWhitespace(str.charAt(i))) {
7790 if (match || preserveAllTokens) {
7791 lastMatch = true;
7792 if (sizePlus1++ == max) {
7793 i = len;
7794 lastMatch = false;
7795 }
7796 list.add(str.substring(start, i));
7797 match = false;
7798 }
7799 start = ++i;
7800 continue;
7801 }
7802 lastMatch = false;
7803 match = true;
7804 i++;
7805 }
7806 } else if (separatorChars.length() == 1) {
7807 // Optimize 1 character case
7808 final char sep = separatorChars.charAt(0);
7809 while (i < len) {
7810 if (str.charAt(i) == sep) {
7811 if (match || preserveAllTokens) {
7812 lastMatch = true;
7813 if (sizePlus1++ == max) {
7814 i = len;
7815 lastMatch = false;
7816 }
7817 list.add(str.substring(start, i));
7818 match = false;
7819 }
7820 start = ++i;
7821 continue;
7822 }
7823 lastMatch = false;
7824 match = true;
7825 i++;
7826 }
7827 } else {
7828 // standard case
7829 while (i < len) {
7830 if (separatorChars.indexOf(str.charAt(i)) >= 0) {
7831 if (match || preserveAllTokens) {
7832 lastMatch = true;
7833 if (sizePlus1++ == max) {
7834 i = len;
7835 lastMatch = false;
7836 }
7837 list.add(str.substring(start, i));
7838 match = false;
7839 }
7840 start = ++i;
7841 continue;
7842 }
7843 lastMatch = false;
7844 match = true;
7845 i++;
7846 }
7847 }
7848 if (match || preserveAllTokens && lastMatch) {
7849 list.add(str.substring(start, i));
7850 }
7851 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7852 }
7853
7854 /**
7855 * Tests if a CharSequence starts with a specified prefix.
7856 *
7857 * <p>
7858 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive.
7859 * </p>
7860 *
7861 * <pre>
7862 * StringUtils.startsWith(null, null) = true
7863 * StringUtils.startsWith(null, "abc") = false
7864 * StringUtils.startsWith("abcdef", null) = false
7865 * StringUtils.startsWith("abcdef", "abc") = true
7866 * StringUtils.startsWith("ABCDEF", "abc") = false
7867 * </pre>
7868 *
7869 * @param str The CharSequence to check, may be null.
7870 * @param prefix The prefix to find, may be null.
7871 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}.
7872 * @see String#startsWith(String)
7873 * @since 2.4
7874 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
7875 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}.
7876 */
7877 @Deprecated
7878 public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
7879 return Strings.CS.startsWith(str, prefix);
7880 }
7881
7882 /**
7883 * Tests if a CharSequence starts with any of the provided case-sensitive prefixes.
7884 *
7885 * <pre>
7886 * StringUtils.startsWithAny(null, null) = false
7887 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false
7888 * StringUtils.startsWithAny("abcxyz", null) = false
7889 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
7890 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
7891 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
7892 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
7893 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
7894 * </pre>
7895 *
7896 * @param sequence The CharSequence to check, may be null.
7897 * @param searchStrings The case-sensitive CharSequence prefixes, may be empty or contain {@code null}.
7898 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with
7899 * any of the provided case-sensitive {@code searchStrings}.
7900 * @see StringUtils#startsWith(CharSequence, CharSequence)
7901 * @since 2.5
7902 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
7903 * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)}.
7904 */
7905 @Deprecated
7906 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
7907 return Strings.CS.startsWithAny(sequence, searchStrings);
7908 }
7909
7910 /**
7911 * Case-insensitive check if a CharSequence starts with a specified prefix.
7912 *
7913 * <p>
7914 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive.
7915 * </p>
7916 *
7917 * <pre>
7918 * StringUtils.startsWithIgnoreCase(null, null) = true
7919 * StringUtils.startsWithIgnoreCase(null, "abc") = false
7920 * StringUtils.startsWithIgnoreCase("abcdef", null) = false
7921 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
7922 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
7923 * </pre>
7924 *
7925 * @param str The CharSequence to check, may be null.
7926 * @param prefix The prefix to find, may be null.
7927 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}.
7928 * @see String#startsWith(String)
7929 * @since 2.4
7930 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
7931 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}.
7932 */
7933 @Deprecated
7934 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
7935 return Strings.CI.startsWith(str, prefix);
7936 }
7937
7938 /**
7939 * Strips whitespace from the start and end of a String.
7940 *
7941 * <p>
7942 * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
7943 * </p>
7944 *
7945 * <p>
7946 * A {@code null} input String returns {@code null}.
7947 * </p>
7948 *
7949 * <pre>
7950 * StringUtils.strip(null) = null
7951 * StringUtils.strip("") = ""
7952 * StringUtils.strip(" ") = ""
7953 * StringUtils.strip("abc") = "abc"
7954 * StringUtils.strip(" abc") = "abc"
7955 * StringUtils.strip("abc ") = "abc"
7956 * StringUtils.strip(" abc ") = "abc"
7957 * StringUtils.strip(" ab c ") = "ab c"
7958 * </pre>
7959 *
7960 * @param str The String to remove whitespace from, may be null.
7961 * @return The stripped String, {@code null} if null String input.
7962 */
7963 public static String strip(final String str) {
7964 return strip(str, null);
7965 }
7966
7967 /**
7968 * Strips any of a set of characters from the start and end of a String. This is similar to {@link String#trim()} but allows the characters to be stripped
7969 * to be controlled.
7970 *
7971 * <p>
7972 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
7973 * </p>
7974 *
7975 * <p>
7976 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use
7977 * {@link #strip(String)}.
7978 * </p>
7979 *
7980 * <pre>
7981 * StringUtils.strip(null, *) = null
7982 * StringUtils.strip("", *) = ""
7983 * StringUtils.strip("abc", null) = "abc"
7984 * StringUtils.strip(" abc", null) = "abc"
7985 * StringUtils.strip("abc ", null) = "abc"
7986 * StringUtils.strip(" abc ", null) = "abc"
7987 * StringUtils.strip(" abcyx", "xyz") = " abc"
7988 * </pre>
7989 *
7990 * @param str The String to remove characters from, may be null.
7991 * @param stripChars The characters to remove, null treated as whitespace.
7992 * @return The stripped String, {@code null} if null String input.
7993 */
7994 public static String strip(String str, final String stripChars) {
7995 str = stripStart(str, stripChars);
7996 return stripEnd(str, stripChars);
7997 }
7998
7999 /**
8000 * Removes diacritics (~= accents) from a string. The case will not be altered.
8001 * <p>
8002 * For instance, 'à' will be replaced by 'a'.
8003 * </p>
8004 * <p>
8005 * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a>
8006 * </p>
8007 * <p>
8008 * Be aware that this NFKD compatibility decomposition can map non-letter compatibility forms (fullwidth, small-form, math-symbol variants of {@code <},
8009 * {@code >}, {@code /}, and so on) to their ASCII counterparts.
8010 * </p>
8011 *
8012 * <pre>
8013 * StringUtils.stripAccents(null) = null
8014 * StringUtils.stripAccents("") = ""
8015 * StringUtils.stripAccents("control") = "control"
8016 * StringUtils.stripAccents("éclair") = "eclair"
8017 * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3") = "abc123"
8018 * StringUtils.stripAccents("\u00BC \u00BD \u00BE") = "1â4 1â2 3â4"
8019 * </pre>
8020 * <p>
8021 * See also <a href="https://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>.
8022 * </p>
8023 *
8024 * @param input String to be stripped.
8025 * @return input text with diacritics removed.
8026 * @since 3.0
8027 */
8028 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix:
8029 // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
8030 public static String stripAccents(final String input) {
8031 if (isEmpty(input)) {
8032 return input;
8033 }
8034 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD));
8035 convertRemainingAccentCharacters(decomposed);
8036 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
8037 }
8038
8039 /**
8040 * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}.
8041 *
8042 * <p>
8043 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A
8044 * {@code null} array entry will be ignored.
8045 * </p>
8046 *
8047 * <pre>
8048 * StringUtils.stripAll(null) = null
8049 * StringUtils.stripAll([]) = []
8050 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
8051 * StringUtils.stripAll(["abc ", null]) = ["abc", null]
8052 * </pre>
8053 *
8054 * @param strs The array to remove whitespace from, may be null.
8055 * @return The stripped Strings, {@code null} if null array input.
8056 */
8057 public static String[] stripAll(final String... strs) {
8058 return stripAll(strs, null);
8059 }
8060
8061 /**
8062 * Strips any of a set of characters from the start and end of every String in an array.
8063 * <p>
8064 * Whitespace is defined by {@link Character#isWhitespace(char)}.
8065 * </p>
8066 *
8067 * <p>
8068 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A
8069 * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}.
8070 * </p>
8071 *
8072 * <pre>
8073 * StringUtils.stripAll(null, *) = null
8074 * StringUtils.stripAll([], *) = []
8075 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]
8076 * StringUtils.stripAll(["abc ", null], null) = ["abc", null]
8077 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
8078 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
8079 * </pre>
8080 *
8081 * @param strs The array to remove characters from, may be null.
8082 * @param stripChars The characters to remove, null treated as whitespace.
8083 * @return The stripped Strings, {@code null} if null array input.
8084 */
8085 public static String[] stripAll(final String[] strs, final String stripChars) {
8086 final int strsLen = ArrayUtils.getLength(strs);
8087 if (strsLen == 0) {
8088 return strs;
8089 }
8090 return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars));
8091 }
8092
8093 /**
8094 * Strips any of a set of characters from the end of a String.
8095 *
8096 * <p>
8097 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
8098 * </p>
8099 *
8100 * <p>
8101 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}.
8102 * </p>
8103 *
8104 * <pre>
8105 * StringUtils.stripEnd(null, *) = null
8106 * StringUtils.stripEnd("", *) = ""
8107 * StringUtils.stripEnd("abc", "") = "abc"
8108 * StringUtils.stripEnd("abc", null) = "abc"
8109 * StringUtils.stripEnd(" abc", null) = " abc"
8110 * StringUtils.stripEnd("abc ", null) = "abc"
8111 * StringUtils.stripEnd(" abc ", null) = " abc"
8112 * StringUtils.stripEnd(" abcyx", "xyz") = " abc"
8113 * StringUtils.stripEnd("120.00", ".0") = "12"
8114 * </pre>
8115 *
8116 * @param str The String to remove characters from, may be null.
8117 * @param stripChars The set of characters to remove, null treated as whitespace.
8118 * @return The stripped String, {@code null} if null String input.
8119 */
8120 public static String stripEnd(final String str, final String stripChars) {
8121 int end = length(str);
8122 if (end == 0) {
8123 return str;
8124 }
8125 if (stripChars == null) {
8126 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
8127 end--;
8128 }
8129 } else if (stripChars.isEmpty()) {
8130 return str;
8131 } else {
8132 while (end != 0) {
8133 final int codePoint = str.codePointBefore(end);
8134 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) {
8135 break;
8136 }
8137 end -= Character.charCount(codePoint);
8138 }
8139 }
8140 return str.substring(0, end);
8141 }
8142
8143 /**
8144 * Strips any of a set of characters from the start of a String.
8145 *
8146 * <p>
8147 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
8148 * </p>
8149 *
8150 * <p>
8151 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}.
8152 * </p>
8153 *
8154 * <pre>
8155 * StringUtils.stripStart(null, *) = null
8156 * StringUtils.stripStart("", *) = ""
8157 * StringUtils.stripStart("abc", "") = "abc"
8158 * StringUtils.stripStart("abc", null) = "abc"
8159 * StringUtils.stripStart(" abc", null) = "abc"
8160 * StringUtils.stripStart("abc ", null) = "abc "
8161 * StringUtils.stripStart(" abc ", null) = "abc "
8162 * StringUtils.stripStart("yxabc ", "xyz") = "abc "
8163 * </pre>
8164 *
8165 * @param str The String to remove characters from, may be null.
8166 * @param stripChars The characters to remove, null treated as whitespace.
8167 * @return The stripped String, {@code null} if null String input.
8168 */
8169 public static String stripStart(final String str, final String stripChars) {
8170 final int strLen = length(str);
8171 if (strLen == 0) {
8172 return str;
8173 }
8174 int start = 0;
8175 if (stripChars == null) {
8176 while (start != strLen && Character.isWhitespace(str.charAt(start))) {
8177 start++;
8178 }
8179 } else if (stripChars.isEmpty()) {
8180 return str;
8181 } else {
8182 while (start != strLen) {
8183 final int codePoint = str.codePointAt(start);
8184 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) {
8185 break;
8186 }
8187 start += Character.charCount(codePoint);
8188 }
8189 }
8190 return str.substring(start);
8191 }
8192
8193 /**
8194 * Strips whitespace from the start and end of a String returning an empty String if {@code null} input.
8195 *
8196 * <p>
8197 * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
8198 * </p>
8199 *
8200 * <pre>
8201 * StringUtils.stripToEmpty(null) = ""
8202 * StringUtils.stripToEmpty("") = ""
8203 * StringUtils.stripToEmpty(" ") = ""
8204 * StringUtils.stripToEmpty("abc") = "abc"
8205 * StringUtils.stripToEmpty(" abc") = "abc"
8206 * StringUtils.stripToEmpty("abc ") = "abc"
8207 * StringUtils.stripToEmpty(" abc ") = "abc"
8208 * StringUtils.stripToEmpty(" ab c ") = "ab c"
8209 * </pre>
8210 *
8211 * @param str The String to be stripped, may be null.
8212 * @return The trimmed String, or an empty String if {@code null} input.
8213 * @since 2.0
8214 */
8215 public static String stripToEmpty(final String str) {
8216 return str == null ? EMPTY : strip(str, null);
8217 }
8218
8219 /**
8220 * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip.
8221 *
8222 * <p>
8223 * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
8224 * </p>
8225 *
8226 * <pre>
8227 * StringUtils.stripToNull(null) = null
8228 * StringUtils.stripToNull("") = null
8229 * StringUtils.stripToNull(" ") = null
8230 * StringUtils.stripToNull("abc") = "abc"
8231 * StringUtils.stripToNull(" abc") = "abc"
8232 * StringUtils.stripToNull("abc ") = "abc"
8233 * StringUtils.stripToNull(" abc ") = "abc"
8234 * StringUtils.stripToNull(" ab c ") = "ab c"
8235 * </pre>
8236 *
8237 * @param str The String to be stripped, may be null.
8238 * @return The stripped String, {@code null} if whitespace, empty or null String input.
8239 * @since 2.0
8240 */
8241 public static String stripToNull(String str) {
8242 if (str == null) {
8243 return null;
8244 }
8245 str = strip(str, null);
8246 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here
8247 }
8248
8249 /**
8250 * Gets a substring from the specified String avoiding exceptions.
8251 *
8252 * <p>
8253 * A negative start position can be used to start {@code n} characters from the end of the String.
8254 * </p>
8255 *
8256 * <p>
8257 * A {@code null} String will return {@code null}. An empty ("") String will return "".
8258 * </p>
8259 *
8260 * <pre>
8261 * StringUtils.substring(null, *) = null
8262 * StringUtils.substring("", *) = ""
8263 * StringUtils.substring("abc", 0) = "abc"
8264 * StringUtils.substring("abc", 2) = "c"
8265 * StringUtils.substring("abc", 4) = ""
8266 * StringUtils.substring("abc", -2) = "bc"
8267 * StringUtils.substring("abc", -4) = "abc"
8268 * </pre>
8269 *
8270 * @param str The String to get the substring from, may be null.
8271 * @param start The position to start from, negative means count back from the end of the String by this many characters.
8272 * @return substring from start position, {@code null} if null String input.
8273 */
8274 public static String substring(final String str, int start) {
8275 if (str == null) {
8276 return null;
8277 }
8278 // handle negatives, which means last n characters
8279 if (start < 0) {
8280 start = str.length() + start; // remember start is negative
8281 }
8282 if (start < 0) {
8283 start = 0;
8284 }
8285 if (start > str.length()) {
8286 return EMPTY;
8287 }
8288 return str.substring(start);
8289 }
8290
8291 /**
8292 * Gets a substring from the specified String avoiding exceptions.
8293 *
8294 * <p>
8295 * A negative start position can be used to start/end {@code n} characters from the end of the String.
8296 * </p>
8297 *
8298 * <p>
8299 * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is
8300 * zero-based -- i.e., to start at the beginning of the string use {@code start = 0}. Negative start and end positions can be used to specify offsets
8301 * relative to the end of the String.
8302 * </p>
8303 *
8304 * <p>
8305 * If {@code start} is not strictly to the left of {@code end}, "" is returned.
8306 * </p>
8307 *
8308 * <pre>
8309 * StringUtils.substring(null, *, *) = null
8310 * StringUtils.substring("", * , *) = "";
8311 * StringUtils.substring("abc", 0, 2) = "ab"
8312 * StringUtils.substring("abc", 2, 0) = ""
8313 * StringUtils.substring("abc", 2, 4) = "c"
8314 * StringUtils.substring("abc", 4, 6) = ""
8315 * StringUtils.substring("abc", 2, 2) = ""
8316 * StringUtils.substring("abc", -2, -1) = "b"
8317 * StringUtils.substring("abc", -4, 2) = "ab"
8318 * </pre>
8319 *
8320 * @param str The String to get the substring from, may be null.
8321 * @param start The position to start from, negative means count back from the end of the String by this many characters.
8322 * @param end The position to end at (exclusive), negative means count back from the end of the String by this many characters.
8323 * @return substring from start position to end position, {@code null} if null String input.
8324 */
8325 public static String substring(final String str, int start, int end) {
8326 if (str == null) {
8327 return null;
8328 }
8329 // handle negatives
8330 if (end < 0) {
8331 end = str.length() + end; // remember end is negative
8332 }
8333 if (start < 0) {
8334 start = str.length() + start; // remember start is negative
8335 }
8336 // check length next
8337 if (end > str.length()) {
8338 end = str.length();
8339 }
8340 // if start is greater than end, return ""
8341 if (start > end) {
8342 return EMPTY;
8343 }
8344 if (start < 0) {
8345 start = 0;
8346 }
8347 if (end < 0) {
8348 end = 0;
8349 }
8350 return str.substring(start, end);
8351 }
8352
8353 /**
8354 * Gets the substring after the first occurrence of a separator. The separator is not returned.
8355 *
8356 * <p>
8357 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8358 * </p>
8359 *
8360 * <p>
8361 * If nothing is found, the empty string is returned.
8362 * </p>
8363 *
8364 * <pre>
8365 * StringUtils.substringAfter(null, *) = null
8366 * StringUtils.substringAfter("", *) = ""
8367 * StringUtils.substringAfter("abc", 'a') = "bc"
8368 * StringUtils.substringAfter("abcba", 'b') = "cba"
8369 * StringUtils.substringAfter("abc", 'c') = ""
8370 * StringUtils.substringAfter("abc", 'd') = ""
8371 * StringUtils.substringAfter(" abc", 32) = "abc"
8372 * </pre>
8373 *
8374 * @param str The String to get a substring from, may be null.
8375 * @param find The character (Unicode code point) to find.
8376 * @return The substring after the first occurrence of the specified character, {@code null} if null String input.
8377 * @since 3.11
8378 */
8379 public static String substringAfter(final String str, final int find) {
8380 if (isEmpty(str)) {
8381 return str;
8382 }
8383 final int pos = str.indexOf(find);
8384 if (pos == INDEX_NOT_FOUND) {
8385 return EMPTY;
8386 }
8387 return str.substring(pos + Character.charCount(find));
8388 }
8389
8390 /**
8391 * Gets the substring after the first occurrence of a separator. The separator is not returned.
8392 *
8393 * <p>
8394 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the
8395 * empty string if the input string is not {@code null}.
8396 * </p>
8397 *
8398 * <p>
8399 * If nothing is found, the empty string is returned.
8400 * </p>
8401 *
8402 * <pre>
8403 * StringUtils.substringAfter(null, *) = null
8404 * StringUtils.substringAfter("", *) = ""
8405 * StringUtils.substringAfter(*, null) = ""
8406 * StringUtils.substringAfter("abc", "a") = "bc"
8407 * StringUtils.substringAfter("abcba", "b") = "cba"
8408 * StringUtils.substringAfter("abc", "c") = ""
8409 * StringUtils.substringAfter("abc", "d") = ""
8410 * StringUtils.substringAfter("abc", "") = "abc"
8411 * </pre>
8412 *
8413 * @param str The String to get a substring from, may be null.
8414 * @param find The String to find, may be null.
8415 * @return The substring after the first occurrence of the specified string, {@code null} if null String input.
8416 * @since 2.0
8417 */
8418 public static String substringAfter(final String str, final String find) {
8419 if (isEmpty(str)) {
8420 return str;
8421 }
8422 if (find == null) {
8423 return EMPTY;
8424 }
8425 final int pos = str.indexOf(find);
8426 if (pos == INDEX_NOT_FOUND) {
8427 return EMPTY;
8428 }
8429 return str.substring(pos + find.length());
8430 }
8431
8432 /**
8433 * Gets the substring after the last occurrence of a separator. The separator is not returned.
8434 *
8435 * <p>
8436 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8437 * </p>
8438 *
8439 * <p>
8440 * If nothing is found, the empty string is returned.
8441 * </p>
8442 *
8443 * <pre>
8444 * StringUtils.substringAfterLast(null, *) = null
8445 * StringUtils.substringAfterLast("", *) = ""
8446 * StringUtils.substringAfterLast("abc", 'a') = "bc"
8447 * StringUtils.substringAfterLast(" bc", 32) = "bc"
8448 * StringUtils.substringAfterLast("abcba", 'b') = "a"
8449 * StringUtils.substringAfterLast("abc", 'c') = ""
8450 * StringUtils.substringAfterLast("a", 'a') = ""
8451 * StringUtils.substringAfterLast("a", 'z') = ""
8452 * </pre>
8453 *
8454 * @param str The String to get a substring from, may be null.
8455 * @param find The character (Unicode code point) to find.
8456 * @return The substring after the last occurrence of the specified character, {@code null} if null String input.
8457 * @since 3.11
8458 */
8459 public static String substringAfterLast(final String str, final int find) {
8460 if (isEmpty(str)) {
8461 return str;
8462 }
8463 final int pos = str.lastIndexOf(find);
8464 if (pos == INDEX_NOT_FOUND || pos == str.length() - Character.charCount(find)) {
8465 return EMPTY;
8466 }
8467 return str.substring(pos + Character.charCount(find));
8468 }
8469
8470 /**
8471 * Gets the substring after the last occurrence of a separator. The separator is not returned.
8472 *
8473 * <p>
8474 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will
8475 * return the empty string if the input string is not {@code null}.
8476 * </p>
8477 *
8478 * <p>
8479 * If nothing is found, the empty string is returned.
8480 * </p>
8481 *
8482 * <pre>
8483 * StringUtils.substringAfterLast(null, *) = null
8484 * StringUtils.substringAfterLast("", *) = ""
8485 * StringUtils.substringAfterLast(*, "") = ""
8486 * StringUtils.substringAfterLast(*, null) = ""
8487 * StringUtils.substringAfterLast("abc", "a") = "bc"
8488 * StringUtils.substringAfterLast("abcba", "b") = "a"
8489 * StringUtils.substringAfterLast("abc", "c") = ""
8490 * StringUtils.substringAfterLast("a", "a") = ""
8491 * StringUtils.substringAfterLast("a", "z") = ""
8492 * </pre>
8493 *
8494 * @param str The String to get a substring from, may be null.
8495 * @param find The String to find, may be null.
8496 * @return The substring after the last occurrence of the specified string, {@code null} if null String input.
8497 * @since 2.0
8498 */
8499 public static String substringAfterLast(final String str, final String find) {
8500 if (isEmpty(str)) {
8501 return str;
8502 }
8503 if (isEmpty(find)) {
8504 return EMPTY;
8505 }
8506 final int pos = str.lastIndexOf(find);
8507 if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) {
8508 return EMPTY;
8509 }
8510 return str.substring(pos + find.length());
8511 }
8512
8513 /**
8514 * Gets the substring before the first occurrence of a separator. The separator is not returned.
8515 *
8516 * <p>
8517 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8518 * </p>
8519 *
8520 * <p>
8521 * If nothing is found, the string input is returned.
8522 * </p>
8523 *
8524 * <pre>
8525 * StringUtils.substringBefore(null, *) = null
8526 * StringUtils.substringBefore("", *) = ""
8527 * StringUtils.substringBefore("abc", 'a') = ""
8528 * StringUtils.substringBefore("abcba", 'b') = "a"
8529 * StringUtils.substringBefore("abc", 'c') = "ab"
8530 * StringUtils.substringBefore("abc", 'd') = "abc"
8531 * </pre>
8532 *
8533 * @param str The String to get a substring from, may be null.
8534 * @param find The character (Unicode code point) to find.
8535 * @return The substring before the first occurrence of the specified character, {@code null} if null String input.
8536 * @since 3.12.0
8537 */
8538 public static String substringBefore(final String str, final int find) {
8539 if (isEmpty(str)) {
8540 return str;
8541 }
8542 final int pos = str.indexOf(find);
8543 if (pos == INDEX_NOT_FOUND) {
8544 return str;
8545 }
8546 return str.substring(0, pos);
8547 }
8548
8549 /**
8550 * Gets the substring before the first occurrence of a separator. The separator is not returned.
8551 *
8552 * <p>
8553 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the
8554 * input string.
8555 * </p>
8556 *
8557 * <p>
8558 * If nothing is found, the string input is returned.
8559 * </p>
8560 *
8561 * <pre>
8562 * StringUtils.substringBefore(null, *) = null
8563 * StringUtils.substringBefore("", *) = ""
8564 * StringUtils.substringBefore("abc", "a") = ""
8565 * StringUtils.substringBefore("abcba", "b") = "a"
8566 * StringUtils.substringBefore("abc", "c") = "ab"
8567 * StringUtils.substringBefore("abc", "d") = "abc"
8568 * StringUtils.substringBefore("abc", "") = ""
8569 * StringUtils.substringBefore("abc", null) = "abc"
8570 * </pre>
8571 *
8572 * @param str The String to get a substring from, may be null.
8573 * @param find The String to find, may be null.
8574 * @return The substring before the first occurrence of the specified string, {@code null} if null String input.
8575 * @since 2.0
8576 */
8577 public static String substringBefore(final String str, final String find) {
8578 if (isEmpty(str) || find == null) {
8579 return str;
8580 }
8581 if (find.isEmpty()) {
8582 return EMPTY;
8583 }
8584 final int pos = str.indexOf(find);
8585 if (pos == INDEX_NOT_FOUND) {
8586 return str;
8587 }
8588 return str.substring(0, pos);
8589 }
8590
8591 /**
8592 * Gets the substring before the last occurrence of a separator. The separator is not returned.
8593 *
8594 * <p>
8595 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will
8596 * return the input string.
8597 * </p>
8598 *
8599 * <p>
8600 * If nothing is found, the string input is returned.
8601 * </p>
8602 *
8603 * <pre>
8604 * StringUtils.substringBeforeLast(null, *) = null
8605 * StringUtils.substringBeforeLast("", *) = ""
8606 * StringUtils.substringBeforeLast("abcba", "b") = "abc"
8607 * StringUtils.substringBeforeLast("abc", "c") = "ab"
8608 * StringUtils.substringBeforeLast("a", "a") = ""
8609 * StringUtils.substringBeforeLast("a", "z") = "a"
8610 * StringUtils.substringBeforeLast("a", null) = "a"
8611 * StringUtils.substringBeforeLast("a", "") = "a"
8612 * </pre>
8613 *
8614 * @param str The String to get a substring from, may be null.
8615 * @param find The String to find, may be null.
8616 * @return The substring before the last occurrence of the specified string, {@code null} if null String input.
8617 * @since 2.0
8618 */
8619 public static String substringBeforeLast(final String str, final String find) {
8620 if (isEmpty(str) || isEmpty(find)) {
8621 return str;
8622 }
8623 final int pos = str.lastIndexOf(find);
8624 if (pos == INDEX_NOT_FOUND) {
8625 return str;
8626 }
8627 return str.substring(0, pos);
8628 }
8629
8630 /**
8631 * Gets the String that is nested in between two instances of the same String.
8632 *
8633 * <p>
8634 * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}.
8635 * </p>
8636 *
8637 * <pre>
8638 * StringUtils.substringBetween(null, *) = null
8639 * StringUtils.substringBetween("", "") = ""
8640 * StringUtils.substringBetween("", "tag") = null
8641 * StringUtils.substringBetween("tagabctag", null) = null
8642 * StringUtils.substringBetween("tagabctag", "") = ""
8643 * StringUtils.substringBetween("tagabctag", "tag") = "abc"
8644 * </pre>
8645 *
8646 * @param str The String containing the substring, may be null.
8647 * @param tag The String before and after the substring, may be null.
8648 * @return The substring, {@code null} if no match.
8649 * @since 2.0
8650 */
8651 public static String substringBetween(final String str, final String tag) {
8652 return substringBetween(str, tag, tag);
8653 }
8654
8655 /**
8656 * Gets the String that is nested in between two Strings. Only the first match is returned.
8657 *
8658 * <p>
8659 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open and close returns an
8660 * empty string.
8661 * </p>
8662 *
8663 * <pre>
8664 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
8665 * StringUtils.substringBetween(null, *, *) = null
8666 * StringUtils.substringBetween(*, null, *) = null
8667 * StringUtils.substringBetween(*, *, null) = null
8668 * StringUtils.substringBetween("", "", "") = ""
8669 * StringUtils.substringBetween("", "", "]") = null
8670 * StringUtils.substringBetween("", "[", "]") = null
8671 * StringUtils.substringBetween("yabcz", "", "") = ""
8672 * StringUtils.substringBetween("yabcz", "y", "z") = "abc"
8673 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
8674 * </pre>
8675 *
8676 * @param str The String containing the substring, may be null.
8677 * @param open The String before the substring, may be null.
8678 * @param close The String after the substring, may be null.
8679 * @return The substring, {@code null} if no match.
8680 * @since 2.0
8681 */
8682 public static String substringBetween(final String str, final String open, final String close) {
8683 if (!ObjectUtils.allNotNull(str, open, close)) {
8684 return null;
8685 }
8686 final int start = str.indexOf(open);
8687 if (start != INDEX_NOT_FOUND) {
8688 final int end = str.indexOf(close, start + open.length());
8689 if (end != INDEX_NOT_FOUND) {
8690 return str.substring(start + open.length(), end);
8691 }
8692 }
8693 return null;
8694 }
8695
8696 /**
8697 * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array.
8698 *
8699 * <p>
8700 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns
8701 * {@code null} (no match).
8702 * </p>
8703 *
8704 * <pre>
8705 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
8706 * StringUtils.substringsBetween(null, *, *) = null
8707 * StringUtils.substringsBetween(*, null, *) = null
8708 * StringUtils.substringsBetween(*, *, null) = null
8709 * StringUtils.substringsBetween("", "[", "]") = []
8710 * </pre>
8711 *
8712 * @param str The String containing the substrings, null returns null, empty returns empty.
8713 * @param open The String identifying the start of the substring, empty returns null.
8714 * @param close The String identifying the end of the substring, empty returns null.
8715 * @return A String Array of substrings, or {@code null} if no match.
8716 * @since 2.3
8717 */
8718 public static String[] substringsBetween(final String str, final String open, final String close) {
8719 if (str == null || isEmpty(open) || isEmpty(close)) {
8720 return null;
8721 }
8722 final int strLen = str.length();
8723 if (strLen == 0) {
8724 return ArrayUtils.EMPTY_STRING_ARRAY;
8725 }
8726 final int closeLen = close.length();
8727 final int openLen = open.length();
8728 final List<String> list = new ArrayList<>();
8729 int pos = 0;
8730 while (pos < strLen - closeLen) {
8731 int start = str.indexOf(open, pos);
8732 if (start < 0) {
8733 break;
8734 }
8735 start += openLen;
8736 final int end = str.indexOf(close, start);
8737 if (end < 0) {
8738 break;
8739 }
8740 list.add(str.substring(start, end));
8741 pos = end + closeLen;
8742 }
8743 if (list.isEmpty()) {
8744 return null;
8745 }
8746 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
8747 }
8748
8749 /**
8750 * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case.
8751 *
8752 * <ul>
8753 * <li>Upper case character converts to Lower case</li>
8754 * <li>Title case character converts to Lower case</li>
8755 * <li>Lower case character converts to Upper case</li>
8756 * </ul>
8757 *
8758 * <p>
8759 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}.
8760 * </p>
8761 *
8762 * <pre>
8763 * StringUtils.swapCase(null) = null
8764 * StringUtils.swapCase("") = ""
8765 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
8766 * </pre>
8767 *
8768 * <p>
8769 * NOTE: This method changed in Lang version 2.0. It no longer performs a word based algorithm. If you only use ASCII, you will notice no change. That
8770 * functionality is available in org.apache.commons.lang3.text.WordUtils.
8771 * </p>
8772 *
8773 * @param str The String to swap case, may be null.
8774 * @return The changed String, {@code null} if null String input.
8775 */
8776 public static String swapCase(final String str) {
8777 if (isEmpty(str)) {
8778 return str;
8779 }
8780 final int strLen = str.length();
8781 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
8782 int outOffset = 0;
8783 for (int i = 0; i < strLen;) {
8784 final int oldCodepoint = str.codePointAt(i);
8785 final int newCodePoint;
8786 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) {
8787 newCodePoint = Character.toLowerCase(oldCodepoint);
8788 } else if (Character.isLowerCase(oldCodepoint)) {
8789 newCodePoint = Character.toUpperCase(oldCodepoint);
8790 } else {
8791 newCodePoint = oldCodepoint;
8792 }
8793 newCodePoints[outOffset++] = newCodePoint;
8794 i += Character.charCount(newCodePoint);
8795 }
8796 return new String(newCodePoints, 0, outOffset);
8797 }
8798
8799 /**
8800 * Converts a {@link CharSequence} into an array of code points.
8801 *
8802 * <p>
8803 * Valid pairs of surrogate code units will be converted into a single supplementary code point. Isolated surrogate code units (i.e. a high surrogate not
8804 * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is.
8805 * </p>
8806 *
8807 * <pre>
8808 * StringUtils.toCodePoints(null) = null
8809 * StringUtils.toCodePoints("") = [] // empty array
8810 * </pre>
8811 *
8812 * @param cs The character sequence to convert.
8813 * @return An array of code points.
8814 * @since 3.6
8815 */
8816 public static int[] toCodePoints(final CharSequence cs) {
8817 if (cs == null) {
8818 return null;
8819 }
8820 if (isEmpty(cs)) {
8821 return ArrayUtils.EMPTY_INT_ARRAY;
8822 }
8823 return cs.toString().codePoints().toArray();
8824 }
8825
8826 /**
8827 * Converts a {@code byte[]} to a String using the specified character encoding.
8828 *
8829 * @param bytes The byte array to read from.
8830 * @param charset The encoding to use, if null then use the platform default.
8831 * @return A new String.
8832 * @throws NullPointerException Thrown if {@code bytes} is null.
8833 * @since 3.2
8834 * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
8835 */
8836 public static String toEncodedString(final byte[] bytes, final Charset charset) {
8837 return new String(bytes, Charsets.toCharset(charset));
8838 }
8839
8840 /**
8841 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
8842 *
8843 * @param source A source String or null.
8844 * @return The given source String as a lower-case using the {@link Locale#ROOT} locale or null.
8845 * @since 3.10
8846 */
8847 public static String toRootLowerCase(final String source) {
8848 return source == null ? null : source.toLowerCase(Locale.ROOT);
8849 }
8850
8851 /**
8852 * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
8853 *
8854 * @param source A source String or null.
8855 * @return The given source String as an upper-case using the {@link Locale#ROOT} locale or null.
8856 * @since 3.10
8857 */
8858 public static String toRootUpperCase(final String source) {
8859 return source == null ? null : source.toUpperCase(Locale.ROOT);
8860 }
8861
8862 /**
8863 * Converts a {@code byte[]} to a String using the specified character encoding.
8864 *
8865 * @param bytes The byte array to read from.
8866 * @param charsetName The encoding to use, if null then use the platform default.
8867 * @return A new String.
8868 * @throws NullPointerException Thrown if the input is null.
8869 * @since 3.1
8870 * @deprecated Use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code.
8871 */
8872 @Deprecated
8873 public static String toString(final byte[] bytes, final String charsetName) {
8874 return new String(bytes, Charsets.toCharset(charsetName));
8875 }
8876
8877 /**
8878 * Removes control characters plus space (char <= 32) from both ends of this String, handling {@code null} by returning {@code null}.
8879 *
8880 * <p>
8881 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #strip(String)}.
8882 * </p>
8883 *
8884 * <p>
8885 * To trim your choice of characters, use the {@link #strip(String, String)} methods.
8886 * </p>
8887 *
8888 * <pre>
8889 * StringUtils.trim(null) = null
8890 * StringUtils.trim("") = ""
8891 * StringUtils.trim(" ") = ""
8892 * StringUtils.trim("abc") = "abc"
8893 * StringUtils.trim(" abc ") = "abc"
8894 * </pre>
8895 *
8896 * @param str The String to be trimmed, may be null.
8897 * @return The trimmed string, {@code null} if null String input.
8898 */
8899 public static String trim(final String str) {
8900 return str == null ? null : str.trim();
8901 }
8902
8903 /**
8904 * Removes {@link CharUtils#isAsciiControl(char) ASCII control characters} (char <= 31 or char == 127) from both ends of this String, handling
8905 * {@code null} by returning {@code null}.
8906 *
8907 * <p>
8908 * To trim your choice of characters, use the {@link #strip(String, String)} methods.
8909 * </p>
8910 *
8911 * <pre>{@code
8912 * StringUtils.trimAsciiControl(null) = null
8913 * StringUtils.trimAsciiControl("") = ""
8914 * StringUtils.trimAsciiControl("abc\u0000") = "abc"
8915 * StringUtils.trimAsciiControl("abc") = "abc"
8916 * StringUtils.trimAsciiControl(" abc ") = " abc "
8917 * }</pre>
8918 *
8919 * @param str The String to be trimmed, may be null.
8920 * @return The trimmed string, {@code null} if null String input.
8921 * @since 3.21.0
8922 */
8923 public static String trimAsciiControl(final String str) {
8924 if (str == null) {
8925 return null;
8926 }
8927 int len = str.length();
8928 int st = 0;
8929 while (st < len && CharUtils.isAsciiControl(str.charAt(st))) {
8930 st++;
8931 }
8932 while (st < len && CharUtils.isAsciiControl(str.charAt(len - 1))) {
8933 len--;
8934 }
8935 return st > 0 || len < str.length() ? str.substring(st, len) : str;
8936 }
8937
8938 /**
8939 * Removes control characters (char <= 32) from both ends of this String returning an empty String ("") if the String is empty ("") after the trim or if
8940 * it is {@code null}.
8941 *
8942 * <p>
8943 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToEmpty(String)}.
8944 * </p>
8945 *
8946 * <pre>
8947 * StringUtils.trimToEmpty(null) = ""
8948 * StringUtils.trimToEmpty("") = ""
8949 * StringUtils.trimToEmpty(" ") = ""
8950 * StringUtils.trimToEmpty("abc") = "abc"
8951 * StringUtils.trimToEmpty(" abc ") = "abc"
8952 * </pre>
8953 *
8954 * @param str The String to be trimmed, may be null.
8955 * @return The trimmed String, or an empty String if {@code null} input.
8956 * @since 2.0
8957 */
8958 public static String trimToEmpty(final String str) {
8959 return str == null ? EMPTY : str.trim();
8960 }
8961
8962 /**
8963 * Removes control characters (char <= 32) from both ends of this String returning {@code null} if the String is empty ("") after the trim or if it is
8964 * {@code null}.
8965 *
8966 * <p>
8967 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToNull(String)}.
8968 * </p>
8969 *
8970 * <pre>
8971 * StringUtils.trimToNull(null) = null
8972 * StringUtils.trimToNull("") = null
8973 * StringUtils.trimToNull(" ") = null
8974 * StringUtils.trimToNull("abc") = "abc"
8975 * StringUtils.trimToNull(" abc ") = "abc"
8976 * </pre>
8977 *
8978 * @param str The String to be trimmed, may be null.
8979 * @return The trimmed String, {@code null} if only chars <= 32, empty or null String input.
8980 * @since 2.0
8981 */
8982 public static String trimToNull(final String str) {
8983 final String ts = trim(str);
8984 return isEmpty(ts) ? null : ts;
8985 }
8986
8987 /**
8988 * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for".
8989 *
8990 * <p>
8991 * Specifically:
8992 * </p>
8993 * <ul>
8994 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li>
8995 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
8996 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
8997 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
8998 * </ul>
8999 *
9000 * <pre>
9001 * StringUtils.truncate(null, 0) = null
9002 * StringUtils.truncate(null, 2) = null
9003 * StringUtils.truncate("", 4) = ""
9004 * StringUtils.truncate("abcdefg", 4) = "abcd"
9005 * StringUtils.truncate("abcdefg", 6) = "abcdef"
9006 * StringUtils.truncate("abcdefg", 7) = "abcdefg"
9007 * StringUtils.truncate("abcdefg", 8) = "abcdefg"
9008 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
9009 * </pre>
9010 *
9011 * @param str The String to truncate, may be null.
9012 * @param maxWidth maximum length of result String, must be non-negative.
9013 * @return truncated String, {@code null} if null String input.
9014 * @throws IllegalArgumentException Thrown if {@code maxWidth} is less than {@code 0}.
9015 * @since 3.5
9016 */
9017 public static String truncate(final String str, final int maxWidth) {
9018 return truncate(str, 0, maxWidth);
9019 }
9020
9021 /**
9022 * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all".
9023 *
9024 * <p>
9025 * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset.
9026 * </p>
9027 *
9028 * <p>
9029 * Specifically:
9030 * </p>
9031 * <ul>
9032 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li>
9033 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
9034 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
9035 * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
9036 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
9037 * </ul>
9038 *
9039 * <pre>
9040 * StringUtils.truncate(null, 0, 0) = null
9041 * StringUtils.truncate(null, 2, 4) = null
9042 * StringUtils.truncate("", 0, 10) = ""
9043 * StringUtils.truncate("", 2, 10) = ""
9044 * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
9045 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
9046 * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
9047 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
9048 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
9049 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
9050 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
9051 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
9052 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
9053 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
9054 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
9055 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
9056 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
9057 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
9058 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
9059 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
9060 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
9061 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
9062 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
9063 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
9064 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
9065 * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
9066 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
9067 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
9068 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
9069 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
9070 * </pre>
9071 *
9072 * @param str The String to truncate, may be null.
9073 * @param offset left edge of source String.
9074 * @param maxWidth maximum length of result String, must be non-negative.
9075 * @return truncated String, {@code null} if null String input.
9076 * @throws IllegalArgumentException Thrown if {@code offset} or {@code maxWidth} is less than {@code 0}.
9077 * @since 3.5
9078 */
9079 public static String truncate(final String str, final int offset, final int maxWidth) {
9080 if (offset < 0) {
9081 throw new IllegalArgumentException("offset cannot be negative");
9082 }
9083 if (maxWidth < 0) {
9084 throw new IllegalArgumentException("maxWidth cannot be negative");
9085 }
9086 if (str == null) {
9087 return null;
9088 }
9089 final int len = str.length();
9090 int start = Math.min(offset, len);
9091 int end = Math.min(offset > len - maxWidth ? len : offset + maxWidth, len);
9092 // keep both edges off the middle of a surrogate pair so the result is never left holding a lone surrogate
9093 if (splitsSurrogatePair(str, start)) {
9094 start++;
9095 }
9096 if (splitsSurrogatePair(str, end)) {
9097 end--;
9098 }
9099 return str.substring(start, Math.max(start, end));
9100 }
9101
9102 /**
9103 * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed.
9104 *
9105 * <p>
9106 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}.
9107 * </p>
9108 *
9109 * <pre>
9110 * StringUtils.uncapitalize(null) = null
9111 * StringUtils.uncapitalize("") = ""
9112 * StringUtils.uncapitalize("cat") = "cat"
9113 * StringUtils.uncapitalize("Cat") = "cat"
9114 * StringUtils.uncapitalize("CAT") = "cAT"
9115 * </pre>
9116 *
9117 * @param str The String to uncapitalize, may be null.
9118 * @return The uncapitalized String, {@code null} if null String input.
9119 * @see org.apache.commons.text.WordUtils#uncapitalize(String)
9120 * @see #capitalize(String)
9121 * @since 2.0
9122 */
9123 public static String uncapitalize(final String str) {
9124 final int strLen = length(str);
9125 if (strLen == 0) {
9126 return str;
9127 }
9128 final int firstCodePoint = str.codePointAt(0);
9129 final int newCodePoint = Character.toLowerCase(firstCodePoint);
9130 if (firstCodePoint == newCodePoint) {
9131 // already uncapitalized
9132 return str;
9133 }
9134 final int[] newCodePoints = str.codePoints().toArray();
9135 newCodePoints[0] = newCodePoint; // copy the first code point
9136 return new String(newCodePoints, 0, newCodePoints.length);
9137 }
9138
9139 /**
9140 * Unwraps a given string from a character.
9141 *
9142 * <pre>
9143 * StringUtils.unwrap(null, null) = null
9144 * StringUtils.unwrap(null, '\0') = null
9145 * StringUtils.unwrap(null, '1') = null
9146 * StringUtils.unwrap("a", 'a') = "a"
9147 * StringUtils.unwrap("aa", 'a') = ""
9148 * StringUtils.unwrap("\'abc\'", '\'') = "abc"
9149 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA"
9150 * StringUtils.unwrap("A", '#') = "A"
9151 * StringUtils.unwrap("#A", '#') = "#A"
9152 * StringUtils.unwrap("A#", '#') = "A#"
9153 * </pre>
9154 *
9155 * @param str The String to be unwrapped, can be null.
9156 * @param wrapChar The character used to unwrap.
9157 * @return unwrapped String or the original string if it is not quoted properly with the wrapChar.
9158 * @since 3.6
9159 */
9160 public static String unwrap(final String str, final char wrapChar) {
9161 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
9162 return str;
9163 }
9164 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
9165 final int startIndex = 0;
9166 final int endIndex = str.length() - 1;
9167 return str.substring(startIndex + 1, endIndex);
9168 }
9169 return str;
9170 }
9171
9172 /**
9173 * Unwraps a given string from another string.
9174 *
9175 * <pre>
9176 * StringUtils.unwrap(null, null) = null
9177 * StringUtils.unwrap(null, "") = null
9178 * StringUtils.unwrap(null, "1") = null
9179 * StringUtils.unwrap("a", "a") = "a"
9180 * StringUtils.unwrap("aa", "a") = ""
9181 * StringUtils.unwrap("\'abc\'", "\'") = "abc"
9182 * StringUtils.unwrap("\"abc\"", "\"") = "abc"
9183 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB"
9184 * StringUtils.unwrap("A", "#") = "A"
9185 * StringUtils.unwrap("#A", "#") = "#A"
9186 * StringUtils.unwrap("A#", "#") = "A#"
9187 * </pre>
9188 *
9189 * @param str The String to be unwrapped, can be null.
9190 * @param wrapToken The String used to unwrap.
9191 * @return unwrapped String or the original string if it is not quoted properly with the wrapToken.
9192 * @since 3.6
9193 */
9194 public static String unwrap(final String str, final String wrapToken) {
9195 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) {
9196 return str;
9197 }
9198 if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) {
9199 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken));
9200 }
9201 return str;
9202 }
9203
9204 /**
9205 * Converts a String to upper case as per {@link String#toUpperCase()}.
9206 *
9207 * <p>
9208 * A {@code null} input String returns {@code null}.
9209 * </p>
9210 *
9211 * <pre>
9212 * StringUtils.upperCase(null) = null
9213 * StringUtils.upperCase("") = ""
9214 * StringUtils.upperCase("aBc") = "ABC"
9215 * </pre>
9216 *
9217 * <p>
9218 * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale.
9219 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g.
9220 * {@link Locale#ENGLISH}).
9221 * </p>
9222 *
9223 * @param str The String to upper case, may be null.
9224 * @return The upper-cased String, {@code null} if null String input.
9225 */
9226 public static String upperCase(final String str) {
9227 if (str == null) {
9228 return null;
9229 }
9230 return str.toUpperCase();
9231 }
9232
9233 /**
9234 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
9235 *
9236 * <p>
9237 * A {@code null} input String returns {@code null}.
9238 * </p>
9239 *
9240 * <pre>
9241 * StringUtils.upperCase(null, Locale.ENGLISH) = null
9242 * StringUtils.upperCase("", Locale.ENGLISH) = ""
9243 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
9244 * </pre>
9245 *
9246 * @param str The String to upper case, may be null.
9247 * @param locale The locale that defines the case transformation rules, must not be null.
9248 * @return The upper-cased String, {@code null} if null String input.
9249 * @since 2.5
9250 */
9251 public static String upperCase(final String str, final Locale locale) {
9252 if (str == null) {
9253 return null;
9254 }
9255 return str.toUpperCase(LocaleUtils.toLocale(locale));
9256 }
9257
9258 /**
9259 * Returns the string representation of the {@code char} array or null.
9260 *
9261 * @param value The character array.
9262 * @return A String or null.
9263 * @see String#valueOf(char[])
9264 * @since 3.9
9265 */
9266 public static String valueOf(final char[] value) {
9267 return value == null ? null : String.valueOf(value);
9268 }
9269
9270 /**
9271 * Wraps a string with a char.
9272 *
9273 * <pre>
9274 * StringUtils.wrap(null, *) = null
9275 * StringUtils.wrap("", *) = ""
9276 * StringUtils.wrap("ab", '\0') = "ab"
9277 * StringUtils.wrap("ab", 'x') = "xabx"
9278 * StringUtils.wrap("ab", '\'') = "'ab'"
9279 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
9280 * </pre>
9281 *
9282 * @param str The string to be wrapped, may be {@code null}.
9283 * @param wrapWith The char that will wrap {@code str}.
9284 * @return The wrapped string, or {@code null} if {@code str == null}.
9285 * @since 3.4
9286 */
9287 public static String wrap(final String str, final char wrapWith) {
9288 if (isEmpty(str) || wrapWith == CharUtils.NUL) {
9289 return str;
9290 }
9291 return wrapWith + str + wrapWith;
9292 }
9293
9294 /**
9295 * Wraps a String with another String.
9296 *
9297 * <p>
9298 * A {@code null} input String returns {@code null}.
9299 * </p>
9300 *
9301 * <pre>
9302 * StringUtils.wrap(null, *) = null
9303 * StringUtils.wrap("", *) = ""
9304 * StringUtils.wrap("ab", null) = "ab"
9305 * StringUtils.wrap("ab", "x") = "xabx"
9306 * StringUtils.wrap("ab", "\"") = "\"ab\""
9307 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\""
9308 * StringUtils.wrap("ab", "'") = "'ab'"
9309 * StringUtils.wrap("'abcd'", "'") = "''abcd''"
9310 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
9311 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\""
9312 * </pre>
9313 *
9314 * @param str The String to be wrapper, may be null.
9315 * @param wrapWith The String that will wrap str.
9316 * @return wrapped String, {@code null} if null String input.
9317 * @since 3.4
9318 */
9319 public static String wrap(final String str, final String wrapWith) {
9320 if (isEmpty(str) || isEmpty(wrapWith)) {
9321 return str;
9322 }
9323 return wrapWith.concat(str).concat(wrapWith);
9324 }
9325
9326 /**
9327 * Wraps a string with a char if that char is missing from the start or end of the given string.
9328 *
9329 * <p>
9330 * A new {@link String} will not be created if {@code str} is already wrapped.
9331 * </p>
9332 *
9333 * <pre>
9334 * StringUtils.wrapIfMissing(null, *) = null
9335 * StringUtils.wrapIfMissing("", *) = ""
9336 * StringUtils.wrapIfMissing("ab", '\0') = "ab"
9337 * StringUtils.wrapIfMissing("ab", 'x') = "xabx"
9338 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'"
9339 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
9340 * StringUtils.wrapIfMissing("/", '/') = "/"
9341 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/"
9342 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/"
9343 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/"
9344 * </pre>
9345 *
9346 * @param str The string to be wrapped, may be {@code null}.
9347 * @param wrapWith The char that will wrap {@code str}.
9348 * @return The wrapped string, or {@code null} if {@code str == null}.
9349 * @since 3.5
9350 */
9351 public static String wrapIfMissing(final String str, final char wrapWith) {
9352 if (isEmpty(str) || wrapWith == CharUtils.NUL) {
9353 return str;
9354 }
9355 final boolean wrapStart = str.charAt(0) != wrapWith;
9356 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
9357 if (!wrapStart && !wrapEnd) {
9358 return str;
9359 }
9360 final StringBuilder builder = new StringBuilder(str.length() + 2);
9361 if (wrapStart) {
9362 builder.append(wrapWith);
9363 }
9364 builder.append(str);
9365 if (wrapEnd) {
9366 builder.append(wrapWith);
9367 }
9368 return builder.toString();
9369 }
9370
9371 /**
9372 * Wraps a string with a string if that string is missing from the start or end of the given string.
9373 *
9374 * <p>
9375 * A new {@link String} will not be created if {@code str} is already wrapped.
9376 * </p>
9377 *
9378 * <pre>
9379 * StringUtils.wrapIfMissing(null, *) = null
9380 * StringUtils.wrapIfMissing("", *) = ""
9381 * StringUtils.wrapIfMissing("ab", null) = "ab"
9382 * StringUtils.wrapIfMissing("ab", "x") = "xabx"
9383 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\""
9384 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\""
9385 * StringUtils.wrapIfMissing("ab", "'") = "'ab'"
9386 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'"
9387 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
9388 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\""
9389 * StringUtils.wrapIfMissing("/", "/") = "/"
9390 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/"
9391 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/"
9392 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/"
9393 * </pre>
9394 *
9395 * @param str The string to be wrapped, may be {@code null}.
9396 * @param wrapWith The string that will wrap {@code str}.
9397 * @return The wrapped string, or {@code null} if {@code str == null}.
9398 * @since 3.5
9399 */
9400 public static String wrapIfMissing(final String str, final String wrapWith) {
9401 if (isEmpty(str) || isEmpty(wrapWith)) {
9402 return str;
9403 }
9404 final boolean wrapStart = !str.startsWith(wrapWith);
9405 final boolean wrapEnd = !str.endsWith(wrapWith);
9406 if (!wrapStart && !wrapEnd) {
9407 return str;
9408 }
9409 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
9410 if (wrapStart) {
9411 builder.append(wrapWith);
9412 }
9413 builder.append(str);
9414 if (wrapEnd) {
9415 builder.append(wrapWith);
9416 }
9417 return builder.toString();
9418 }
9419
9420 /**
9421 * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}.
9422 *
9423 * <p>
9424 * This constructor is public to permit tools that require a JavaBean instance to operate.
9425 * </p>
9426 *
9427 * @deprecated TODO Make private in 4.0.
9428 */
9429 @Deprecated
9430 public StringUtils() {
9431 // empty
9432 }
9433
9434 }