1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.lang3; 18 19 import java.io.UnsupportedEncodingException; 20 import java.nio.charset.Charset; 21 import java.text.Normalizer; 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.HashSet; 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 33 import org.apache.commons.lang3.function.Suppliers; 34 import org.apache.commons.lang3.function.ToBooleanBiFunction; 35 import org.apache.commons.lang3.stream.LangCollectors; 36 import org.apache.commons.lang3.stream.Streams; 37 38 /** 39 * Operations on {@link java.lang.String} that are 40 * {@code null} safe. 41 * 42 * <ul> 43 * <li><b>IsEmpty/IsBlank</b> 44 * - checks if a String contains text</li> 45 * <li><b>Trim/Strip</b> 46 * - removes leading and trailing whitespace</li> 47 * <li><b>Equals/Compare</b> 48 * - compares two strings in a null-safe manner</li> 49 * <li><b>startsWith</b> 50 * - check if a String starts with a prefix in a null-safe manner</li> 51 * <li><b>endsWith</b> 52 * - check if a String ends with a suffix in a null-safe manner</li> 53 * <li><b>IndexOf/LastIndexOf/Contains</b> 54 * - null-safe index-of checks 55 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b> 56 * - index-of any of a set of Strings</li> 57 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b> 58 * - checks if String contains only/none/any of these characters</li> 59 * <li><b>Substring/Left/Right/Mid</b> 60 * - null-safe substring extractions</li> 61 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b> 62 * - substring extraction relative to other strings</li> 63 * <li><b>Split/Join</b> 64 * - splits a String into an array of substrings and vice versa</li> 65 * <li><b>Remove/Delete</b> 66 * - removes part of a String</li> 67 * <li><b>Replace/Overlay</b> 68 * - Searches a String and replaces one String with another</li> 69 * <li><b>Chomp/Chop</b> 70 * - removes the last part of a String</li> 71 * <li><b>AppendIfMissing</b> 72 * - appends a suffix to the end of the String if not present</li> 73 * <li><b>PrependIfMissing</b> 74 * - prepends a prefix to the start of the String if not present</li> 75 * <li><b>LeftPad/RightPad/Center/Repeat</b> 76 * - pads a String</li> 77 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b> 78 * - changes the case of a String</li> 79 * <li><b>CountMatches</b> 80 * - counts the number of occurrences of one String in another</li> 81 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b> 82 * - checks the characters in a String</li> 83 * <li><b>DefaultString</b> 84 * - protects against a null input String</li> 85 * <li><b>Rotate</b> 86 * - rotate (circular shift) a String</li> 87 * <li><b>Reverse/ReverseDelimited</b> 88 * - reverses a String</li> 89 * <li><b>Abbreviate</b> 90 * - abbreviates a string using ellipses or another given String</li> 91 * <li><b>Difference</b> 92 * - compares Strings and reports on their differences</li> 93 * <li><b>LevenshteinDistance</b> 94 * - the number of changes needed to change one String into another</li> 95 * </ul> 96 * 97 * <p>The {@link StringUtils} class defines certain words related to 98 * String handling.</p> 99 * 100 * <ul> 101 * <li>null - {@code null}</li> 102 * <li>empty - a zero-length string ({@code ""})</li> 103 * <li>space - the space character ({@code ' '}, char 32)</li> 104 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 105 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 106 * </ul> 107 * 108 * <p>{@link StringUtils} handles {@code null} input Strings quietly. 109 * That is to say that a {@code null} input will return {@code null}. 110 * Where a {@code boolean} or {@code int} is being returned 111 * details vary by method.</p> 112 * 113 * <p>A side effect of the {@code null} handling is that a 114 * {@link NullPointerException} should be considered a bug in 115 * {@link StringUtils}.</p> 116 * 117 * <p>Methods in this class include sample code in their Javadoc comments to explain their operation. 118 * The symbol {@code *} is used to indicate any input including {@code null}.</p> 119 * 120 * <p>#ThreadSafe#</p> 121 * @see String 122 * @since 1.0 123 */ 124 //@Immutable 125 public class StringUtils { 126 127 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 128 // Whitespace: 129 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 130 // where WHITESPACE is a string of all whitespace characters 131 // 132 // Character access: 133 // String.charAt(n) versus toCharArray(), then array[n] 134 // String.charAt(n) is about 15% worse for a 10K string 135 // They are about equal for a length 50 string 136 // String.charAt(n) is about 4 times better for a length 3 string 137 // String.charAt(n) is best bet overall 138 // 139 // Append: 140 // String.concat about twice as fast as StringBuffer.append 141 // (not sure who tested this) 142 143 /** 144 * A String for a space character. 145 * 146 * @since 3.2 147 */ 148 public static final String SPACE = " "; 149 150 /** 151 * The empty String {@code ""}. 152 * @since 2.0 153 */ 154 public static final String EMPTY = ""; 155 156 /** 157 * A String for linefeed LF ("\n"). 158 * 159 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 160 * for Character and String Literals</a> 161 * @since 3.2 162 */ 163 public static final String LF = "\n"; 164 165 /** 166 * A String for carriage return CR ("\r"). 167 * 168 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 169 * for Character and String Literals</a> 170 * @since 3.2 171 */ 172 public static final String CR = "\r"; 173 174 /** 175 * Represents a failed index search. 176 * @since 2.1 177 */ 178 public static final int INDEX_NOT_FOUND = -1; 179 180 /** 181 * The maximum size to which the padding constant(s) can expand. 182 */ 183 private static final int PAD_LIMIT = 8192; 184 185 /** 186 * Pattern used in {@link #stripAccents(String)}. 187 */ 188 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 189 190 /** 191 * Abbreviates a String using ellipses. This will turn 192 * "Now is the time for all good men" into "Now is the time for..." 193 * 194 * <p>Specifically:</p> 195 * <ul> 196 * <li>If the number of characters in {@code str} is less than or equal to 197 * {@code maxWidth}, return {@code str}.</li> 198 * <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li> 199 * <li>If {@code maxWidth} is less than {@code 4}, throw an 200 * {@link IllegalArgumentException}.</li> 201 * <li>In no case will it return a String of length greater than 202 * {@code maxWidth}.</li> 203 * </ul> 204 * 205 * <pre> 206 * StringUtils.abbreviate(null, *) = null 207 * StringUtils.abbreviate("", 4) = "" 208 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 209 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 210 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 211 * StringUtils.abbreviate("abcdefg", 4) = "a..." 212 * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException 213 * </pre> 214 * 215 * @param str the String to check, may be null 216 * @param maxWidth maximum length of result String, must be at least 4 217 * @return abbreviated String, {@code null} if null String input 218 * @throws IllegalArgumentException if the width is too small 219 * @since 2.0 220 */ 221 public static String abbreviate(final String str, final int maxWidth) { 222 return abbreviate(str, "...", 0, maxWidth); 223 } 224 225 /** 226 * Abbreviates a String using ellipses. This will turn 227 * "Now is the time for all good men" into "...is the time for..." 228 * 229 * <p>Works like {@code abbreviate(String, int)}, but allows you to specify 230 * a "left edge" offset. Note that this left edge is not necessarily going to 231 * be the leftmost character in the result, or the first character following the 232 * ellipses, but it will appear somewhere in the result. 233 * 234 * <p>In no case will it return a String of length greater than 235 * {@code maxWidth}.</p> 236 * 237 * <pre> 238 * StringUtils.abbreviate(null, *, *) = null 239 * StringUtils.abbreviate("", 0, 4) = "" 240 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 241 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 242 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 243 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 244 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 245 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 246 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 247 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 248 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 249 * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 250 * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 251 * </pre> 252 * 253 * @param str the String to check, may be null 254 * @param offset left edge of source String 255 * @param maxWidth maximum length of result String, must be at least 4 256 * @return abbreviated String, {@code null} if null String input 257 * @throws IllegalArgumentException if the width is too small 258 * @since 2.0 259 */ 260 public static String abbreviate(final String str, final int offset, final int maxWidth) { 261 return abbreviate(str, "...", offset, maxWidth); 262 } 263 264 /** 265 * Abbreviates a String using another given String as replacement marker. This will turn 266 * "Now is the time for all good men" into "Now is the time for..." if "..." was defined 267 * as the replacement marker. 268 * 269 * <p>Specifically:</p> 270 * <ul> 271 * <li>If the number of characters in {@code str} is less than or equal to 272 * {@code maxWidth}, return {@code str}.</li> 273 * <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li> 274 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an 275 * {@link IllegalArgumentException}.</li> 276 * <li>In no case will it return a String of length greater than 277 * {@code maxWidth}.</li> 278 * </ul> 279 * 280 * <pre> 281 * StringUtils.abbreviate(null, "...", *) = null 282 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 283 * StringUtils.abbreviate("", "...", 4) = "" 284 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 285 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 286 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 287 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 288 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 289 * StringUtils.abbreviate("abcdefg", "..", 2) = IllegalArgumentException 290 * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException 291 * </pre> 292 * 293 * @param str the String to check, may be null 294 * @param abbrevMarker the String used as replacement marker 295 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1} 296 * @return abbreviated String, {@code null} if null String input 297 * @throws IllegalArgumentException if the width is too small 298 * @since 3.6 299 */ 300 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 301 return abbreviate(str, abbrevMarker, 0, maxWidth); 302 } 303 /** 304 * Abbreviates a String using a given replacement marker. This will turn 305 * "Now is the time for all good men" into "...is the time for..." if "..." was defined 306 * as the replacement marker. 307 * 308 * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify 309 * a "left edge" offset. Note that this left edge is not necessarily going to 310 * be the leftmost character in the result, or the first character following the 311 * replacement marker, but it will appear somewhere in the result. 312 * 313 * <p>In no case will it return a String of length greater than {@code maxWidth}.</p> 314 * 315 * <pre> 316 * StringUtils.abbreviate(null, null, *, *) = null 317 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 318 * StringUtils.abbreviate("", "...", 0, 4) = "" 319 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 320 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 321 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 322 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 323 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 324 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 325 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 326 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 327 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 328 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = IllegalArgumentException 329 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = IllegalArgumentException 330 * </pre> 331 * 332 * @param str the String to check, may be null 333 * @param abbrevMarker the String used as replacement marker 334 * @param offset left edge of source String 335 * @param maxWidth maximum length of result String, must be at least 4 336 * @return abbreviated String, {@code null} if null String input 337 * @throws IllegalArgumentException if the width is too small 338 * @since 3.6 339 */ 340 public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) { 341 if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) { 342 return substring(str, 0, maxWidth); 343 } 344 if (isAnyEmpty(str, abbrevMarker)) { 345 return str; 346 } 347 final int abbrevMarkerLength = abbrevMarker.length(); 348 final int minAbbrevWidth = abbrevMarkerLength + 1; 349 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 350 351 if (maxWidth < minAbbrevWidth) { 352 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 353 } 354 final int strLen = str.length(); 355 if (strLen <= maxWidth) { 356 return str; 357 } 358 if (offset > strLen) { 359 offset = strLen; 360 } 361 if (strLen - offset < maxWidth - abbrevMarkerLength) { 362 offset = strLen - (maxWidth - abbrevMarkerLength); 363 } 364 if (offset <= abbrevMarkerLength+1) { 365 return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker; 366 } 367 if (maxWidth < minAbbrevWidthOffset) { 368 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 369 } 370 if (offset + maxWidth - abbrevMarkerLength < strLen) { 371 return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength); 372 } 373 return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength)); 374 } 375 376 /** 377 * Abbreviates a String to the length passed, replacing the middle characters with the supplied 378 * replacement String. 379 * 380 * <p>This abbreviation only occurs if the following criteria is met:</p> 381 * <ul> 382 * <li>Neither the String for abbreviation nor the replacement String are null or empty </li> 383 * <li>The length to truncate to is less than the length of the supplied String</li> 384 * <li>The length to truncate to is greater than 0</li> 385 * <li>The abbreviated String will have enough room for the length supplied replacement String 386 * and the first and last characters of the supplied String for abbreviation</li> 387 * </ul> 388 * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation. 389 * </p> 390 * 391 * <pre> 392 * StringUtils.abbreviateMiddle(null, null, 0) = null 393 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 394 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 395 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 396 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 397 * </pre> 398 * 399 * @param str the String to abbreviate, may be null 400 * @param middle the String to replace the middle characters with, may be null 401 * @param length the length to abbreviate {@code str} to. 402 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 403 * @since 2.5 404 */ 405 public static String abbreviateMiddle(final String str, final String middle, final int length) { 406 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length()+2) { 407 return str; 408 } 409 410 final int targetSting = length-middle.length(); 411 final int startOffset = targetSting/2+targetSting%2; 412 final int endOffset = str.length()-targetSting/2; 413 414 return str.substring(0, startOffset) + 415 middle + 416 str.substring(endOffset); 417 } 418 419 /** 420 * Appends the suffix to the end of the string if the string does not 421 * already end with the suffix. 422 * 423 * @param str The string. 424 * @param suffix The suffix to append to the end of the string. 425 * @param ignoreCase Indicates whether the compare should ignore case. 426 * @param suffixes Additional suffixes that are valid terminators (optional). 427 * 428 * @return A new String if suffix was appended, the same string otherwise. 429 */ 430 private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) { 431 if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) { 432 return str; 433 } 434 if (ArrayUtils.isNotEmpty(suffixes)) { 435 for (final CharSequence s : suffixes) { 436 if (endsWith(str, s, ignoreCase)) { 437 return str; 438 } 439 } 440 } 441 return str + suffix.toString(); 442 } 443 444 /** 445 * Appends the suffix to the end of the string if the string does not 446 * already end with any of the suffixes. 447 * 448 * <pre> 449 * StringUtils.appendIfMissing(null, null) = null 450 * StringUtils.appendIfMissing("abc", null) = "abc" 451 * StringUtils.appendIfMissing("", "xyz") = "xyz" 452 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 453 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 454 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 455 * </pre> 456 * <p>With additional suffixes,</p> 457 * <pre> 458 * StringUtils.appendIfMissing(null, null, null) = null 459 * StringUtils.appendIfMissing("abc", null, null) = "abc" 460 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 461 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 462 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 463 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 464 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 465 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 466 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 467 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 468 * </pre> 469 * 470 * @param str The string. 471 * @param suffix The suffix to append to the end of the string. 472 * @param suffixes Additional suffixes that are valid terminators. 473 * 474 * @return A new String if suffix was appended, the same string otherwise. 475 * 476 * @since 3.2 477 */ 478 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 479 return appendIfMissing(str, suffix, false, suffixes); 480 } 481 482 /** 483 * Appends the suffix to the end of the string if the string does not 484 * already end, case-insensitive, with any of the suffixes. 485 * 486 * <pre> 487 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 488 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 489 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 490 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 491 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 492 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 493 * </pre> 494 * <p>With additional suffixes,</p> 495 * <pre> 496 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 497 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 498 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 499 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 500 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 501 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 502 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 503 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 504 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 505 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 506 * </pre> 507 * 508 * @param str The string. 509 * @param suffix The suffix to append to the end of the string. 510 * @param suffixes Additional suffixes that are valid terminators. 511 * 512 * @return A new String if suffix was appended, the same string otherwise. 513 * 514 * @since 3.2 515 */ 516 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 517 return appendIfMissing(str, suffix, true, suffixes); 518 } 519 520 /** 521 * Capitalizes a String changing the first character to title case as 522 * per {@link Character#toTitleCase(int)}. No other characters are changed. 523 * 524 * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. 525 * A {@code null} input String returns {@code null}.</p> 526 * 527 * <pre> 528 * StringUtils.capitalize(null) = null 529 * StringUtils.capitalize("") = "" 530 * StringUtils.capitalize("cat") = "Cat" 531 * StringUtils.capitalize("cAt") = "CAt" 532 * StringUtils.capitalize("'cat'") = "'cat'" 533 * </pre> 534 * 535 * @param str the String to capitalize, may be null 536 * @return the capitalized String, {@code null} if null String input 537 * @see org.apache.commons.text.WordUtils#capitalize(String) 538 * @see #uncapitalize(String) 539 * @since 2.0 540 */ 541 public static String capitalize(final String str) { 542 final int strLen = length(str); 543 if (strLen == 0) { 544 return str; 545 } 546 547 final int firstCodepoint = str.codePointAt(0); 548 final int newCodePoint = Character.toTitleCase(firstCodepoint); 549 if (firstCodepoint == newCodePoint) { 550 // already capitalized 551 return str; 552 } 553 554 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 555 int outOffset = 0; 556 newCodePoints[outOffset++] = newCodePoint; // copy the first code point 557 for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) { 558 final int codePoint = str.codePointAt(inOffset); 559 newCodePoints[outOffset++] = codePoint; // copy the remaining ones 560 inOffset += Character.charCount(codePoint); 561 } 562 return new String(newCodePoints, 0, outOffset); 563 } 564 565 /** 566 * Centers a String in a larger String of size {@code size} 567 * using the space character (' '). 568 * 569 * <p>If the size is less than the String length, the original String is returned. 570 * A {@code null} String returns {@code null}. 571 * A negative size is treated as zero.</p> 572 * 573 * <p>Equivalent to {@code center(str, size, " ")}.</p> 574 * 575 * <pre> 576 * StringUtils.center(null, *) = null 577 * StringUtils.center("", 4) = " " 578 * StringUtils.center("ab", -1) = "ab" 579 * StringUtils.center("ab", 4) = " ab " 580 * StringUtils.center("abcd", 2) = "abcd" 581 * StringUtils.center("a", 4) = " a " 582 * </pre> 583 * 584 * @param str the String to center, may be null 585 * @param size the int size of new String, negative treated as zero 586 * @return centered String, {@code null} if null String input 587 */ 588 public static String center(final String str, final int size) { 589 return center(str, size, ' '); 590 } 591 592 /** 593 * Centers a String in a larger String of size {@code size}. 594 * Uses a supplied character as the value to pad the String with. 595 * 596 * <p>If the size is less than the String length, the String is returned. 597 * A {@code null} String returns {@code null}. 598 * A negative size is treated as zero.</p> 599 * 600 * <pre> 601 * StringUtils.center(null, *, *) = null 602 * StringUtils.center("", 4, ' ') = " " 603 * StringUtils.center("ab", -1, ' ') = "ab" 604 * StringUtils.center("ab", 4, ' ') = " ab " 605 * StringUtils.center("abcd", 2, ' ') = "abcd" 606 * StringUtils.center("a", 4, ' ') = " a " 607 * StringUtils.center("a", 4, 'y') = "yayy" 608 * </pre> 609 * 610 * @param str the String to center, may be null 611 * @param size the int size of new String, negative treated as zero 612 * @param padChar the character to pad the new String with 613 * @return centered String, {@code null} if null String input 614 * @since 2.0 615 */ 616 public static String center(String str, final int size, final char padChar) { 617 if (str == null || size <= 0) { 618 return str; 619 } 620 final int strLen = str.length(); 621 final int pads = size - strLen; 622 if (pads <= 0) { 623 return str; 624 } 625 str = leftPad(str, strLen + pads / 2, padChar); 626 str = rightPad(str, size, padChar); 627 return str; 628 } 629 630 /** 631 * Centers a String in a larger String of size {@code size}. 632 * Uses a supplied String as the value to pad the String with. 633 * 634 * <p>If the size is less than the String length, the String is returned. 635 * A {@code null} String returns {@code null}. 636 * A negative size is treated as zero.</p> 637 * 638 * <pre> 639 * StringUtils.center(null, *, *) = null 640 * StringUtils.center("", 4, " ") = " " 641 * StringUtils.center("ab", -1, " ") = "ab" 642 * StringUtils.center("ab", 4, " ") = " ab " 643 * StringUtils.center("abcd", 2, " ") = "abcd" 644 * StringUtils.center("a", 4, " ") = " a " 645 * StringUtils.center("a", 4, "yz") = "yayz" 646 * StringUtils.center("abc", 7, null) = " abc " 647 * StringUtils.center("abc", 7, "") = " abc " 648 * </pre> 649 * 650 * @param str the String to center, may be null 651 * @param size the int size of new String, negative treated as zero 652 * @param padStr the String to pad the new String with, must not be null or empty 653 * @return centered String, {@code null} if null String input 654 * @throws IllegalArgumentException if padStr is {@code null} or empty 655 */ 656 public static String center(String str, final int size, String padStr) { 657 if (str == null || size <= 0) { 658 return str; 659 } 660 if (isEmpty(padStr)) { 661 padStr = SPACE; 662 } 663 final int strLen = str.length(); 664 final int pads = size - strLen; 665 if (pads <= 0) { 666 return str; 667 } 668 str = leftPad(str, strLen + pads / 2, padStr); 669 str = rightPad(str, size, padStr); 670 return str; 671 } 672 673 /** 674 * Removes one newline from end of a String if it's there, 675 * otherwise leave it alone. A newline is "{@code \n}", 676 * "{@code \r}", or "{@code \r\n}". 677 * 678 * <p>NOTE: This method changed in 2.0. 679 * It now more closely matches Perl chomp.</p> 680 * 681 * <pre> 682 * StringUtils.chomp(null) = null 683 * StringUtils.chomp("") = "" 684 * StringUtils.chomp("abc \r") = "abc " 685 * StringUtils.chomp("abc\n") = "abc" 686 * StringUtils.chomp("abc\r\n") = "abc" 687 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 688 * StringUtils.chomp("abc\n\r") = "abc\n" 689 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 690 * StringUtils.chomp("\r") = "" 691 * StringUtils.chomp("\n") = "" 692 * StringUtils.chomp("\r\n") = "" 693 * </pre> 694 * 695 * @param str the String to chomp a newline from, may be null 696 * @return String without newline, {@code null} if null String input 697 */ 698 public static String chomp(final String str) { 699 if (isEmpty(str)) { 700 return str; 701 } 702 703 if (str.length() == 1) { 704 final char ch = str.charAt(0); 705 if (ch == CharUtils.CR || ch == CharUtils.LF) { 706 return EMPTY; 707 } 708 return str; 709 } 710 711 int lastIdx = str.length() - 1; 712 final char last = str.charAt(lastIdx); 713 714 if (last == CharUtils.LF) { 715 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 716 lastIdx--; 717 } 718 } else if (last != CharUtils.CR) { 719 lastIdx++; 720 } 721 return str.substring(0, lastIdx); 722 } 723 724 /** 725 * Removes {@code separator} from the end of 726 * {@code str} if it's there, otherwise leave it alone. 727 * 728 * <p>NOTE: This method changed in version 2.0. 729 * It now more closely matches Perl chomp. 730 * For the previous behavior, use {@link #substringBeforeLast(String, String)}. 731 * This method uses {@link String#endsWith(String)}.</p> 732 * 733 * <pre> 734 * StringUtils.chomp(null, *) = null 735 * StringUtils.chomp("", *) = "" 736 * StringUtils.chomp("foobar", "bar") = "foo" 737 * StringUtils.chomp("foobar", "baz") = "foobar" 738 * StringUtils.chomp("foo", "foo") = "" 739 * StringUtils.chomp("foo ", "foo") = "foo " 740 * StringUtils.chomp(" foo", "foo") = " " 741 * StringUtils.chomp("foo", "foooo") = "foo" 742 * StringUtils.chomp("foo", "") = "foo" 743 * StringUtils.chomp("foo", null) = "foo" 744 * </pre> 745 * 746 * @param str the String to chomp from, may be null 747 * @param separator separator String, may be null 748 * @return String without trailing separator, {@code null} if null String input 749 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead 750 */ 751 @Deprecated 752 public static String chomp(final String str, final String separator) { 753 return removeEnd(str, separator); 754 } 755 756 /** 757 * Remove the last character from a String. 758 * 759 * <p>If the String ends in {@code \r\n}, then remove both 760 * of them.</p> 761 * 762 * <pre> 763 * StringUtils.chop(null) = null 764 * StringUtils.chop("") = "" 765 * StringUtils.chop("abc \r") = "abc " 766 * StringUtils.chop("abc\n") = "abc" 767 * StringUtils.chop("abc\r\n") = "abc" 768 * StringUtils.chop("abc") = "ab" 769 * StringUtils.chop("abc\nabc") = "abc\nab" 770 * StringUtils.chop("a") = "" 771 * StringUtils.chop("\r") = "" 772 * StringUtils.chop("\n") = "" 773 * StringUtils.chop("\r\n") = "" 774 * </pre> 775 * 776 * @param str the String to chop last character from, may be null 777 * @return String without last character, {@code null} if null String input 778 */ 779 public static String chop(final String str) { 780 if (str == null) { 781 return null; 782 } 783 final int strLen = str.length(); 784 if (strLen < 2) { 785 return EMPTY; 786 } 787 final int lastIdx = strLen - 1; 788 final String ret = str.substring(0, lastIdx); 789 final char last = str.charAt(lastIdx); 790 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 791 return ret.substring(0, lastIdx - 1); 792 } 793 return ret; 794 } 795 796 /** 797 * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 798 * <ul> 799 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 800 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 801 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 802 * </ul> 803 * 804 * <p>This is a {@code null} safe version of :</p> 805 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 806 * 807 * <p>{@code null} value is considered less than non-{@code null} value. 808 * Two {@code null} references are considered equal.</p> 809 * 810 * <pre> 811 * StringUtils.compare(null, null) = 0 812 * StringUtils.compare(null , "a") < 0 813 * StringUtils.compare("a", null) > 0 814 * StringUtils.compare("abc", "abc") = 0 815 * StringUtils.compare("a", "b") < 0 816 * StringUtils.compare("b", "a") > 0 817 * StringUtils.compare("a", "B") > 0 818 * StringUtils.compare("ab", "abc") < 0 819 * </pre> 820 * 821 * @see #compare(String, String, boolean) 822 * @see String#compareTo(String) 823 * @param str1 the String to compare from 824 * @param str2 the String to compare to 825 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2} 826 * @since 3.5 827 */ 828 public static int compare(final String str1, final String str2) { 829 return compare(str1, str2, true); 830 } 831 832 /** 833 * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 834 * <ul> 835 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 836 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 837 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 838 * </ul> 839 * 840 * <p>This is a {@code null} safe version of :</p> 841 * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> 842 * 843 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 844 * Two {@code null} references are considered equal.</p> 845 * 846 * <pre> 847 * StringUtils.compare(null, null, *) = 0 848 * StringUtils.compare(null , "a", true) < 0 849 * StringUtils.compare(null , "a", false) > 0 850 * StringUtils.compare("a", null, true) > 0 851 * StringUtils.compare("a", null, false) < 0 852 * StringUtils.compare("abc", "abc", *) = 0 853 * StringUtils.compare("a", "b", *) < 0 854 * StringUtils.compare("b", "a", *) > 0 855 * StringUtils.compare("a", "B", *) > 0 856 * StringUtils.compare("ab", "abc", *) < 0 857 * </pre> 858 * 859 * @see String#compareTo(String) 860 * @param str1 the String to compare from 861 * @param str2 the String to compare to 862 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 863 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2} 864 * @since 3.5 865 */ 866 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 867 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 868 return 0; 869 } 870 if (str1 == null) { 871 return nullIsLess ? -1 : 1; 872 } 873 if (str2 == null) { 874 return nullIsLess ? 1 : - 1; 875 } 876 return str1.compareTo(str2); 877 } 878 879 /** 880 * Compare two Strings lexicographically, ignoring case differences, 881 * as per {@link String#compareToIgnoreCase(String)}, returning : 882 * <ul> 883 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 884 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 885 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 886 * </ul> 887 * 888 * <p>This is a {@code null} safe version of :</p> 889 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 890 * 891 * <p>{@code null} value is considered less than non-{@code null} value. 892 * Two {@code null} references are considered equal. 893 * Comparison is case insensitive.</p> 894 * 895 * <pre> 896 * StringUtils.compareIgnoreCase(null, null) = 0 897 * StringUtils.compareIgnoreCase(null , "a") < 0 898 * StringUtils.compareIgnoreCase("a", null) > 0 899 * StringUtils.compareIgnoreCase("abc", "abc") = 0 900 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 901 * StringUtils.compareIgnoreCase("a", "b") < 0 902 * StringUtils.compareIgnoreCase("b", "a") > 0 903 * StringUtils.compareIgnoreCase("a", "B") < 0 904 * StringUtils.compareIgnoreCase("A", "b") < 0 905 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 906 * </pre> 907 * 908 * @see #compareIgnoreCase(String, String, boolean) 909 * @see String#compareToIgnoreCase(String) 910 * @param str1 the String to compare from 911 * @param str2 the String to compare to 912 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 913 * ignoring case differences. 914 * @since 3.5 915 */ 916 public static int compareIgnoreCase(final String str1, final String str2) { 917 return compareIgnoreCase(str1, str2, true); 918 } 919 920 /** 921 * Compare two Strings lexicographically, ignoring case differences, 922 * as per {@link String#compareToIgnoreCase(String)}, returning : 923 * <ul> 924 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 925 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 926 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 927 * </ul> 928 * 929 * <p>This is a {@code null} safe version of :</p> 930 * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> 931 * 932 * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. 933 * Two {@code null} references are considered equal. 934 * Comparison is case insensitive.</p> 935 * 936 * <pre> 937 * StringUtils.compareIgnoreCase(null, null, *) = 0 938 * StringUtils.compareIgnoreCase(null , "a", true) < 0 939 * StringUtils.compareIgnoreCase(null , "a", false) > 0 940 * StringUtils.compareIgnoreCase("a", null, true) > 0 941 * StringUtils.compareIgnoreCase("a", null, false) < 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 * @see String#compareToIgnoreCase(String) 952 * @param str1 the String to compare from 953 * @param str2 the String to compare to 954 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value 955 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, 956 * ignoring case differences. 957 * @since 3.5 958 */ 959 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 960 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 961 return 0; 962 } 963 if (str1 == null) { 964 return nullIsLess ? -1 : 1; 965 } 966 if (str2 == null) { 967 return nullIsLess ? 1 : - 1; 968 } 969 return str1.compareToIgnoreCase(str2); 970 } 971 972 /** 973 * Checks if CharSequence contains a search CharSequence, handling {@code null}. 974 * This method uses {@link String#indexOf(String)} if possible. 975 * 976 * <p>A {@code null} CharSequence will return {@code false}.</p> 977 * 978 * <pre> 979 * StringUtils.contains(null, *) = false 980 * StringUtils.contains(*, null) = false 981 * StringUtils.contains("", "") = true 982 * StringUtils.contains("abc", "") = true 983 * StringUtils.contains("abc", "a") = true 984 * StringUtils.contains("abc", "z") = false 985 * </pre> 986 * 987 * @param seq the CharSequence to check, may be null 988 * @param searchSeq the CharSequence to find, may be null 989 * @return true if the CharSequence contains the search CharSequence, 990 * false if not or {@code null} string input 991 * @since 2.0 992 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 993 */ 994 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 995 if (seq == null || searchSeq == null) { 996 return false; 997 } 998 return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0; 999 } 1000 1001 /** 1002 * Checks if CharSequence contains a search character, handling {@code null}. 1003 * This method uses {@link String#indexOf(int)} if possible. 1004 * 1005 * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p> 1006 * 1007 * <pre> 1008 * StringUtils.contains(null, *) = false 1009 * StringUtils.contains("", *) = false 1010 * StringUtils.contains("abc", 'a') = true 1011 * StringUtils.contains("abc", 'z') = false 1012 * </pre> 1013 * 1014 * @param seq the CharSequence to check, may be null 1015 * @param searchChar the character to find 1016 * @return true if the CharSequence contains the search character, 1017 * false if not or {@code null} string input 1018 * @since 2.0 1019 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1020 */ 1021 public static boolean contains(final CharSequence seq, final int searchChar) { 1022 if (isEmpty(seq)) { 1023 return false; 1024 } 1025 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1026 } 1027 1028 /** 1029 * Checks if the CharSequence contains any character in the given 1030 * set of characters. 1031 * 1032 * <p>A {@code null} CharSequence will return {@code false}. 1033 * A {@code null} or zero length search array will return {@code false}.</p> 1034 * 1035 * <pre> 1036 * StringUtils.containsAny(null, *) = false 1037 * StringUtils.containsAny("", *) = false 1038 * StringUtils.containsAny(*, null) = false 1039 * StringUtils.containsAny(*, []) = false 1040 * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true 1041 * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true 1042 * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true 1043 * StringUtils.containsAny("aba", ['z']) = false 1044 * </pre> 1045 * 1046 * @param cs the CharSequence to check, may be null 1047 * @param searchChars the chars to search for, may be null 1048 * @return the {@code true} if any of the chars are found, 1049 * {@code false} if no match or null input 1050 * @since 2.4 1051 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1052 */ 1053 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1054 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1055 return false; 1056 } 1057 final int csLength = cs.length(); 1058 final int searchLength = searchChars.length; 1059 final int csLast = csLength - 1; 1060 final int searchLast = searchLength - 1; 1061 for (int i = 0; i < csLength; i++) { 1062 final char ch = cs.charAt(i); 1063 for (int j = 0; j < searchLength; j++) { 1064 if (searchChars[j] == ch) { 1065 if (!Character.isHighSurrogate(ch)) { 1066 // ch is in the Basic Multilingual Plane 1067 return true; 1068 } 1069 if (j == searchLast) { 1070 // missing low surrogate, fine, like String.indexOf(String) 1071 return true; 1072 } 1073 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1074 return true; 1075 } 1076 } 1077 } 1078 } 1079 return false; 1080 } 1081 1082 /** 1083 * Checks if the CharSequence contains any character in the given set of characters. 1084 * 1085 * <p> 1086 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return 1087 * {@code false}. 1088 * </p> 1089 * 1090 * <pre> 1091 * StringUtils.containsAny(null, *) = false 1092 * StringUtils.containsAny("", *) = false 1093 * StringUtils.containsAny(*, null) = false 1094 * StringUtils.containsAny(*, "") = false 1095 * StringUtils.containsAny("zzabyycdxx", "za") = true 1096 * StringUtils.containsAny("zzabyycdxx", "by") = true 1097 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1098 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1099 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1100 * StringUtils.containsAny("aba", "z") = false 1101 * </pre> 1102 * 1103 * @param cs 1104 * the CharSequence to check, may be null 1105 * @param searchChars 1106 * the chars to search for, may be null 1107 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input 1108 * @since 2.4 1109 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1110 */ 1111 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1112 if (searchChars == null) { 1113 return false; 1114 } 1115 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1116 } 1117 1118 /** 1119 * Checks if the CharSequence contains any of the CharSequences in the given array. 1120 * 1121 * <p> 1122 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1123 * return {@code false}. 1124 * </p> 1125 * 1126 * <pre> 1127 * StringUtils.containsAny(null, *) = false 1128 * StringUtils.containsAny("", *) = false 1129 * StringUtils.containsAny(*, null) = false 1130 * StringUtils.containsAny(*, []) = false 1131 * StringUtils.containsAny("abcd", "ab", null) = true 1132 * StringUtils.containsAny("abcd", "ab", "cd") = true 1133 * StringUtils.containsAny("abc", "d", "abc") = true 1134 * </pre> 1135 * 1136 * @param cs The CharSequence to check, may be null 1137 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1138 * null as well. 1139 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1140 * @since 3.4 1141 */ 1142 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1143 return containsAny(StringUtils::contains, cs, searchCharSequences); 1144 } 1145 1146 /** 1147 * Checks if the CharSequence contains any of the CharSequences in the given array. 1148 * 1149 * <p> 1150 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1151 * return {@code false}. 1152 * </p> 1153 * 1154 * @param cs The CharSequence to check, may be null 1155 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1156 * null as well. 1157 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1158 * @since 3.12.0 1159 */ 1160 private static boolean containsAny(final ToBooleanBiFunction<CharSequence, CharSequence> test, 1161 final CharSequence cs, final CharSequence... searchCharSequences) { 1162 if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) { 1163 return false; 1164 } 1165 for (final CharSequence searchCharSequence : searchCharSequences) { 1166 if (test.applyAsBoolean(cs, searchCharSequence)) { 1167 return true; 1168 } 1169 } 1170 return false; 1171 } 1172 1173 /** 1174 * Checks if the CharSequence contains any of the CharSequences in the given array, ignoring case. 1175 * 1176 * <p> 1177 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1178 * return {@code false}. 1179 * </p> 1180 * 1181 * <pre> 1182 * StringUtils.containsAny(null, *) = false 1183 * StringUtils.containsAny("", *) = false 1184 * StringUtils.containsAny(*, null) = false 1185 * StringUtils.containsAny(*, []) = false 1186 * StringUtils.containsAny("abcd", "ab", null) = true 1187 * StringUtils.containsAny("abcd", "ab", "cd") = true 1188 * StringUtils.containsAny("abc", "d", "abc") = true 1189 * StringUtils.containsAny("abc", "D", "ABC") = true 1190 * StringUtils.containsAny("ABC", "d", "abc") = true 1191 * </pre> 1192 * 1193 * @param cs The CharSequence to check, may be null 1194 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1195 * null as well. 1196 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1197 * @since 3.12.0 1198 */ 1199 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) { 1200 return containsAny(StringUtils::containsIgnoreCase, cs, searchCharSequences); 1201 } 1202 1203 /** 1204 * Checks if CharSequence contains a search CharSequence irrespective of case, 1205 * handling {@code null}. Case-insensitivity is defined as by 1206 * {@link String#equalsIgnoreCase(String)}. 1207 * 1208 * <p>A {@code null} CharSequence will return {@code false}. 1209 * 1210 * <pre> 1211 * StringUtils.containsIgnoreCase(null, *) = false 1212 * StringUtils.containsIgnoreCase(*, null) = false 1213 * StringUtils.containsIgnoreCase("", "") = true 1214 * StringUtils.containsIgnoreCase("abc", "") = true 1215 * StringUtils.containsIgnoreCase("abc", "a") = true 1216 * StringUtils.containsIgnoreCase("abc", "z") = false 1217 * StringUtils.containsIgnoreCase("abc", "A") = true 1218 * StringUtils.containsIgnoreCase("abc", "Z") = false 1219 * </pre> 1220 * 1221 * @param str the CharSequence to check, may be null 1222 * @param searchStr the CharSequence to find, may be null 1223 * @return true if the CharSequence contains the search CharSequence irrespective of 1224 * case or false if not or {@code null} string input 1225 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence) 1226 */ 1227 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1228 if (str == null || searchStr == null) { 1229 return false; 1230 } 1231 final int len = searchStr.length(); 1232 final int max = str.length() - len; 1233 for (int i = 0; i <= max; i++) { 1234 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) { 1235 return true; 1236 } 1237 } 1238 return false; 1239 } 1240 1241 /** 1242 * Checks that the CharSequence does not contain certain characters. 1243 * 1244 * <p>A {@code null} CharSequence will return {@code true}. 1245 * A {@code null} invalid character array will return {@code true}. 1246 * An empty CharSequence (length()=0) always returns true.</p> 1247 * 1248 * <pre> 1249 * StringUtils.containsNone(null, *) = true 1250 * StringUtils.containsNone(*, null) = true 1251 * StringUtils.containsNone("", *) = true 1252 * StringUtils.containsNone("ab", '') = true 1253 * StringUtils.containsNone("abab", 'xyz') = true 1254 * StringUtils.containsNone("ab1", 'xyz') = true 1255 * StringUtils.containsNone("abz", 'xyz') = false 1256 * </pre> 1257 * 1258 * @param cs the CharSequence to check, may be null 1259 * @param searchChars an array of invalid chars, may be null 1260 * @return true if it contains none of the invalid chars, or is null 1261 * @since 2.0 1262 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1263 */ 1264 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1265 if (cs == null || searchChars == null) { 1266 return true; 1267 } 1268 final int csLen = cs.length(); 1269 final int csLast = csLen - 1; 1270 final int searchLen = searchChars.length; 1271 final int searchLast = searchLen - 1; 1272 for (int i = 0; i < csLen; i++) { 1273 final char ch = cs.charAt(i); 1274 for (int j = 0; j < searchLen; j++) { 1275 if (searchChars[j] == ch) { 1276 if (!Character.isHighSurrogate(ch)) { 1277 // ch is in the Basic Multilingual Plane 1278 return false; 1279 } 1280 if (j == searchLast) { 1281 // missing low surrogate, fine, like String.indexOf(String) 1282 return false; 1283 } 1284 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1285 return false; 1286 } 1287 } 1288 } 1289 } 1290 return true; 1291 } 1292 1293 /** 1294 * Checks that the CharSequence does not contain certain characters. 1295 * 1296 * <p>A {@code null} CharSequence will return {@code true}. 1297 * A {@code null} invalid character array will return {@code true}. 1298 * An empty String ("") always returns true.</p> 1299 * 1300 * <pre> 1301 * StringUtils.containsNone(null, *) = true 1302 * StringUtils.containsNone(*, null) = true 1303 * StringUtils.containsNone("", *) = true 1304 * StringUtils.containsNone("ab", "") = true 1305 * StringUtils.containsNone("abab", "xyz") = true 1306 * StringUtils.containsNone("ab1", "xyz") = true 1307 * StringUtils.containsNone("abz", "xyz") = false 1308 * </pre> 1309 * 1310 * @param cs the CharSequence to check, may be null 1311 * @param invalidChars a String of invalid chars, may be null 1312 * @return true if it contains none of the invalid chars, or is null 1313 * @since 2.0 1314 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1315 */ 1316 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1317 if (invalidChars == null) { 1318 return true; 1319 } 1320 return containsNone(cs, invalidChars.toCharArray()); 1321 } 1322 1323 /** 1324 * Checks if the CharSequence contains only certain characters. 1325 * 1326 * <p>A {@code null} CharSequence will return {@code false}. 1327 * A {@code null} valid character array will return {@code false}. 1328 * An empty CharSequence (length()=0) always returns {@code true}.</p> 1329 * 1330 * <pre> 1331 * StringUtils.containsOnly(null, *) = false 1332 * StringUtils.containsOnly(*, null) = false 1333 * StringUtils.containsOnly("", *) = true 1334 * StringUtils.containsOnly("ab", '') = false 1335 * StringUtils.containsOnly("abab", 'abc') = true 1336 * StringUtils.containsOnly("ab1", 'abc') = false 1337 * StringUtils.containsOnly("abz", 'abc') = false 1338 * </pre> 1339 * 1340 * @param cs the String to check, may be null 1341 * @param valid an array of valid chars, may be null 1342 * @return true if it only contains valid chars and is non-null 1343 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1344 */ 1345 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1346 // All these pre-checks are to maintain API with an older version 1347 if (valid == null || cs == null) { 1348 return false; 1349 } 1350 if (cs.length() == 0) { 1351 return true; 1352 } 1353 if (valid.length == 0) { 1354 return false; 1355 } 1356 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1357 } 1358 1359 /** 1360 * Checks if the CharSequence contains only certain characters. 1361 * 1362 * <p>A {@code null} CharSequence will return {@code false}. 1363 * A {@code null} valid character String will return {@code false}. 1364 * An empty String (length()=0) always returns {@code true}.</p> 1365 * 1366 * <pre> 1367 * StringUtils.containsOnly(null, *) = false 1368 * StringUtils.containsOnly(*, null) = false 1369 * StringUtils.containsOnly("", *) = true 1370 * StringUtils.containsOnly("ab", "") = false 1371 * StringUtils.containsOnly("abab", "abc") = true 1372 * StringUtils.containsOnly("ab1", "abc") = false 1373 * StringUtils.containsOnly("abz", "abc") = false 1374 * </pre> 1375 * 1376 * @param cs the CharSequence to check, may be null 1377 * @param validChars a String of valid chars, may be null 1378 * @return true if it only contains valid chars and is non-null 1379 * @since 2.0 1380 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1381 */ 1382 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1383 if (cs == null || validChars == null) { 1384 return false; 1385 } 1386 return containsOnly(cs, validChars.toCharArray()); 1387 } 1388 1389 /** 1390 * Check whether the given CharSequence contains any whitespace characters. 1391 * 1392 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1393 * 1394 * @param seq the CharSequence to check (may be {@code null}) 1395 * @return {@code true} if the CharSequence is not empty and 1396 * contains at least 1 (breaking) whitespace character 1397 * @since 3.0 1398 */ 1399 // From org.springframework.util.StringUtils, under Apache License 2.0 1400 public static boolean containsWhitespace(final CharSequence seq) { 1401 if (isEmpty(seq)) { 1402 return false; 1403 } 1404 final int strLen = seq.length(); 1405 for (int i = 0; i < strLen; i++) { 1406 if (Character.isWhitespace(seq.charAt(i))) { 1407 return true; 1408 } 1409 } 1410 return false; 1411 } 1412 1413 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1414 for (int i = 0; i < decomposed.length(); i++) { 1415 if (decomposed.charAt(i) == '\u0141') { 1416 decomposed.setCharAt(i, 'L'); 1417 } else if (decomposed.charAt(i) == '\u0142') { 1418 decomposed.setCharAt(i, 'l'); 1419 } 1420 } 1421 } 1422 1423 /** 1424 * Counts how many times the char appears in the given string. 1425 * 1426 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1427 * 1428 * <pre> 1429 * StringUtils.countMatches(null, *) = 0 1430 * StringUtils.countMatches("", *) = 0 1431 * StringUtils.countMatches("abba", 0) = 0 1432 * StringUtils.countMatches("abba", 'a') = 2 1433 * StringUtils.countMatches("abba", 'b') = 2 1434 * StringUtils.countMatches("abba", 'x') = 0 1435 * </pre> 1436 * 1437 * @param str the CharSequence to check, may be null 1438 * @param ch the char to count 1439 * @return the number of occurrences, 0 if the CharSequence is {@code null} 1440 * @since 3.4 1441 */ 1442 public static int countMatches(final CharSequence str, final char ch) { 1443 if (isEmpty(str)) { 1444 return 0; 1445 } 1446 int count = 0; 1447 // We could also call str.toCharArray() for faster lookups but that would generate more garbage. 1448 for (int i = 0; i < str.length(); i++) { 1449 if (ch == str.charAt(i)) { 1450 count++; 1451 } 1452 } 1453 return count; 1454 } 1455 1456 /** 1457 * Counts how many times the substring appears in the larger string. 1458 * Note that the code only counts non-overlapping matches. 1459 * 1460 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 1461 * 1462 * <pre> 1463 * StringUtils.countMatches(null, *) = 0 1464 * StringUtils.countMatches("", *) = 0 1465 * StringUtils.countMatches("abba", null) = 0 1466 * StringUtils.countMatches("abba", "") = 0 1467 * StringUtils.countMatches("abba", "a") = 2 1468 * StringUtils.countMatches("abba", "ab") = 1 1469 * StringUtils.countMatches("abba", "xxx") = 0 1470 * StringUtils.countMatches("ababa", "aba") = 1 1471 * </pre> 1472 * 1473 * @param str the CharSequence to check, may be null 1474 * @param sub the substring to count, may be null 1475 * @return the number of occurrences, 0 if either CharSequence is {@code null} 1476 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1477 */ 1478 public static int countMatches(final CharSequence str, final CharSequence sub) { 1479 if (isEmpty(str) || isEmpty(sub)) { 1480 return 0; 1481 } 1482 int count = 0; 1483 int idx = 0; 1484 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1485 count++; 1486 idx += sub.length(); 1487 } 1488 return count; 1489 } 1490 1491 /** 1492 * Returns either the passed in CharSequence, or if the CharSequence is 1493 * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}. 1494 * 1495 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1496 * 1497 * <pre> 1498 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1499 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1500 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1501 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1502 * StringUtils.defaultIfBlank("", null) = null 1503 * </pre> 1504 * @param <T> the specific kind of CharSequence 1505 * @param str the CharSequence to check, may be null 1506 * @param defaultStr the default CharSequence to return 1507 * if the input is whitespace, empty ("") or {@code null}, may be null 1508 * @return the passed in CharSequence, or the default 1509 * @see StringUtils#defaultString(String, String) 1510 */ 1511 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1512 return isBlank(str) ? defaultStr : str; 1513 } 1514 1515 /** 1516 * Returns either the passed in CharSequence, or if the CharSequence is 1517 * empty or {@code null}, the value of {@code defaultStr}. 1518 * 1519 * <pre> 1520 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1521 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1522 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1523 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1524 * StringUtils.defaultIfEmpty("", null) = null 1525 * </pre> 1526 * @param <T> the specific kind of CharSequence 1527 * @param str the CharSequence to check, may be null 1528 * @param defaultStr the default CharSequence to return 1529 * if the input is empty ("") or {@code null}, may be null 1530 * @return the passed in CharSequence, or the default 1531 * @see StringUtils#defaultString(String, String) 1532 */ 1533 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1534 return isEmpty(str) ? defaultStr : str; 1535 } 1536 1537 /** 1538 * Returns either the passed in String, 1539 * or if the String is {@code null}, an empty String (""). 1540 * 1541 * <pre> 1542 * StringUtils.defaultString(null) = "" 1543 * StringUtils.defaultString("") = "" 1544 * StringUtils.defaultString("bat") = "bat" 1545 * </pre> 1546 * 1547 * @see Objects#toString(Object, String) 1548 * @see String#valueOf(Object) 1549 * @param str the String to check, may be null 1550 * @return the passed in String, or the empty String if it 1551 * was {@code null} 1552 */ 1553 public static String defaultString(final String str) { 1554 return Objects.toString(str, EMPTY); 1555 } 1556 1557 /** 1558 * Returns either the given String, or if the String is 1559 * {@code null}, {@code nullDefault}. 1560 * 1561 * <pre> 1562 * StringUtils.defaultString(null, "NULL") = "NULL" 1563 * StringUtils.defaultString("", "NULL") = "" 1564 * StringUtils.defaultString("bat", "NULL") = "bat" 1565 * </pre> 1566 * <p> 1567 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}: 1568 * </p> 1569 * <pre> 1570 * Objects.toString(null, "NULL") = "NULL" 1571 * Objects.toString("", "NULL") = "" 1572 * Objects.toString("bat", "NULL") = "bat" 1573 * </pre> 1574 * 1575 * @see Objects#toString(Object, String) 1576 * @see String#valueOf(Object) 1577 * @param str the String to check, may be null 1578 * @param nullDefault the default String to return 1579 * if the input is {@code null}, may be null 1580 * @return the passed in String, or the default if it was {@code null} 1581 * @deprecated Use {@link Objects#toString(Object, String)} 1582 */ 1583 @Deprecated 1584 public static String defaultString(final String str, final String nullDefault) { 1585 return Objects.toString(str, nullDefault); 1586 } 1587 1588 /** 1589 * Deletes all whitespaces from a String as defined by 1590 * {@link Character#isWhitespace(char)}. 1591 * 1592 * <pre> 1593 * StringUtils.deleteWhitespace(null) = null 1594 * StringUtils.deleteWhitespace("") = "" 1595 * StringUtils.deleteWhitespace("abc") = "abc" 1596 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1597 * </pre> 1598 * 1599 * @param str the String to delete whitespace from, may be null 1600 * @return the String without whitespaces, {@code null} if null String input 1601 */ 1602 public static String deleteWhitespace(final String str) { 1603 if (isEmpty(str)) { 1604 return str; 1605 } 1606 final int sz = str.length(); 1607 final char[] chs = new char[sz]; 1608 int count = 0; 1609 for (int i = 0; i < sz; i++) { 1610 if (!Character.isWhitespace(str.charAt(i))) { 1611 chs[count++] = str.charAt(i); 1612 } 1613 } 1614 if (count == sz) { 1615 return str; 1616 } 1617 if (count == 0) { 1618 return EMPTY; 1619 } 1620 return new String(chs, 0, count); 1621 } 1622 1623 /** 1624 * Compares two Strings, and returns the portion where they differ. 1625 * More precisely, return the remainder of the second String, 1626 * starting from where it's different from the first. This means that 1627 * the difference between "abc" and "ab" is the empty String and not "c". 1628 * 1629 * <p>For example, 1630 * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p> 1631 * 1632 * <pre> 1633 * StringUtils.difference(null, null) = null 1634 * StringUtils.difference("", "") = "" 1635 * StringUtils.difference("", "abc") = "abc" 1636 * StringUtils.difference("abc", "") = "" 1637 * StringUtils.difference("abc", "abc") = "" 1638 * StringUtils.difference("abc", "ab") = "" 1639 * StringUtils.difference("ab", "abxyz") = "xyz" 1640 * StringUtils.difference("abcde", "abxyz") = "xyz" 1641 * StringUtils.difference("abcde", "xyz") = "xyz" 1642 * </pre> 1643 * 1644 * @param str1 the first String, may be null 1645 * @param str2 the second String, may be null 1646 * @return the portion of str2 where it differs from str1; returns the 1647 * empty String if they are equal 1648 * @see #indexOfDifference(CharSequence,CharSequence) 1649 * @since 2.0 1650 */ 1651 public static String difference(final String str1, final String str2) { 1652 if (str1 == null) { 1653 return str2; 1654 } 1655 if (str2 == null) { 1656 return str1; 1657 } 1658 final int at = indexOfDifference(str1, str2); 1659 if (at == INDEX_NOT_FOUND) { 1660 return EMPTY; 1661 } 1662 return str2.substring(at); 1663 } 1664 1665 /** 1666 * Check if a CharSequence ends with a specified suffix. 1667 * 1668 * <p>{@code null}s are handled without exceptions. Two {@code null} 1669 * references are considered to be equal. The comparison is case-sensitive.</p> 1670 * 1671 * <pre> 1672 * StringUtils.endsWith(null, null) = true 1673 * StringUtils.endsWith(null, "def") = false 1674 * StringUtils.endsWith("abcdef", null) = false 1675 * StringUtils.endsWith("abcdef", "def") = true 1676 * StringUtils.endsWith("ABCDEF", "def") = false 1677 * StringUtils.endsWith("ABCDEF", "cde") = false 1678 * StringUtils.endsWith("ABCDEF", "") = true 1679 * </pre> 1680 * 1681 * @see String#endsWith(String) 1682 * @param str the CharSequence to check, may be null 1683 * @param suffix the suffix to find, may be null 1684 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or 1685 * both {@code null} 1686 * @since 2.4 1687 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1688 */ 1689 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1690 return endsWith(str, suffix, false); 1691 } 1692 1693 /** 1694 * Check if a CharSequence ends with a specified suffix (optionally case insensitive). 1695 * 1696 * @see String#endsWith(String) 1697 * @param str the CharSequence to check, may be null 1698 * @param suffix the suffix to find, may be null 1699 * @param ignoreCase indicates whether the compare should ignore case 1700 * (case-insensitive) or not. 1701 * @return {@code true} if the CharSequence starts with the prefix or 1702 * both {@code null} 1703 */ 1704 private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { 1705 if (str == null || suffix == null) { 1706 return str == suffix; 1707 } 1708 if (suffix.length() > str.length()) { 1709 return false; 1710 } 1711 final int strOffset = str.length() - suffix.length(); 1712 return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); 1713 } 1714 1715 /** 1716 * Check if a CharSequence ends with any of the provided case-sensitive suffixes. 1717 * 1718 * <pre> 1719 * StringUtils.endsWithAny(null, null) = false 1720 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1721 * StringUtils.endsWithAny("abcxyz", null) = false 1722 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1723 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1724 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1725 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1726 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1727 * </pre> 1728 * 1729 * @param sequence the CharSequence to check, may be null 1730 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null} 1731 * @see StringUtils#endsWith(CharSequence, CharSequence) 1732 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 1733 * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}. 1734 * @since 3.0 1735 */ 1736 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1737 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 1738 return false; 1739 } 1740 for (final CharSequence searchString : searchStrings) { 1741 if (endsWith(sequence, searchString)) { 1742 return true; 1743 } 1744 } 1745 return false; 1746 } 1747 1748 /** 1749 * Case insensitive check if a CharSequence ends with a specified suffix. 1750 * 1751 * <p>{@code null}s are handled without exceptions. Two {@code null} 1752 * references are considered to be equal. The comparison is case insensitive.</p> 1753 * 1754 * <pre> 1755 * StringUtils.endsWithIgnoreCase(null, null) = true 1756 * StringUtils.endsWithIgnoreCase(null, "def") = false 1757 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1758 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1759 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1760 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1761 * </pre> 1762 * 1763 * @see String#endsWith(String) 1764 * @param str the CharSequence to check, may be null 1765 * @param suffix the suffix to find, may be null 1766 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or 1767 * both {@code null} 1768 * @since 2.4 1769 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1770 */ 1771 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1772 return endsWith(str, suffix, true); 1773 } 1774 1775 /** 1776 * Compares two CharSequences, returning {@code true} if they represent 1777 * equal sequences of characters. 1778 * 1779 * <p>{@code null}s are handled without exceptions. Two {@code null} 1780 * references are considered to be equal. The comparison is <strong>case-sensitive</strong>.</p> 1781 * 1782 * <pre> 1783 * StringUtils.equals(null, null) = true 1784 * StringUtils.equals(null, "abc") = false 1785 * StringUtils.equals("abc", null) = false 1786 * StringUtils.equals("abc", "abc") = true 1787 * StringUtils.equals("abc", "ABC") = false 1788 * </pre> 1789 * 1790 * @param cs1 the first CharSequence, may be {@code null} 1791 * @param cs2 the second CharSequence, may be {@code null} 1792 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} 1793 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1794 * @see Object#equals(Object) 1795 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1796 */ 1797 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1798 if (cs1 == cs2) { 1799 return true; 1800 } 1801 if (cs1 == null || cs2 == null) { 1802 return false; 1803 } 1804 if (cs1.length() != cs2.length()) { 1805 return false; 1806 } 1807 if (cs1 instanceof String && cs2 instanceof String) { 1808 return cs1.equals(cs2); 1809 } 1810 // Step-wise comparison 1811 final int length = cs1.length(); 1812 for (int i = 0; i < length; i++) { 1813 if (cs1.charAt(i) != cs2.charAt(i)) { 1814 return false; 1815 } 1816 } 1817 return true; 1818 } 1819 1820 /** 1821 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1822 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}. 1823 * 1824 * <pre> 1825 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1826 * StringUtils.equalsAny(null, null, null) = true 1827 * StringUtils.equalsAny(null, "abc", "def") = false 1828 * StringUtils.equalsAny("abc", null, "def") = false 1829 * StringUtils.equalsAny("abc", "abc", "def") = true 1830 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1831 * </pre> 1832 * 1833 * @param string to compare, may be {@code null}. 1834 * @param searchStrings a vararg of strings, may be {@code null}. 1835 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; 1836 * {@code false} if {@code searchStrings} is null or contains no matches. 1837 * @since 3.5 1838 */ 1839 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1840 if (ArrayUtils.isNotEmpty(searchStrings)) { 1841 for (final CharSequence next : searchStrings) { 1842 if (equals(string, next)) { 1843 return true; 1844 } 1845 } 1846 } 1847 return false; 1848 } 1849 1850 /** 1851 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1852 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1853 * 1854 * <pre> 1855 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1856 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1857 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1858 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1859 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1860 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 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-insensitive) to any other element of {@code searchStrings}; 1866 * {@code false} if {@code searchStrings} is null or contains no matches. 1867 * @since 3.5 1868 */ 1869 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) { 1870 if (ArrayUtils.isNotEmpty(searchStrings)) { 1871 for (final CharSequence next : searchStrings) { 1872 if (equalsIgnoreCase(string, next)) { 1873 return true; 1874 } 1875 } 1876 } 1877 return false; 1878 } 1879 1880 /** 1881 * Compares two CharSequences, returning {@code true} if they represent 1882 * equal sequences of characters, ignoring case. 1883 * 1884 * <p>{@code null}s are handled without exceptions. Two {@code null} 1885 * references are considered equal. The comparison is <strong>case insensitive</strong>.</p> 1886 * 1887 * <pre> 1888 * StringUtils.equalsIgnoreCase(null, null) = true 1889 * StringUtils.equalsIgnoreCase(null, "abc") = false 1890 * StringUtils.equalsIgnoreCase("abc", null) = false 1891 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1892 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1893 * </pre> 1894 * 1895 * @param cs1 the first CharSequence, may be {@code null} 1896 * @param cs2 the second CharSequence, may be {@code null} 1897 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} 1898 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1899 * @see #equals(CharSequence, CharSequence) 1900 */ 1901 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1902 if (cs1 == cs2) { 1903 return true; 1904 } 1905 if (cs1 == null || cs2 == null) { 1906 return false; 1907 } 1908 if (cs1.length() != cs2.length()) { 1909 return false; 1910 } 1911 return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length()); 1912 } 1913 1914 /** 1915 * Returns the first value in the array which is not empty (""), 1916 * {@code null} or whitespace only. 1917 * 1918 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1919 * 1920 * <p>If all values are blank or the array is {@code null} 1921 * or empty then {@code null} is returned.</p> 1922 * 1923 * <pre> 1924 * StringUtils.firstNonBlank(null, null, null) = null 1925 * StringUtils.firstNonBlank(null, "", " ") = null 1926 * StringUtils.firstNonBlank("abc") = "abc" 1927 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1928 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1929 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1930 * StringUtils.firstNonBlank() = null 1931 * </pre> 1932 * 1933 * @param <T> the specific kind of CharSequence 1934 * @param values the values to test, may be {@code null} or empty 1935 * @return the first value from {@code values} which is not blank, 1936 * or {@code null} if there are no non-blank values 1937 * @since 3.8 1938 */ 1939 @SafeVarargs 1940 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1941 if (values != null) { 1942 for (final T val : values) { 1943 if (isNotBlank(val)) { 1944 return val; 1945 } 1946 } 1947 } 1948 return null; 1949 } 1950 1951 /** 1952 * Returns the first value in the array which is not empty. 1953 * 1954 * <p>If all values are empty or the array is {@code null} 1955 * or empty then {@code null} is returned.</p> 1956 * 1957 * <pre> 1958 * StringUtils.firstNonEmpty(null, null, null) = null 1959 * StringUtils.firstNonEmpty(null, null, "") = null 1960 * StringUtils.firstNonEmpty(null, "", " ") = " " 1961 * StringUtils.firstNonEmpty("abc") = "abc" 1962 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1963 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1964 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1965 * StringUtils.firstNonEmpty() = null 1966 * </pre> 1967 * 1968 * @param <T> the specific kind of CharSequence 1969 * @param values the values to test, may be {@code null} or empty 1970 * @return the first value from {@code values} which is not empty, 1971 * or {@code null} if there are no non-empty values 1972 * @since 3.8 1973 */ 1974 @SafeVarargs 1975 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1976 if (values != null) { 1977 for (final T val : values) { 1978 if (isNotEmpty(val)) { 1979 return val; 1980 } 1981 } 1982 } 1983 return null; 1984 } 1985 1986 /** 1987 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1988 * 1989 * @param string input string 1990 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 1991 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1992 * @see String#getBytes(Charset) 1993 * @since 3.10 1994 */ 1995 public static byte[] getBytes(final String string, final Charset charset) { 1996 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1997 } 1998 1999 /** 2000 * Calls {@link String#getBytes(String)} in a null-safe manner. 2001 * 2002 * @param string input string 2003 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 2004 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 2005 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 2006 * @see String#getBytes(String) 2007 * @since 3.10 2008 */ 2009 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 2010 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 2011 } 2012 2013 /** 2014 * Compares all Strings in an array and returns the initial sequence of 2015 * characters that is common to all of them. 2016 * 2017 * <p>For example, 2018 * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "}</p> 2019 * 2020 * <pre> 2021 * StringUtils.getCommonPrefix(null) = "" 2022 * StringUtils.getCommonPrefix(new String[] {}) = "" 2023 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 2024 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 2025 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 2026 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 2027 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 2028 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 2029 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 2030 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 2031 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 2032 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 2033 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 2034 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 2035 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2036 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2037 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2038 * </pre> 2039 * 2040 * @param strs array of String objects, entries may be null 2041 * @return the initial sequence of characters that are common to all Strings 2042 * in the array; empty String if the array is null, the elements are all null 2043 * or if there is no common prefix. 2044 * @since 2.4 2045 */ 2046 public static String getCommonPrefix(final String... strs) { 2047 if (ArrayUtils.isEmpty(strs)) { 2048 return EMPTY; 2049 } 2050 final int smallestIndexOfDiff = indexOfDifference(strs); 2051 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2052 // all strings were identical 2053 if (strs[0] == null) { 2054 return EMPTY; 2055 } 2056 return strs[0]; 2057 } 2058 if (smallestIndexOfDiff == 0) { 2059 // there were no common initial characters 2060 return EMPTY; 2061 } 2062 // we found a common initial character sequence 2063 return strs[0].substring(0, smallestIndexOfDiff); 2064 } 2065 2066 /** 2067 * Checks if a String {@code str} contains Unicode digits, 2068 * if yes then concatenate all the digits in {@code str} and return it as a String. 2069 * 2070 * <p>An empty ("") String will be returned if no digits found in {@code str}.</p> 2071 * 2072 * <pre> 2073 * StringUtils.getDigits(null) = null 2074 * StringUtils.getDigits("") = "" 2075 * StringUtils.getDigits("abc") = "" 2076 * StringUtils.getDigits("1000$") = "1000" 2077 * StringUtils.getDigits("1123~45") = "112345" 2078 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2079 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2080 * </pre> 2081 * 2082 * @param str the String to extract digits from, may be null 2083 * @return String with only digits, 2084 * or an empty ("") String if no digits found, 2085 * or {@code null} String if {@code str} is null 2086 * @since 3.6 2087 */ 2088 public static String getDigits(final String str) { 2089 if (isEmpty(str)) { 2090 return str; 2091 } 2092 final int sz = str.length(); 2093 final StringBuilder strDigits = new StringBuilder(sz); 2094 for (int i = 0; i < sz; i++) { 2095 final char tempChar = str.charAt(i); 2096 if (Character.isDigit(tempChar)) { 2097 strDigits.append(tempChar); 2098 } 2099 } 2100 return strDigits.toString(); 2101 } 2102 2103 /** 2104 * Find the Fuzzy Distance which indicates the similarity score between two Strings. 2105 * 2106 * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text, 2107 * TextMate, Atom and others. One point is given for every matched character. Subsequent 2108 * matches yield two bonus points. A higher score indicates a higher similarity.</p> 2109 * 2110 * <pre> 2111 * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException 2112 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2113 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2114 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2115 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2116 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2117 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2118 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2119 * </pre> 2120 * 2121 * @param term a full term that should be matched against, must not be null 2122 * @param query the query that will be matched against a term, must not be null 2123 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize 2124 * both Strings to lower case. 2125 * @return result score 2126 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null} 2127 * @since 3.4 2128 * @deprecated As of 3.6, use Apache Commons Text 2129 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2130 * FuzzyScore</a> instead 2131 */ 2132 @Deprecated 2133 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2134 if (term == null || query == null) { 2135 throw new IllegalArgumentException("Strings must not be null"); 2136 } 2137 if (locale == null) { 2138 throw new IllegalArgumentException("Locale must not be null"); 2139 } 2140 2141 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2142 // case right from the start. Turning characters to lower case 2143 // via Character.toLowerCase(char) is unfortunately insufficient 2144 // as it does not accept a locale. 2145 final String termLowerCase = term.toString().toLowerCase(locale); 2146 final String queryLowerCase = query.toString().toLowerCase(locale); 2147 2148 // the resulting score 2149 int score = 0; 2150 2151 // the position in the term which will be scanned next for potential 2152 // query character matches 2153 int termIndex = 0; 2154 2155 // index of the previously matched character in the term 2156 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2157 2158 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2159 final char queryChar = queryLowerCase.charAt(queryIndex); 2160 2161 boolean termCharacterMatchFound = false; 2162 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2163 final char termChar = termLowerCase.charAt(termIndex); 2164 2165 if (queryChar == termChar) { 2166 // simple character matches result in one point 2167 score++; 2168 2169 // subsequent character matches further improve 2170 // the score. 2171 if (previousMatchingCharacterIndex + 1 == termIndex) { 2172 score += 2; 2173 } 2174 2175 previousMatchingCharacterIndex = termIndex; 2176 2177 // we can leave the nested loop. Every character in the 2178 // query can match at most one character in the term. 2179 termCharacterMatchFound = true; 2180 } 2181 } 2182 } 2183 2184 return score; 2185 } 2186 2187 /** 2188 * Returns either the passed in CharSequence, or if the CharSequence is 2189 * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}. 2190 * 2191 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2192 * 2193 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2194 * 2195 * <pre> 2196 * {@code 2197 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2198 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2199 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2200 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2201 * StringUtils.getIfBlank("", () -> null) = null 2202 * StringUtils.getIfBlank("", null) = null 2203 * }</pre> 2204 * @param <T> the specific kind of CharSequence 2205 * @param str the CharSequence to check, may be null 2206 * @param defaultSupplier the supplier of default CharSequence to return 2207 * if the input is whitespace, empty ("") or {@code null}, may be null 2208 * @return the passed in CharSequence, or the default 2209 * @see StringUtils#defaultString(String, String) 2210 * @since 3.10 2211 */ 2212 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2213 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2214 } 2215 2216 /** 2217 * Returns either the passed in CharSequence, or if the CharSequence is 2218 * empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2219 * 2220 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2221 * 2222 * <pre> 2223 * {@code 2224 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2225 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2226 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2227 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2228 * StringUtils.getIfEmpty("", () -> null) = null 2229 * StringUtils.getIfEmpty("", null) = null 2230 * } 2231 * </pre> 2232 * @param <T> the specific kind of CharSequence 2233 * @param str the CharSequence to check, may be null 2234 * @param defaultSupplier the supplier of default CharSequence to return 2235 * if the input is empty ("") or {@code null}, may be null 2236 * @return the passed in CharSequence, or the default 2237 * @see StringUtils#defaultString(String, String) 2238 * @since 3.10 2239 */ 2240 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2241 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2242 } 2243 2244 /** 2245 * Find the Jaro Winkler Distance which indicates the similarity score between two Strings. 2246 * 2247 * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. 2248 * Winkler increased this measure for matching initial characters.</p> 2249 * 2250 * <p>This implementation is based on the Jaro Winkler similarity algorithm 2251 * from <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p> 2252 * 2253 * <pre> 2254 * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException 2255 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2256 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2257 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2258 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2259 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2260 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2261 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2262 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2263 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2264 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2265 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2266 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2267 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2268 * </pre> 2269 * 2270 * @param first the first String, must not be null 2271 * @param second the second String, must not be null 2272 * @return result distance 2273 * @throws IllegalArgumentException if either String input {@code null} 2274 * @since 3.3 2275 * @deprecated As of 3.6, use Apache Commons Text 2276 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2277 * JaroWinklerDistance</a> instead 2278 */ 2279 @Deprecated 2280 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2281 final double DEFAULT_SCALING_FACTOR = 0.1; 2282 2283 if (first == null || second == null) { 2284 throw new IllegalArgumentException("Strings must not be null"); 2285 } 2286 2287 final int[] mtp = matches(first, second); 2288 final double m = mtp[0]; 2289 if (m == 0) { 2290 return 0D; 2291 } 2292 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2293 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2294 return Math.round(jw * 100.0D) / 100.0D; 2295 } 2296 2297 /** 2298 * Find the Levenshtein distance between two Strings. 2299 * 2300 * <p>This is the number of changes needed to change one String into 2301 * another, where each change is a single character modification (deletion, 2302 * insertion or substitution).</p> 2303 * 2304 * <p>The implementation uses a single-dimensional array of length s.length() + 1. See 2305 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2306 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p> 2307 * 2308 * <pre> 2309 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 2310 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 2311 * StringUtils.getLevenshteinDistance("", "") = 0 2312 * StringUtils.getLevenshteinDistance("", "a") = 1 2313 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2314 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2315 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2316 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2317 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2318 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2319 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2320 * </pre> 2321 * 2322 * @param s the first String, must not be null 2323 * @param t the second String, must not be null 2324 * @return result distance 2325 * @throws IllegalArgumentException if either String input {@code null} 2326 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to 2327 * getLevenshteinDistance(CharSequence, CharSequence) 2328 * @deprecated As of 3.6, use Apache Commons Text 2329 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2330 * LevenshteinDistance</a> instead 2331 */ 2332 @Deprecated 2333 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2334 if (s == null || t == null) { 2335 throw new IllegalArgumentException("Strings must not be null"); 2336 } 2337 2338 int n = s.length(); 2339 int m = t.length(); 2340 2341 if (n == 0) { 2342 return m; 2343 } 2344 if (m == 0) { 2345 return n; 2346 } 2347 2348 if (n > m) { 2349 // swap the input strings to consume less memory 2350 final CharSequence tmp = s; 2351 s = t; 2352 t = tmp; 2353 n = m; 2354 m = t.length(); 2355 } 2356 2357 final int[] p = new int[n + 1]; 2358 // indexes into strings s and t 2359 int i; // iterates through s 2360 int j; // iterates through t 2361 int upperleft; 2362 int upper; 2363 2364 char jOfT; // jth character of t 2365 int cost; 2366 2367 for (i = 0; i <= n; i++) { 2368 p[i] = i; 2369 } 2370 2371 for (j = 1; j <= m; j++) { 2372 upperleft = p[0]; 2373 jOfT = t.charAt(j - 1); 2374 p[0] = j; 2375 2376 for (i = 1; i <= n; i++) { 2377 upper = p[i]; 2378 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2379 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2380 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2381 upperleft = upper; 2382 } 2383 } 2384 2385 return p[n]; 2386 } 2387 2388 /** 2389 * Find the Levenshtein distance between two Strings if it's less than or equal to a given 2390 * threshold. 2391 * 2392 * <p>This is the number of changes needed to change one String into 2393 * another, where each change is a single character modification (deletion, 2394 * insertion or substitution).</p> 2395 * 2396 * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield 2397 * and Chas Emerick's implementation of the Levenshtein distance algorithm from 2398 * <a href="https://web.archive.org/web/20120212021906/http%3A//www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 2399 * 2400 * <pre> 2401 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 2402 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 2403 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 2404 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2405 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2406 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2407 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2408 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2409 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2410 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2411 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2412 * </pre> 2413 * 2414 * @param s the first String, must not be null 2415 * @param t the second String, must not be null 2416 * @param threshold the target threshold, must not be negative 2417 * @return result distance, or {@code -1} if the distance would be greater than the threshold 2418 * @throws IllegalArgumentException if either String input {@code null} or negative threshold 2419 * @deprecated As of 3.6, use Apache Commons Text 2420 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2421 * LevenshteinDistance</a> instead 2422 */ 2423 @Deprecated 2424 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2425 if (s == null || t == null) { 2426 throw new IllegalArgumentException("Strings must not be null"); 2427 } 2428 if (threshold < 0) { 2429 throw new IllegalArgumentException("Threshold must not be negative"); 2430 } 2431 2432 /* 2433 This implementation only computes the distance if it's less than or equal to the 2434 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2435 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2436 computing a diagonal stripe of width 2k + 1 of the cost table. 2437 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2438 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2439 d is the distance. 2440 2441 One subtlety comes from needing to ignore entries on the border of our stripe 2442 eg. 2443 p[] = |#|#|#|* 2444 d[] = *|#|#|#| 2445 We must ignore the entry to the left of the leftmost member 2446 We must ignore the entry above the rightmost member 2447 2448 Another subtlety comes from our stripe running off the matrix if the strings aren't 2449 of the same size. Since string s is always swapped to be the shorter of the two, 2450 the stripe will always run off to the upper right instead of the lower left of the matrix. 2451 2452 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2453 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2454 2455 1 2 3 4 5 2456 1 |#|#| | | | 2457 2 |#|#|#| | | 2458 3 | |#|#|#| | 2459 4 | | |#|#|#| 2460 5 | | | |#|#| 2461 6 | | | | |#| 2462 7 | | | | | | 2463 2464 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2465 into one of length 7 in edit distance of 1. 2466 2467 Additionally, this implementation decreases memory usage by using two 2468 single-dimensional arrays and swapping them back and forth instead of allocating 2469 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2470 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2471 large values so that entries we don't compute are ignored. 2472 2473 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2474 */ 2475 2476 int n = s.length(); // length of s 2477 int m = t.length(); // length of t 2478 2479 // if one string is empty, the edit distance is necessarily the length of the other 2480 if (n == 0) { 2481 return m <= threshold ? m : -1; 2482 } 2483 if (m == 0) { 2484 return n <= threshold ? n : -1; 2485 } 2486 if (Math.abs(n - m) > threshold) { 2487 // no need to calculate the distance if the length difference is greater than the threshold 2488 return -1; 2489 } 2490 2491 if (n > m) { 2492 // swap the two strings to consume less memory 2493 final CharSequence tmp = s; 2494 s = t; 2495 t = tmp; 2496 n = m; 2497 m = t.length(); 2498 } 2499 2500 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2501 int[] d = new int[n + 1]; // cost array, horizontally 2502 int[] tmp; // placeholder to assist in swapping p and d 2503 2504 // fill in starting table values 2505 final int boundary = Math.min(n, threshold) + 1; 2506 for (int i = 0; i < boundary; i++) { 2507 p[i] = i; 2508 } 2509 // these fills ensure that the value above the rightmost entry of our 2510 // stripe will be ignored in following loop iterations 2511 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2512 Arrays.fill(d, Integer.MAX_VALUE); 2513 2514 // iterates through t 2515 for (int j = 1; j <= m; j++) { 2516 final char jOfT = t.charAt(j - 1); // jth character of t 2517 d[0] = j; 2518 2519 // compute stripe indices, constrain to array size 2520 final int min = Math.max(1, j - threshold); 2521 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2522 2523 // the stripe may lead off of the table if s and t are of different sizes 2524 if (min > max) { 2525 return -1; 2526 } 2527 2528 // ignore entry left of leftmost 2529 if (min > 1) { 2530 d[min - 1] = Integer.MAX_VALUE; 2531 } 2532 2533 // iterates through [min, max] in s 2534 for (int i = min; i <= max; i++) { 2535 if (s.charAt(i - 1) == jOfT) { 2536 // diagonally left and up 2537 d[i] = p[i - 1]; 2538 } else { 2539 // 1 + minimum of cell to the left, to the top, diagonally left and up 2540 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2541 } 2542 } 2543 2544 // copy current distance counts to 'previous row' distance counts 2545 tmp = p; 2546 p = d; 2547 d = tmp; 2548 } 2549 2550 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2551 // distance 2552 if (p[n] <= threshold) { 2553 return p[n]; 2554 } 2555 return -1; 2556 } 2557 2558 /** 2559 * Finds the first index within a CharSequence, handling {@code null}. 2560 * This method uses {@link String#indexOf(String, int)} if possible. 2561 * 2562 * <p>A {@code null} CharSequence will return {@code -1}.</p> 2563 * 2564 * <pre> 2565 * StringUtils.indexOf(null, *) = -1 2566 * StringUtils.indexOf(*, null) = -1 2567 * StringUtils.indexOf("", "") = 0 2568 * StringUtils.indexOf("", *) = -1 (except when * = "") 2569 * StringUtils.indexOf("aabaabaa", "a") = 0 2570 * StringUtils.indexOf("aabaabaa", "b") = 2 2571 * StringUtils.indexOf("aabaabaa", "ab") = 1 2572 * StringUtils.indexOf("aabaabaa", "") = 0 2573 * </pre> 2574 * 2575 * @param seq the CharSequence to check, may be null 2576 * @param searchSeq the CharSequence to find, may be null 2577 * @return the first index of the search CharSequence, 2578 * -1 if no match or {@code null} string input 2579 * @since 2.0 2580 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2581 */ 2582 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2583 if (seq == null || searchSeq == null) { 2584 return INDEX_NOT_FOUND; 2585 } 2586 return CharSequenceUtils.indexOf(seq, searchSeq, 0); 2587 } 2588 2589 /** 2590 * Finds the first index within a CharSequence, handling {@code null}. 2591 * This method uses {@link String#indexOf(String, int)} if possible. 2592 * 2593 * <p>A {@code null} CharSequence will return {@code -1}. 2594 * A negative start position is treated as zero. 2595 * An empty ("") search CharSequence always matches. 2596 * A start position greater than the string length only matches 2597 * an empty search CharSequence.</p> 2598 * 2599 * <pre> 2600 * StringUtils.indexOf(null, *, *) = -1 2601 * StringUtils.indexOf(*, null, *) = -1 2602 * StringUtils.indexOf("", "", 0) = 0 2603 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2604 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2605 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2606 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2607 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2608 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2609 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2610 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2611 * StringUtils.indexOf("abc", "", 9) = 3 2612 * </pre> 2613 * 2614 * @param seq the CharSequence to check, may be null 2615 * @param searchSeq the CharSequence to find, may be null 2616 * @param startPos the start position, negative treated as zero 2617 * @return the first index of the search CharSequence (always ≥ startPos), 2618 * -1 if no match or {@code null} string input 2619 * @since 2.0 2620 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2621 */ 2622 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2623 if (seq == null || searchSeq == null) { 2624 return INDEX_NOT_FOUND; 2625 } 2626 return CharSequenceUtils.indexOf(seq, searchSeq, startPos); 2627 } 2628 2629 /** 2630 * Returns the index within {@code seq} of the first occurrence of 2631 * the specified character. If a character with value 2632 * {@code searchChar} occurs in the character sequence represented by 2633 * {@code seq} {@link CharSequence} object, then the index (in Unicode 2634 * code units) of the first such occurrence is returned. For 2635 * values of {@code searchChar} in the range from 0 to 0xFFFF 2636 * (inclusive), this is the smallest value <i>k</i> such that: 2637 * <blockquote><pre> 2638 * this.charAt(<i>k</i>) == searchChar 2639 * </pre></blockquote> 2640 * is true. For other values of {@code searchChar}, it is the 2641 * smallest value <i>k</i> such that: 2642 * <blockquote><pre> 2643 * this.codePointAt(<i>k</i>) == searchChar 2644 * </pre></blockquote> 2645 * is true. In either case, if no such character occurs in {@code seq}, 2646 * then {@code INDEX_NOT_FOUND (-1)} is returned. 2647 * 2648 * <p>Furthermore, a {@code null} or empty ("") CharSequence will 2649 * return {@code INDEX_NOT_FOUND (-1)}.</p> 2650 * 2651 * <pre> 2652 * StringUtils.indexOf(null, *) = -1 2653 * StringUtils.indexOf("", *) = -1 2654 * StringUtils.indexOf("aabaabaa", 'a') = 0 2655 * StringUtils.indexOf("aabaabaa", 'b') = 2 2656 * </pre> 2657 * 2658 * @param seq the CharSequence to check, may be null 2659 * @param searchChar the character to find 2660 * @return the first index of the search character, 2661 * -1 if no match or {@code null} string input 2662 * @since 2.0 2663 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2664 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2665 */ 2666 public static int indexOf(final CharSequence seq, final int searchChar) { 2667 if (isEmpty(seq)) { 2668 return INDEX_NOT_FOUND; 2669 } 2670 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2671 } 2672 2673 /** 2674 * Returns the index within {@code seq} of the first occurrence of the 2675 * specified character, starting the search at the specified index. 2676 * <p> 2677 * If a character with value {@code searchChar} occurs in the 2678 * character sequence represented by the {@code seq} {@link CharSequence} 2679 * object at an index no smaller than {@code startPos}, then 2680 * the index of the first such occurrence is returned. For values 2681 * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), 2682 * this is the smallest value <i>k</i> such that: 2683 * <blockquote><pre> 2684 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2685 * </pre></blockquote> 2686 * is true. For other values of {@code searchChar}, it is the 2687 * smallest value <i>k</i> such that: 2688 * <blockquote><pre> 2689 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2690 * </pre></blockquote> 2691 * is true. In either case, if no such character occurs in {@code seq} 2692 * at or after position {@code startPos}, then 2693 * {@code -1} is returned. 2694 * 2695 * <p> 2696 * There is no restriction on the value of {@code startPos}. If it 2697 * is negative, it has the same effect as if it were zero: this entire 2698 * string may be searched. If it is greater than the length of this 2699 * string, it has the same effect as if it were equal to the length of 2700 * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a 2701 * {@code null} or empty ("") CharSequence will 2702 * return {@code (INDEX_NOT_FOUND) -1}. 2703 * 2704 * <p>All indices are specified in {@code char} values 2705 * (Unicode code units). 2706 * 2707 * <pre> 2708 * StringUtils.indexOf(null, *, *) = -1 2709 * StringUtils.indexOf("", *, *) = -1 2710 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2711 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2712 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2713 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2714 * </pre> 2715 * 2716 * @param seq the CharSequence to check, may be null 2717 * @param searchChar the character to find 2718 * @param startPos the start position, negative treated as zero 2719 * @return the first index of the search character (always ≥ startPos), 2720 * -1 if no match or {@code null} string input 2721 * @since 2.0 2722 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2723 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2724 */ 2725 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2726 if (isEmpty(seq)) { 2727 return INDEX_NOT_FOUND; 2728 } 2729 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2730 } 2731 2732 /** 2733 * Search a CharSequence to find the first index of any 2734 * character in the given set of characters. 2735 * 2736 * <p>A {@code null} String will return {@code -1}. 2737 * A {@code null} or zero length search array will return {@code -1}.</p> 2738 * 2739 * <pre> 2740 * StringUtils.indexOfAny(null, *) = -1 2741 * StringUtils.indexOfAny("", *) = -1 2742 * StringUtils.indexOfAny(*, null) = -1 2743 * StringUtils.indexOfAny(*, []) = -1 2744 * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0 2745 * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3 2746 * StringUtils.indexOfAny("aba", ['z']) = -1 2747 * </pre> 2748 * 2749 * @param cs the CharSequence to check, may be null 2750 * @param searchChars the chars to search for, may be null 2751 * @return the index of any of the chars, -1 if no match or null input 2752 * @since 2.0 2753 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2754 */ 2755 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2756 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2757 return INDEX_NOT_FOUND; 2758 } 2759 final int csLen = cs.length(); 2760 final int csLast = csLen - 1; 2761 final int searchLen = searchChars.length; 2762 final int searchLast = searchLen - 1; 2763 for (int i = 0; i < csLen; i++) { 2764 final char ch = cs.charAt(i); 2765 for (int j = 0; j < searchLen; j++) { 2766 if (searchChars[j] == ch) { 2767 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) { 2768 return i; 2769 } 2770 // ch is a supplementary character 2771 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2772 return i; 2773 } 2774 } 2775 } 2776 } 2777 return INDEX_NOT_FOUND; 2778 } 2779 2780 /** 2781 * Find the first index of any of a set of potential substrings. 2782 * 2783 * <p>A {@code null} CharSequence will return {@code -1}. 2784 * A {@code null} or zero length search array will return {@code -1}. 2785 * A {@code null} search array entry will be ignored, but a search 2786 * array containing "" will return {@code 0} if {@code str} is not 2787 * null. This method uses {@link String#indexOf(String)} if possible.</p> 2788 * 2789 * <pre> 2790 * StringUtils.indexOfAny(null, *) = -1 2791 * StringUtils.indexOfAny(*, null) = -1 2792 * StringUtils.indexOfAny(*, []) = -1 2793 * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"]) = 2 2794 * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"]) = 2 2795 * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"]) = -1 2796 * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1 2797 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 2798 * StringUtils.indexOfAny("", [""]) = 0 2799 * StringUtils.indexOfAny("", ["a"]) = -1 2800 * </pre> 2801 * 2802 * @param str the CharSequence to check, may be null 2803 * @param searchStrs the CharSequences to search for, may be null 2804 * @return the first index of any of the searchStrs in str, -1 if no match 2805 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2806 */ 2807 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2808 if (str == null || searchStrs == null) { 2809 return INDEX_NOT_FOUND; 2810 } 2811 2812 // String's can't have a MAX_VALUEth index. 2813 int ret = Integer.MAX_VALUE; 2814 2815 int tmp; 2816 for (final CharSequence search : searchStrs) { 2817 if (search == null) { 2818 continue; 2819 } 2820 tmp = CharSequenceUtils.indexOf(str, search, 0); 2821 if (tmp == INDEX_NOT_FOUND) { 2822 continue; 2823 } 2824 2825 if (tmp < ret) { 2826 ret = tmp; 2827 } 2828 } 2829 2830 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2831 } 2832 2833 /** 2834 * Search a CharSequence to find the first index of any 2835 * character in the given set of characters. 2836 * 2837 * <p>A {@code null} String will return {@code -1}. 2838 * A {@code null} search string will return {@code -1}.</p> 2839 * 2840 * <pre> 2841 * StringUtils.indexOfAny(null, *) = -1 2842 * StringUtils.indexOfAny("", *) = -1 2843 * StringUtils.indexOfAny(*, null) = -1 2844 * StringUtils.indexOfAny(*, "") = -1 2845 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2846 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2847 * StringUtils.indexOfAny("aba", "z") = -1 2848 * </pre> 2849 * 2850 * @param cs the CharSequence to check, may be null 2851 * @param searchChars the chars to search for, may be null 2852 * @return the index of any of the chars, -1 if no match or null input 2853 * @since 2.0 2854 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2855 */ 2856 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2857 if (isEmpty(cs) || isEmpty(searchChars)) { 2858 return INDEX_NOT_FOUND; 2859 } 2860 return indexOfAny(cs, searchChars.toCharArray()); 2861 } 2862 2863 /** 2864 * Searches a CharSequence to find the first index of any 2865 * character not in the given set of characters. 2866 * 2867 * <p>A {@code null} CharSequence will return {@code -1}. 2868 * A {@code null} or zero length search array will return {@code -1}.</p> 2869 * 2870 * <pre> 2871 * StringUtils.indexOfAnyBut(null, *) = -1 2872 * StringUtils.indexOfAnyBut("", *) = -1 2873 * StringUtils.indexOfAnyBut(*, null) = -1 2874 * StringUtils.indexOfAnyBut(*, []) = -1 2875 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2876 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2877 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2878 2879 * </pre> 2880 * 2881 * @param cs the CharSequence to check, may be null 2882 * @param searchChars the chars to search for, may be null 2883 * @return the index of any of the chars, -1 if no match or null input 2884 * @since 2.0 2885 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2886 */ 2887 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2888 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2889 return INDEX_NOT_FOUND; 2890 } 2891 final int csLen = cs.length(); 2892 final int csLast = csLen - 1; 2893 final int searchLen = searchChars.length; 2894 final int searchLast = searchLen - 1; 2895 outer: 2896 for (int i = 0; i < csLen; i++) { 2897 final char ch = cs.charAt(i); 2898 for (int j = 0; j < searchLen; j++) { 2899 if (searchChars[j] == ch) { 2900 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) { 2901 continue outer; 2902 } 2903 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2904 continue outer; 2905 } 2906 } 2907 } 2908 return i; 2909 } 2910 return INDEX_NOT_FOUND; 2911 } 2912 2913 /** 2914 * Search a CharSequence to find the first index of any 2915 * character not in the given set of characters. 2916 * 2917 * <p>A {@code null} CharSequence will return {@code -1}. 2918 * A {@code null} or empty search string will return {@code -1}.</p> 2919 * 2920 * <pre> 2921 * StringUtils.indexOfAnyBut(null, *) = -1 2922 * StringUtils.indexOfAnyBut("", *) = -1 2923 * StringUtils.indexOfAnyBut(*, null) = -1 2924 * StringUtils.indexOfAnyBut(*, "") = -1 2925 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2926 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2927 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2928 * </pre> 2929 * 2930 * @param seq the CharSequence to check, may be null 2931 * @param searchChars the chars to search for, may be null 2932 * @return the index of any of the chars, -1 if no match or null input 2933 * @since 2.0 2934 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2935 */ 2936 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2937 if (isEmpty(seq) || isEmpty(searchChars)) { 2938 return INDEX_NOT_FOUND; 2939 } 2940 final int strLen = seq.length(); 2941 for (int i = 0; i < strLen; i++) { 2942 final char ch = seq.charAt(i); 2943 final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0; 2944 if (i + 1 < strLen && Character.isHighSurrogate(ch)) { 2945 final char ch2 = seq.charAt(i + 1); 2946 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) { 2947 return i; 2948 } 2949 } else if (!chFound) { 2950 return i; 2951 } 2952 } 2953 return INDEX_NOT_FOUND; 2954 } 2955 2956 /** 2957 * Compares all CharSequences in an array and returns the index at which the 2958 * CharSequences begin to differ. 2959 * 2960 * <p>For example, 2961 * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p> 2962 * 2963 * <pre> 2964 * StringUtils.indexOfDifference(null) = -1 2965 * StringUtils.indexOfDifference(new String[] {}) = -1 2966 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2967 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2968 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2969 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2970 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2971 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2972 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2973 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2974 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2975 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2976 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2977 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2978 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2979 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2980 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2981 * </pre> 2982 * 2983 * @param css array of CharSequences, entries may be null 2984 * @return the index where the strings begin to differ; -1 if they are all equal 2985 * @since 2.4 2986 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2987 */ 2988 public static int indexOfDifference(final CharSequence... css) { 2989 if (ArrayUtils.getLength(css) <= 1) { 2990 return INDEX_NOT_FOUND; 2991 } 2992 boolean anyStringNull = false; 2993 boolean allStringsNull = true; 2994 final int arrayLen = css.length; 2995 int shortestStrLen = Integer.MAX_VALUE; 2996 int longestStrLen = 0; 2997 2998 // find the min and max string lengths; this avoids checking to make 2999 // sure we are not exceeding the length of the string each time through 3000 // the bottom loop. 3001 for (final CharSequence cs : css) { 3002 if (cs == null) { 3003 anyStringNull = true; 3004 shortestStrLen = 0; 3005 } else { 3006 allStringsNull = false; 3007 shortestStrLen = Math.min(cs.length(), shortestStrLen); 3008 longestStrLen = Math.max(cs.length(), longestStrLen); 3009 } 3010 } 3011 3012 // handle lists containing all nulls or all empty strings 3013 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 3014 return INDEX_NOT_FOUND; 3015 } 3016 3017 // handle lists containing some nulls or some empty strings 3018 if (shortestStrLen == 0) { 3019 return 0; 3020 } 3021 3022 // find the position with the first difference across all strings 3023 int firstDiff = -1; 3024 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 3025 final char comparisonChar = css[0].charAt(stringPos); 3026 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3027 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3028 firstDiff = stringPos; 3029 break; 3030 } 3031 } 3032 if (firstDiff != -1) { 3033 break; 3034 } 3035 } 3036 3037 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3038 // we compared all of the characters up to the length of the 3039 // shortest string and didn't find a match, but the string lengths 3040 // vary, so return the length of the shortest string. 3041 return shortestStrLen; 3042 } 3043 return firstDiff; 3044 } 3045 3046 /** 3047 * Compares two CharSequences, and returns the index at which the 3048 * CharSequences begin to differ. 3049 * 3050 * <p>For example, 3051 * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p> 3052 * 3053 * <pre> 3054 * StringUtils.indexOfDifference(null, null) = -1 3055 * StringUtils.indexOfDifference("", "") = -1 3056 * StringUtils.indexOfDifference("", "abc") = 0 3057 * StringUtils.indexOfDifference("abc", "") = 0 3058 * StringUtils.indexOfDifference("abc", "abc") = -1 3059 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3060 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3061 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3062 * </pre> 3063 * 3064 * @param cs1 the first CharSequence, may be null 3065 * @param cs2 the second CharSequence, may be null 3066 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal 3067 * @since 2.0 3068 * @since 3.0 Changed signature from indexOfDifference(String, String) to 3069 * indexOfDifference(CharSequence, CharSequence) 3070 */ 3071 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3072 if (cs1 == cs2) { 3073 return INDEX_NOT_FOUND; 3074 } 3075 if (cs1 == null || cs2 == null) { 3076 return 0; 3077 } 3078 int i; 3079 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3080 if (cs1.charAt(i) != cs2.charAt(i)) { 3081 break; 3082 } 3083 } 3084 if (i < cs2.length() || i < cs1.length()) { 3085 return i; 3086 } 3087 return INDEX_NOT_FOUND; 3088 } 3089 3090 /** 3091 * Case in-sensitive find of the first index within a CharSequence. 3092 * 3093 * <p>A {@code null} CharSequence will return {@code -1}. 3094 * A negative start position is treated as zero. 3095 * An empty ("") search CharSequence always matches. 3096 * A start position greater than the string length only matches 3097 * an empty search CharSequence.</p> 3098 * 3099 * <pre> 3100 * StringUtils.indexOfIgnoreCase(null, *) = -1 3101 * StringUtils.indexOfIgnoreCase(*, null) = -1 3102 * StringUtils.indexOfIgnoreCase("", "") = 0 3103 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3104 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3105 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3106 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3107 * </pre> 3108 * 3109 * @param str the CharSequence to check, may be null 3110 * @param searchStr the CharSequence to find, may be null 3111 * @return the first index of the search CharSequence, 3112 * -1 if no match or {@code null} string input 3113 * @since 2.5 3114 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3115 */ 3116 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3117 return indexOfIgnoreCase(str, searchStr, 0); 3118 } 3119 3120 /** 3121 * Case in-sensitive find of the first index within a CharSequence 3122 * from the specified position. 3123 * 3124 * <p>A {@code null} CharSequence will return {@code -1}. 3125 * A negative start position is treated as zero. 3126 * An empty ("") search CharSequence always matches. 3127 * A start position greater than the string length only matches 3128 * an empty search CharSequence.</p> 3129 * 3130 * <pre> 3131 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3132 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3133 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3134 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3135 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3136 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3137 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3138 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3139 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3140 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3141 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3142 * </pre> 3143 * 3144 * @param str the CharSequence to check, may be null 3145 * @param searchStr the CharSequence to find, may be null 3146 * @param startPos the start position, negative treated as zero 3147 * @return the first index of the search CharSequence (always ≥ startPos), 3148 * -1 if no match or {@code null} string input 3149 * @since 2.5 3150 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3151 */ 3152 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 3153 if (str == null || searchStr == null) { 3154 return INDEX_NOT_FOUND; 3155 } 3156 if (startPos < 0) { 3157 startPos = 0; 3158 } 3159 final int endLimit = str.length() - searchStr.length() + 1; 3160 if (startPos > endLimit) { 3161 return INDEX_NOT_FOUND; 3162 } 3163 if (searchStr.length() == 0) { 3164 return startPos; 3165 } 3166 for (int i = startPos; i < endLimit; i++) { 3167 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 3168 return i; 3169 } 3170 } 3171 return INDEX_NOT_FOUND; 3172 } 3173 3174 /** 3175 * Checks if all of the CharSequences are empty (""), null or whitespace only. 3176 * 3177 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3178 * 3179 * <pre> 3180 * StringUtils.isAllBlank(null) = true 3181 * StringUtils.isAllBlank(null, "foo") = false 3182 * StringUtils.isAllBlank(null, null) = true 3183 * StringUtils.isAllBlank("", "bar") = false 3184 * StringUtils.isAllBlank("bob", "") = false 3185 * StringUtils.isAllBlank(" bob ", null) = false 3186 * StringUtils.isAllBlank(" ", "bar") = false 3187 * StringUtils.isAllBlank("foo", "bar") = false 3188 * StringUtils.isAllBlank(new String[] {}) = true 3189 * </pre> 3190 * 3191 * @param css the CharSequences to check, may be null or empty 3192 * @return {@code true} if all of the CharSequences are empty or null or whitespace only 3193 * @since 3.6 3194 */ 3195 public static boolean isAllBlank(final CharSequence... css) { 3196 if (ArrayUtils.isEmpty(css)) { 3197 return true; 3198 } 3199 for (final CharSequence cs : css) { 3200 if (isNotBlank(cs)) { 3201 return false; 3202 } 3203 } 3204 return true; 3205 } 3206 3207 /** 3208 * Checks if all of the CharSequences are empty ("") or null. 3209 * 3210 * <pre> 3211 * StringUtils.isAllEmpty(null) = true 3212 * StringUtils.isAllEmpty(null, "") = true 3213 * StringUtils.isAllEmpty(new String[] {}) = true 3214 * StringUtils.isAllEmpty(null, "foo") = false 3215 * StringUtils.isAllEmpty("", "bar") = false 3216 * StringUtils.isAllEmpty("bob", "") = false 3217 * StringUtils.isAllEmpty(" bob ", null) = false 3218 * StringUtils.isAllEmpty(" ", "bar") = false 3219 * StringUtils.isAllEmpty("foo", "bar") = false 3220 * </pre> 3221 * 3222 * @param css the CharSequences to check, may be null or empty 3223 * @return {@code true} if all of the CharSequences are empty or null 3224 * @since 3.6 3225 */ 3226 public static boolean isAllEmpty(final CharSequence... css) { 3227 if (ArrayUtils.isEmpty(css)) { 3228 return true; 3229 } 3230 for (final CharSequence cs : css) { 3231 if (isNotEmpty(cs)) { 3232 return false; 3233 } 3234 } 3235 return true; 3236 } 3237 3238 /** 3239 * Checks if the CharSequence contains only lowercase characters. 3240 * 3241 * <p>{@code null} will return {@code false}. 3242 * An empty CharSequence (length()=0) will return {@code false}.</p> 3243 * 3244 * <pre> 3245 * StringUtils.isAllLowerCase(null) = false 3246 * StringUtils.isAllLowerCase("") = false 3247 * StringUtils.isAllLowerCase(" ") = false 3248 * StringUtils.isAllLowerCase("abc") = true 3249 * StringUtils.isAllLowerCase("abC") = false 3250 * StringUtils.isAllLowerCase("ab c") = false 3251 * StringUtils.isAllLowerCase("ab1c") = false 3252 * StringUtils.isAllLowerCase("ab/c") = false 3253 * </pre> 3254 * 3255 * @param cs the CharSequence to check, may be null 3256 * @return {@code true} if only contains lowercase characters, and is non-null 3257 * @since 2.5 3258 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3259 */ 3260 public static boolean isAllLowerCase(final CharSequence cs) { 3261 if (isEmpty(cs)) { 3262 return false; 3263 } 3264 final int sz = cs.length(); 3265 for (int i = 0; i < sz; i++) { 3266 if (!Character.isLowerCase(cs.charAt(i))) { 3267 return false; 3268 } 3269 } 3270 return true; 3271 } 3272 3273 /** 3274 * Checks if the CharSequence contains only uppercase characters. 3275 * 3276 * <p>{@code null} will return {@code false}. 3277 * An empty String (length()=0) will return {@code false}.</p> 3278 * 3279 * <pre> 3280 * StringUtils.isAllUpperCase(null) = false 3281 * StringUtils.isAllUpperCase("") = false 3282 * StringUtils.isAllUpperCase(" ") = false 3283 * StringUtils.isAllUpperCase("ABC") = true 3284 * StringUtils.isAllUpperCase("aBC") = false 3285 * StringUtils.isAllUpperCase("A C") = false 3286 * StringUtils.isAllUpperCase("A1C") = false 3287 * StringUtils.isAllUpperCase("A/C") = false 3288 * </pre> 3289 * 3290 * @param cs the CharSequence to check, may be null 3291 * @return {@code true} if only contains uppercase characters, and is non-null 3292 * @since 2.5 3293 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3294 */ 3295 public static boolean isAllUpperCase(final CharSequence cs) { 3296 if (isEmpty(cs)) { 3297 return false; 3298 } 3299 final int sz = cs.length(); 3300 for (int i = 0; i < sz; i++) { 3301 if (!Character.isUpperCase(cs.charAt(i))) { 3302 return false; 3303 } 3304 } 3305 return true; 3306 } 3307 3308 /** 3309 * Checks if the CharSequence contains only Unicode letters. 3310 * 3311 * <p>{@code null} will return {@code false}. 3312 * An empty CharSequence (length()=0) will return {@code false}.</p> 3313 * 3314 * <pre> 3315 * StringUtils.isAlpha(null) = false 3316 * StringUtils.isAlpha("") = false 3317 * StringUtils.isAlpha(" ") = false 3318 * StringUtils.isAlpha("abc") = true 3319 * StringUtils.isAlpha("ab2c") = false 3320 * StringUtils.isAlpha("ab-c") = false 3321 * </pre> 3322 * 3323 * @param cs the CharSequence to check, may be null 3324 * @return {@code true} if only contains letters, and is non-null 3325 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3326 * @since 3.0 Changed "" to return false and not true 3327 */ 3328 public static boolean isAlpha(final CharSequence cs) { 3329 if (isEmpty(cs)) { 3330 return false; 3331 } 3332 final int sz = cs.length(); 3333 for (int i = 0; i < sz; i++) { 3334 if (!Character.isLetter(cs.charAt(i))) { 3335 return false; 3336 } 3337 } 3338 return true; 3339 } 3340 3341 /** 3342 * Checks if the CharSequence contains only Unicode letters or digits. 3343 * 3344 * <p>{@code null} will return {@code false}. 3345 * An empty CharSequence (length()=0) will return {@code false}.</p> 3346 * 3347 * <pre> 3348 * StringUtils.isAlphanumeric(null) = false 3349 * StringUtils.isAlphanumeric("") = false 3350 * StringUtils.isAlphanumeric(" ") = false 3351 * StringUtils.isAlphanumeric("abc") = true 3352 * StringUtils.isAlphanumeric("ab c") = false 3353 * StringUtils.isAlphanumeric("ab2c") = true 3354 * StringUtils.isAlphanumeric("ab-c") = false 3355 * </pre> 3356 * 3357 * @param cs the CharSequence to check, may be null 3358 * @return {@code true} if only contains letters or digits, 3359 * and is non-null 3360 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3361 * @since 3.0 Changed "" to return false and not true 3362 */ 3363 public static boolean isAlphanumeric(final CharSequence cs) { 3364 if (isEmpty(cs)) { 3365 return false; 3366 } 3367 final int sz = cs.length(); 3368 for (int i = 0; i < sz; i++) { 3369 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3370 return false; 3371 } 3372 } 3373 return true; 3374 } 3375 3376 /** 3377 * Checks if the CharSequence contains only Unicode letters, digits 3378 * or space ({@code ' '}). 3379 * 3380 * <p>{@code null} will return {@code false}. 3381 * An empty CharSequence (length()=0) will return {@code true}.</p> 3382 * 3383 * <pre> 3384 * StringUtils.isAlphanumericSpace(null) = false 3385 * StringUtils.isAlphanumericSpace("") = true 3386 * StringUtils.isAlphanumericSpace(" ") = true 3387 * StringUtils.isAlphanumericSpace("abc") = true 3388 * StringUtils.isAlphanumericSpace("ab c") = true 3389 * StringUtils.isAlphanumericSpace("ab2c") = true 3390 * StringUtils.isAlphanumericSpace("ab-c") = false 3391 * </pre> 3392 * 3393 * @param cs the CharSequence to check, may be null 3394 * @return {@code true} if only contains letters, digits or space, 3395 * and is non-null 3396 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3397 */ 3398 public static boolean isAlphanumericSpace(final CharSequence cs) { 3399 if (cs == null) { 3400 return false; 3401 } 3402 final int sz = cs.length(); 3403 for (int i = 0; i < sz; i++) { 3404 final char nowChar = cs.charAt(i); 3405 if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar) ) { 3406 return false; 3407 } 3408 } 3409 return true; 3410 } 3411 3412 /** 3413 * Checks if the CharSequence contains only Unicode letters and 3414 * space (' '). 3415 * 3416 * <p>{@code null} will return {@code false} 3417 * An empty CharSequence (length()=0) will return {@code true}.</p> 3418 * 3419 * <pre> 3420 * StringUtils.isAlphaSpace(null) = false 3421 * StringUtils.isAlphaSpace("") = true 3422 * StringUtils.isAlphaSpace(" ") = true 3423 * StringUtils.isAlphaSpace("abc") = true 3424 * StringUtils.isAlphaSpace("ab c") = true 3425 * StringUtils.isAlphaSpace("ab2c") = false 3426 * StringUtils.isAlphaSpace("ab-c") = false 3427 * </pre> 3428 * 3429 * @param cs the CharSequence to check, may be null 3430 * @return {@code true} if only contains letters and space, 3431 * and is non-null 3432 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3433 */ 3434 public static boolean isAlphaSpace(final CharSequence cs) { 3435 if (cs == null) { 3436 return false; 3437 } 3438 final int sz = cs.length(); 3439 for (int i = 0; i < sz; i++) { 3440 final char nowChar = cs.charAt(i); 3441 if (nowChar != ' ' && !Character.isLetter(nowChar)) { 3442 return false; 3443 } 3444 } 3445 return true; 3446 } 3447 3448 /** 3449 * Checks if any of the CharSequences are empty ("") or null or whitespace only. 3450 * 3451 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3452 * 3453 * <pre> 3454 * StringUtils.isAnyBlank((String) null) = true 3455 * StringUtils.isAnyBlank((String[]) null) = false 3456 * StringUtils.isAnyBlank(null, "foo") = true 3457 * StringUtils.isAnyBlank(null, null) = true 3458 * StringUtils.isAnyBlank("", "bar") = true 3459 * StringUtils.isAnyBlank("bob", "") = true 3460 * StringUtils.isAnyBlank(" bob ", null) = true 3461 * StringUtils.isAnyBlank(" ", "bar") = true 3462 * StringUtils.isAnyBlank(new String[] {}) = false 3463 * StringUtils.isAnyBlank(new String[]{""}) = true 3464 * StringUtils.isAnyBlank("foo", "bar") = false 3465 * </pre> 3466 * 3467 * @param css the CharSequences to check, may be null or empty 3468 * @return {@code true} if any of the CharSequences are empty or null or whitespace only 3469 * @since 3.2 3470 */ 3471 public static boolean isAnyBlank(final CharSequence... css) { 3472 if (ArrayUtils.isEmpty(css)) { 3473 return false; 3474 } 3475 for (final CharSequence cs : css) { 3476 if (isBlank(cs)) { 3477 return true; 3478 } 3479 } 3480 return false; 3481 } 3482 3483 /** 3484 * Checks if any of the CharSequences are empty ("") or null. 3485 * 3486 * <pre> 3487 * StringUtils.isAnyEmpty((String) null) = true 3488 * StringUtils.isAnyEmpty((String[]) null) = false 3489 * StringUtils.isAnyEmpty(null, "foo") = true 3490 * StringUtils.isAnyEmpty("", "bar") = true 3491 * StringUtils.isAnyEmpty("bob", "") = true 3492 * StringUtils.isAnyEmpty(" bob ", null) = true 3493 * StringUtils.isAnyEmpty(" ", "bar") = false 3494 * StringUtils.isAnyEmpty("foo", "bar") = false 3495 * StringUtils.isAnyEmpty(new String[]{}) = false 3496 * StringUtils.isAnyEmpty(new String[]{""}) = true 3497 * </pre> 3498 * 3499 * @param css the CharSequences to check, may be null or empty 3500 * @return {@code true} if any of the CharSequences are empty or null 3501 * @since 3.2 3502 */ 3503 public static boolean isAnyEmpty(final CharSequence... css) { 3504 if (ArrayUtils.isEmpty(css)) { 3505 return false; 3506 } 3507 for (final CharSequence cs : css) { 3508 if (isEmpty(cs)) { 3509 return true; 3510 } 3511 } 3512 return false; 3513 } 3514 3515 /** 3516 * Checks if the CharSequence contains only ASCII printable characters. 3517 * 3518 * <p>{@code null} will return {@code false}. 3519 * An empty CharSequence (length()=0) will return {@code true}.</p> 3520 * 3521 * <pre> 3522 * StringUtils.isAsciiPrintable(null) = false 3523 * StringUtils.isAsciiPrintable("") = true 3524 * StringUtils.isAsciiPrintable(" ") = true 3525 * StringUtils.isAsciiPrintable("Ceki") = true 3526 * StringUtils.isAsciiPrintable("ab2c") = true 3527 * StringUtils.isAsciiPrintable("!ab-c~") = true 3528 * StringUtils.isAsciiPrintable("\u0020") = true 3529 * StringUtils.isAsciiPrintable("\u0021") = true 3530 * StringUtils.isAsciiPrintable("\u007e") = true 3531 * StringUtils.isAsciiPrintable("\u007f") = false 3532 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3533 * </pre> 3534 * 3535 * @param cs the CharSequence to check, may be null 3536 * @return {@code true} if every character is in the range 3537 * 32 through 126 3538 * @since 2.1 3539 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3540 */ 3541 public static boolean isAsciiPrintable(final CharSequence cs) { 3542 if (cs == null) { 3543 return false; 3544 } 3545 final int sz = cs.length(); 3546 for (int i = 0; i < sz; i++) { 3547 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3548 return false; 3549 } 3550 } 3551 return true; 3552 } 3553 3554 /** 3555 * Checks if a CharSequence is empty (""), null or whitespace only. 3556 * 3557 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3558 * 3559 * <pre> 3560 * StringUtils.isBlank(null) = true 3561 * StringUtils.isBlank("") = true 3562 * StringUtils.isBlank(" ") = true 3563 * StringUtils.isBlank("bob") = false 3564 * StringUtils.isBlank(" bob ") = false 3565 * </pre> 3566 * 3567 * @param cs the CharSequence to check, may be null 3568 * @return {@code true} if the CharSequence is null, empty or whitespace only 3569 * @since 2.0 3570 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3571 */ 3572 public static boolean isBlank(final CharSequence cs) { 3573 final int strLen = length(cs); 3574 if (strLen == 0) { 3575 return true; 3576 } 3577 for (int i = 0; i < strLen; i++) { 3578 if (!Character.isWhitespace(cs.charAt(i))) { 3579 return false; 3580 } 3581 } 3582 return true; 3583 } 3584 3585 /** 3586 * Checks if a CharSequence is empty ("") or null. 3587 * 3588 * <pre> 3589 * StringUtils.isEmpty(null) = true 3590 * StringUtils.isEmpty("") = true 3591 * StringUtils.isEmpty(" ") = false 3592 * StringUtils.isEmpty("bob") = false 3593 * StringUtils.isEmpty(" bob ") = false 3594 * </pre> 3595 * 3596 * <p>NOTE: This method changed in Lang version 2.0. 3597 * It no longer trims the CharSequence. 3598 * That functionality is available in isBlank().</p> 3599 * 3600 * @param cs the CharSequence to check, may be null 3601 * @return {@code true} if the CharSequence is empty or null 3602 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3603 */ 3604 public static boolean isEmpty(final CharSequence cs) { 3605 return cs == null || cs.length() == 0; 3606 } 3607 3608 /** 3609 * Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3610 * 3611 * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return 3612 * {@code false}.</p> 3613 * 3614 * <pre> 3615 * StringUtils.isMixedCase(null) = false 3616 * StringUtils.isMixedCase("") = false 3617 * StringUtils.isMixedCase(" ") = false 3618 * StringUtils.isMixedCase("ABC") = false 3619 * StringUtils.isMixedCase("abc") = false 3620 * StringUtils.isMixedCase("aBc") = true 3621 * StringUtils.isMixedCase("A c") = true 3622 * StringUtils.isMixedCase("A1c") = true 3623 * StringUtils.isMixedCase("a/C") = true 3624 * StringUtils.isMixedCase("aC\t") = true 3625 * </pre> 3626 * 3627 * @param cs the CharSequence to check, may be null 3628 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters 3629 * @since 3.5 3630 */ 3631 public static boolean isMixedCase(final CharSequence cs) { 3632 if (isEmpty(cs) || cs.length() == 1) { 3633 return false; 3634 } 3635 boolean containsUppercase = false; 3636 boolean containsLowercase = false; 3637 final int sz = cs.length(); 3638 for (int i = 0; i < sz; i++) { 3639 final char nowChar = cs.charAt(i); 3640 if (Character.isUpperCase(nowChar)) { 3641 containsUppercase = true; 3642 } else if (Character.isLowerCase(nowChar)) { 3643 containsLowercase = true; 3644 } 3645 if (containsUppercase && containsLowercase) { 3646 return true; 3647 } 3648 } 3649 return false; 3650 } 3651 3652 /** 3653 * Checks if none of the CharSequences are empty (""), null or whitespace only. 3654 * 3655 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3656 * 3657 * <pre> 3658 * StringUtils.isNoneBlank((String) null) = false 3659 * StringUtils.isNoneBlank((String[]) null) = true 3660 * StringUtils.isNoneBlank(null, "foo") = false 3661 * StringUtils.isNoneBlank(null, null) = false 3662 * StringUtils.isNoneBlank("", "bar") = false 3663 * StringUtils.isNoneBlank("bob", "") = false 3664 * StringUtils.isNoneBlank(" bob ", null) = false 3665 * StringUtils.isNoneBlank(" ", "bar") = false 3666 * StringUtils.isNoneBlank(new String[] {}) = true 3667 * StringUtils.isNoneBlank(new String[]{""}) = false 3668 * StringUtils.isNoneBlank("foo", "bar") = true 3669 * </pre> 3670 * 3671 * @param css the CharSequences to check, may be null or empty 3672 * @return {@code true} if none of the CharSequences are empty or null or whitespace only 3673 * @since 3.2 3674 */ 3675 public static boolean isNoneBlank(final CharSequence... css) { 3676 return !isAnyBlank(css); 3677 } 3678 3679 /** 3680 * Checks if none of the CharSequences are empty ("") or null. 3681 * 3682 * <pre> 3683 * StringUtils.isNoneEmpty((String) null) = false 3684 * StringUtils.isNoneEmpty((String[]) null) = true 3685 * StringUtils.isNoneEmpty(null, "foo") = false 3686 * StringUtils.isNoneEmpty("", "bar") = false 3687 * StringUtils.isNoneEmpty("bob", "") = false 3688 * StringUtils.isNoneEmpty(" bob ", null) = false 3689 * StringUtils.isNoneEmpty(new String[] {}) = true 3690 * StringUtils.isNoneEmpty(new String[]{""}) = false 3691 * StringUtils.isNoneEmpty(" ", "bar") = true 3692 * StringUtils.isNoneEmpty("foo", "bar") = true 3693 * </pre> 3694 * 3695 * @param css the CharSequences to check, may be null or empty 3696 * @return {@code true} if none of the CharSequences are empty or null 3697 * @since 3.2 3698 */ 3699 public static boolean isNoneEmpty(final CharSequence... css) { 3700 return !isAnyEmpty(css); 3701 } 3702 3703 /** 3704 * Checks if a CharSequence is not empty (""), not null and not whitespace only. 3705 * 3706 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3707 * 3708 * <pre> 3709 * StringUtils.isNotBlank(null) = false 3710 * StringUtils.isNotBlank("") = false 3711 * StringUtils.isNotBlank(" ") = false 3712 * StringUtils.isNotBlank("bob") = true 3713 * StringUtils.isNotBlank(" bob ") = true 3714 * </pre> 3715 * 3716 * @param cs the CharSequence to check, may be null 3717 * @return {@code true} if the CharSequence is 3718 * not empty and not null and not whitespace only 3719 * @since 2.0 3720 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3721 */ 3722 public static boolean isNotBlank(final CharSequence cs) { 3723 return !isBlank(cs); 3724 } 3725 3726 /** 3727 * Checks if a CharSequence is not empty ("") and not null. 3728 * 3729 * <pre> 3730 * StringUtils.isNotEmpty(null) = false 3731 * StringUtils.isNotEmpty("") = false 3732 * StringUtils.isNotEmpty(" ") = true 3733 * StringUtils.isNotEmpty("bob") = true 3734 * StringUtils.isNotEmpty(" bob ") = true 3735 * </pre> 3736 * 3737 * @param cs the CharSequence to check, may be null 3738 * @return {@code true} if the CharSequence is not empty and not null 3739 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3740 */ 3741 public static boolean isNotEmpty(final CharSequence cs) { 3742 return !isEmpty(cs); 3743 } 3744 3745 /** 3746 * Checks if the CharSequence contains only Unicode digits. 3747 * A decimal point is not a Unicode digit and returns false. 3748 * 3749 * <p>{@code null} will return {@code false}. 3750 * An empty CharSequence (length()=0) will return {@code false}.</p> 3751 * 3752 * <p>Note that the method does not allow for a leading sign, either positive or negative. 3753 * Also, if a String passes the numeric test, it may still generate a NumberFormatException 3754 * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range 3755 * for int or long respectively.</p> 3756 * 3757 * <pre> 3758 * StringUtils.isNumeric(null) = false 3759 * StringUtils.isNumeric("") = false 3760 * StringUtils.isNumeric(" ") = false 3761 * StringUtils.isNumeric("123") = true 3762 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3763 * StringUtils.isNumeric("12 3") = false 3764 * StringUtils.isNumeric("ab2c") = false 3765 * StringUtils.isNumeric("12-3") = false 3766 * StringUtils.isNumeric("12.3") = false 3767 * StringUtils.isNumeric("-123") = false 3768 * StringUtils.isNumeric("+123") = false 3769 * </pre> 3770 * 3771 * @param cs the CharSequence to check, may be null 3772 * @return {@code true} if only contains digits, and is non-null 3773 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3774 * @since 3.0 Changed "" to return false and not true 3775 */ 3776 public static boolean isNumeric(final CharSequence cs) { 3777 if (isEmpty(cs)) { 3778 return false; 3779 } 3780 final int sz = cs.length(); 3781 for (int i = 0; i < sz; i++) { 3782 if (!Character.isDigit(cs.charAt(i))) { 3783 return false; 3784 } 3785 } 3786 return true; 3787 } 3788 3789 /** 3790 * Checks if the CharSequence contains only Unicode digits or space 3791 * ({@code ' '}). 3792 * A decimal point is not a Unicode digit and returns false. 3793 * 3794 * <p>{@code null} will return {@code false}. 3795 * An empty CharSequence (length()=0) will return {@code true}.</p> 3796 * 3797 * <pre> 3798 * StringUtils.isNumericSpace(null) = false 3799 * StringUtils.isNumericSpace("") = true 3800 * StringUtils.isNumericSpace(" ") = true 3801 * StringUtils.isNumericSpace("123") = true 3802 * StringUtils.isNumericSpace("12 3") = true 3803 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3804 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3805 * StringUtils.isNumericSpace("ab2c") = false 3806 * StringUtils.isNumericSpace("12-3") = false 3807 * StringUtils.isNumericSpace("12.3") = false 3808 * </pre> 3809 * 3810 * @param cs the CharSequence to check, may be null 3811 * @return {@code true} if only contains digits or space, 3812 * and is non-null 3813 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3814 */ 3815 public static boolean isNumericSpace(final CharSequence cs) { 3816 if (cs == null) { 3817 return false; 3818 } 3819 final int sz = cs.length(); 3820 for (int i = 0; i < sz; i++) { 3821 final char nowChar = cs.charAt(i); 3822 if (nowChar != ' ' && !Character.isDigit(nowChar)) { 3823 return false; 3824 } 3825 } 3826 return true; 3827 } 3828 3829 /** 3830 * Checks if the CharSequence contains only whitespace. 3831 * 3832 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3833 * 3834 * <p>{@code null} will return {@code false}. 3835 * An empty CharSequence (length()=0) will return {@code true}.</p> 3836 * 3837 * <pre> 3838 * StringUtils.isWhitespace(null) = false 3839 * StringUtils.isWhitespace("") = true 3840 * StringUtils.isWhitespace(" ") = true 3841 * StringUtils.isWhitespace("abc") = false 3842 * StringUtils.isWhitespace("ab2c") = false 3843 * StringUtils.isWhitespace("ab-c") = false 3844 * </pre> 3845 * 3846 * @param cs the CharSequence to check, may be null 3847 * @return {@code true} if only contains whitespace, and is non-null 3848 * @since 2.0 3849 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3850 */ 3851 public static boolean isWhitespace(final CharSequence cs) { 3852 if (cs == null) { 3853 return false; 3854 } 3855 final int sz = cs.length(); 3856 for (int i = 0; i < sz; i++) { 3857 if (!Character.isWhitespace(cs.charAt(i))) { 3858 return false; 3859 } 3860 } 3861 return true; 3862 } 3863 3864 /** 3865 * Joins the elements of the provided array into a single String containing the provided list of elements. 3866 * 3867 * <p> 3868 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3869 * by empty strings. 3870 * </p> 3871 * 3872 * <pre> 3873 * StringUtils.join(null, *) = null 3874 * StringUtils.join([], *) = "" 3875 * StringUtils.join([null], *) = "" 3876 * StringUtils.join([false, false], ';') = "false;false" 3877 * </pre> 3878 * 3879 * @param array 3880 * the array of values to join together, may be null 3881 * @param delimiter 3882 * the separator character to use 3883 * @return the joined String, {@code null} if null array input 3884 * @since 3.12.0 3885 */ 3886 public static String join(final boolean[] array, final char delimiter) { 3887 if (array == null) { 3888 return null; 3889 } 3890 return join(array, delimiter, 0, array.length); 3891 } 3892 3893 /** 3894 * Joins the elements of the provided array into a single String containing the provided list of elements. 3895 * 3896 * <p> 3897 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3898 * by empty strings. 3899 * </p> 3900 * 3901 * <pre> 3902 * StringUtils.join(null, *) = null 3903 * StringUtils.join([], *) = "" 3904 * StringUtils.join([null], *) = "" 3905 * StringUtils.join([true, false, true], ';') = "true;false;true" 3906 * </pre> 3907 * 3908 * @param array 3909 * the array of values to join together, may be null 3910 * @param delimiter 3911 * the separator character to use 3912 * @param startIndex 3913 * the first index to start joining from. It is an error to pass in a start index past the end of the 3914 * array 3915 * @param endIndex 3916 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3917 * the array 3918 * @return the joined String, {@code null} if null array input 3919 * @since 3.12.0 3920 */ 3921 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3922 if (array == null) { 3923 return null; 3924 } 3925 if (endIndex - startIndex <= 0) { 3926 return EMPTY; 3927 } 3928 final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1); 3929 for (int i = startIndex; i < endIndex; i++) { 3930 stringBuilder 3931 .append(array[i]) 3932 .append(delimiter); 3933 } 3934 return stringBuilder.substring(0, stringBuilder.length() - 1); 3935 } 3936 3937 /** 3938 * Joins the elements of the provided array into a single String containing the provided list of elements. 3939 * 3940 * <p> 3941 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3942 * by empty strings. 3943 * </p> 3944 * 3945 * <pre> 3946 * StringUtils.join(null, *) = null 3947 * StringUtils.join([], *) = "" 3948 * StringUtils.join([null], *) = "" 3949 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3950 * StringUtils.join([1, 2, 3], null) = "123" 3951 * </pre> 3952 * 3953 * @param array 3954 * the array of values to join together, may be null 3955 * @param delimiter 3956 * the separator character to use 3957 * @return the joined String, {@code null} if null array input 3958 * @since 3.2 3959 */ 3960 public static String join(final byte[] array, final char delimiter) { 3961 if (array == null) { 3962 return null; 3963 } 3964 return join(array, delimiter, 0, array.length); 3965 } 3966 3967 /** 3968 * Joins the elements of the provided array into a single String containing the provided list of elements. 3969 * 3970 * <p> 3971 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3972 * by empty strings. 3973 * </p> 3974 * 3975 * <pre> 3976 * StringUtils.join(null, *) = null 3977 * StringUtils.join([], *) = "" 3978 * StringUtils.join([null], *) = "" 3979 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3980 * StringUtils.join([1, 2, 3], null) = "123" 3981 * </pre> 3982 * 3983 * @param array 3984 * the array of values to join together, may be null 3985 * @param delimiter 3986 * the separator character to use 3987 * @param startIndex 3988 * the first index to start joining from. It is an error to pass in a start index past the end of the 3989 * array 3990 * @param endIndex 3991 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3992 * the array 3993 * @return the joined String, {@code null} if null array input 3994 * @since 3.2 3995 */ 3996 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 3997 if (array == null) { 3998 return null; 3999 } 4000 if (endIndex - startIndex <= 0) { 4001 return EMPTY; 4002 } 4003 final StringBuilder stringBuilder = new StringBuilder(); 4004 for (int i = startIndex; i < endIndex; i++) { 4005 stringBuilder 4006 .append(array[i]) 4007 .append(delimiter); 4008 } 4009 return stringBuilder.substring(0, stringBuilder.length() - 1); 4010 } 4011 4012 /** 4013 * Joins the elements of the provided array into a single String containing the provided list of elements. 4014 * 4015 * <p> 4016 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4017 * by empty strings. 4018 * </p> 4019 * 4020 * <pre> 4021 * StringUtils.join(null, *) = null 4022 * StringUtils.join([], *) = "" 4023 * StringUtils.join([null], *) = "" 4024 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4025 * StringUtils.join([1, 2, 3], null) = "123" 4026 * </pre> 4027 * 4028 * @param array 4029 * the array of values to join together, may be null 4030 * @param delimiter 4031 * the separator character to use 4032 * @return the joined String, {@code null} if null array input 4033 * @since 3.2 4034 */ 4035 public static String join(final char[] array, final char delimiter) { 4036 if (array == null) { 4037 return null; 4038 } 4039 return join(array, delimiter, 0, array.length); 4040 } 4041 4042 /** 4043 * Joins the elements of the provided array into a single String containing the provided list of elements. 4044 * 4045 * <p> 4046 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4047 * by empty strings. 4048 * </p> 4049 * 4050 * <pre> 4051 * StringUtils.join(null, *) = null 4052 * StringUtils.join([], *) = "" 4053 * StringUtils.join([null], *) = "" 4054 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4055 * StringUtils.join([1, 2, 3], null) = "123" 4056 * </pre> 4057 * 4058 * @param array 4059 * the array of values to join together, may be null 4060 * @param delimiter 4061 * the separator character to use 4062 * @param startIndex 4063 * the first index to start joining from. It is an error to pass in a start index past the end of the 4064 * array 4065 * @param endIndex 4066 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4067 * the array 4068 * @return the joined String, {@code null} if null array input 4069 * @since 3.2 4070 */ 4071 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4072 if (array == null) { 4073 return null; 4074 } 4075 if (endIndex - startIndex <= 0) { 4076 return EMPTY; 4077 } 4078 final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1); 4079 for (int i = startIndex; i < endIndex; i++) { 4080 stringBuilder 4081 .append(array[i]) 4082 .append(delimiter); 4083 } 4084 return stringBuilder.substring(0, stringBuilder.length() - 1); 4085 } 4086 4087 /** 4088 * Joins the elements of the provided array into a single String containing the provided list of elements. 4089 * 4090 * <p> 4091 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4092 * by empty strings. 4093 * </p> 4094 * 4095 * <pre> 4096 * StringUtils.join(null, *) = null 4097 * StringUtils.join([], *) = "" 4098 * StringUtils.join([null], *) = "" 4099 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4100 * StringUtils.join([1, 2, 3], null) = "123" 4101 * </pre> 4102 * 4103 * @param array 4104 * the array of values to join together, may be null 4105 * @param delimiter 4106 * the separator character to use 4107 * @return the joined String, {@code null} if null array input 4108 * @since 3.2 4109 */ 4110 public static String join(final double[] array, final char delimiter) { 4111 if (array == null) { 4112 return null; 4113 } 4114 return join(array, delimiter, 0, array.length); 4115 } 4116 4117 /** 4118 * Joins the elements of the provided array into a single String containing the provided list of elements. 4119 * 4120 * <p> 4121 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4122 * by empty strings. 4123 * </p> 4124 * 4125 * <pre> 4126 * StringUtils.join(null, *) = null 4127 * StringUtils.join([], *) = "" 4128 * StringUtils.join([null], *) = "" 4129 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4130 * StringUtils.join([1, 2, 3], null) = "123" 4131 * </pre> 4132 * 4133 * @param array 4134 * the array of values to join together, may be null 4135 * @param delimiter 4136 * the separator character to use 4137 * @param startIndex 4138 * the first index to start joining from. It is an error to pass in a start index past the end of the 4139 * array 4140 * @param endIndex 4141 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4142 * the array 4143 * @return the joined String, {@code null} if null array input 4144 * @since 3.2 4145 */ 4146 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4147 if (array == null) { 4148 return null; 4149 } 4150 if (endIndex - startIndex <= 0) { 4151 return EMPTY; 4152 } 4153 final StringBuilder stringBuilder = new StringBuilder(); 4154 for (int i = startIndex; i < endIndex; i++) { 4155 stringBuilder 4156 .append(array[i]) 4157 .append(delimiter); 4158 } 4159 return stringBuilder.substring(0, stringBuilder.length() - 1); 4160 } 4161 4162 /** 4163 * Joins the elements of the provided array into a single String containing the provided list of elements. 4164 * 4165 * <p> 4166 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4167 * by empty strings. 4168 * </p> 4169 * 4170 * <pre> 4171 * StringUtils.join(null, *) = null 4172 * StringUtils.join([], *) = "" 4173 * StringUtils.join([null], *) = "" 4174 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4175 * StringUtils.join([1, 2, 3], null) = "123" 4176 * </pre> 4177 * 4178 * @param array 4179 * the array of values to join together, may be null 4180 * @param delimiter 4181 * the separator character to use 4182 * @return the joined String, {@code null} if null array input 4183 * @since 3.2 4184 */ 4185 public static String join(final float[] array, final char delimiter) { 4186 if (array == null) { 4187 return null; 4188 } 4189 return join(array, delimiter, 0, array.length); 4190 } 4191 4192 /** 4193 * Joins the elements of the provided array into a single String containing the provided list of elements. 4194 * 4195 * <p> 4196 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4197 * by empty strings. 4198 * </p> 4199 * 4200 * <pre> 4201 * StringUtils.join(null, *) = null 4202 * StringUtils.join([], *) = "" 4203 * StringUtils.join([null], *) = "" 4204 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4205 * StringUtils.join([1, 2, 3], null) = "123" 4206 * </pre> 4207 * 4208 * @param array 4209 * the array of values to join together, may be null 4210 * @param delimiter 4211 * the separator character to use 4212 * @param startIndex 4213 * the first index to start joining from. It is an error to pass in a start index past the end of the 4214 * array 4215 * @param endIndex 4216 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4217 * the array 4218 * @return the joined String, {@code null} if null array input 4219 * @since 3.2 4220 */ 4221 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4222 if (array == null) { 4223 return null; 4224 } 4225 if (endIndex - startIndex <= 0) { 4226 return EMPTY; 4227 } 4228 final StringBuilder stringBuilder = new StringBuilder(); 4229 for (int i = startIndex; i < endIndex; i++) { 4230 stringBuilder 4231 .append(array[i]) 4232 .append(delimiter); 4233 } 4234 return stringBuilder.substring(0, stringBuilder.length() - 1); 4235 } 4236 4237 /** 4238 * Joins the elements of the provided array into a single String containing the provided list of elements. 4239 * 4240 * <p> 4241 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4242 * by empty strings. 4243 * </p> 4244 * 4245 * <pre> 4246 * StringUtils.join(null, *) = null 4247 * StringUtils.join([], *) = "" 4248 * StringUtils.join([null], *) = "" 4249 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4250 * StringUtils.join([1, 2, 3], null) = "123" 4251 * </pre> 4252 * 4253 * @param array 4254 * the array of values to join together, may be null 4255 * @param separator 4256 * the separator character to use 4257 * @return the joined String, {@code null} if null array input 4258 * @since 3.2 4259 */ 4260 public static String join(final int[] array, final char separator) { 4261 if (array == null) { 4262 return null; 4263 } 4264 return join(array, separator, 0, array.length); 4265 } 4266 4267 /** 4268 * Joins the elements of the provided array into a single String containing the provided list of elements. 4269 * 4270 * <p> 4271 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4272 * by empty strings. 4273 * </p> 4274 * 4275 * <pre> 4276 * StringUtils.join(null, *) = null 4277 * StringUtils.join([], *) = "" 4278 * StringUtils.join([null], *) = "" 4279 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4280 * StringUtils.join([1, 2, 3], null) = "123" 4281 * </pre> 4282 * 4283 * @param array 4284 * the array of values to join together, may be null 4285 * @param delimiter 4286 * the separator character to use 4287 * @param startIndex 4288 * the first index to start joining from. It is an error to pass in a start index past the end of the 4289 * array 4290 * @param endIndex 4291 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4292 * the array 4293 * @return the joined String, {@code null} if null array input 4294 * @since 3.2 4295 */ 4296 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4297 if (array == null) { 4298 return null; 4299 } 4300 if (endIndex - startIndex <= 0) { 4301 return EMPTY; 4302 } 4303 final StringBuilder stringBuilder = new StringBuilder(); 4304 for (int i = startIndex; i < endIndex; i++) { 4305 stringBuilder 4306 .append(array[i]) 4307 .append(delimiter); 4308 } 4309 return stringBuilder.substring(0, stringBuilder.length() - 1); 4310 } 4311 4312 /** 4313 * Joins the elements of the provided {@link Iterable} into 4314 * a single String containing the provided elements. 4315 * 4316 * <p>No delimiter is added before or after the list. Null objects or empty 4317 * strings within the iteration are represented by empty strings.</p> 4318 * 4319 * <p>See the examples here: {@link #join(Object[],char)}.</p> 4320 * 4321 * @param iterable the {@link Iterable} providing the values to join together, may be null 4322 * @param separator the separator character to use 4323 * @return the joined String, {@code null} if null iterator input 4324 * @since 2.3 4325 */ 4326 public static String join(final Iterable<?> iterable, final char separator) { 4327 return iterable != null ? join(iterable.iterator(), separator) : null; 4328 } 4329 4330 /** 4331 * Joins the elements of the provided {@link Iterable} into 4332 * a single String containing the provided elements. 4333 * 4334 * <p>No delimiter is added before or after the list. 4335 * A {@code null} separator is the same as an empty String ("").</p> 4336 * 4337 * <p>See the examples here: {@link #join(Object[],String)}.</p> 4338 * 4339 * @param iterable the {@link Iterable} providing the values to join together, may be null 4340 * @param separator the separator character to use, null treated as "" 4341 * @return the joined String, {@code null} if null iterator input 4342 * @since 2.3 4343 */ 4344 public static String join(final Iterable<?> iterable, final String separator) { 4345 return iterable != null ? join(iterable.iterator(), separator) : null; 4346 } 4347 4348 /** 4349 * Joins the elements of the provided {@link Iterator} into 4350 * a single String containing the provided elements. 4351 * 4352 * <p>No delimiter is added before or after the list. Null objects or empty 4353 * strings within the iteration are represented by empty strings.</p> 4354 * 4355 * <p>See the examples here: {@link #join(Object[],char)}.</p> 4356 * 4357 * @param iterator the {@link Iterator} of values to join together, may be null 4358 * @param separator the separator character to use 4359 * @return the joined String, {@code null} if null iterator input 4360 * @since 2.0 4361 */ 4362 public static String join(final Iterator<?> iterator, final char separator) { 4363 // handle null, zero and one elements before building a buffer 4364 if (iterator == null) { 4365 return null; 4366 } 4367 if (!iterator.hasNext()) { 4368 return EMPTY; 4369 } 4370 return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(String.valueOf(separator)), EMPTY, EMPTY, StringUtils::toStringOrEmpty)); 4371 } 4372 4373 /** 4374 * Joins the elements of the provided {@link Iterator} into 4375 * a single String containing the provided elements. 4376 * 4377 * <p>No delimiter is added before or after the list. 4378 * A {@code null} separator is the same as an empty String ("").</p> 4379 * 4380 * <p>See the examples here: {@link #join(Object[],String)}.</p> 4381 * 4382 * @param iterator the {@link Iterator} of values to join together, may be null 4383 * @param separator the separator character to use, null treated as "" 4384 * @return the joined String, {@code null} if null iterator input 4385 */ 4386 public static String join(final Iterator<?> iterator, final String separator) { 4387 // handle null, zero and one elements before building a buffer 4388 if (iterator == null) { 4389 return null; 4390 } 4391 if (!iterator.hasNext()) { 4392 return EMPTY; 4393 } 4394 return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(separator), EMPTY, EMPTY, StringUtils::toStringOrEmpty)); 4395 } 4396 4397 /** 4398 * Joins the elements of the provided {@link List} into a single String 4399 * containing the provided list of elements. 4400 * 4401 * <p>No delimiter is added before or after the list. 4402 * Null objects or empty strings within the array are represented by 4403 * empty strings.</p> 4404 * 4405 * <pre> 4406 * StringUtils.join(null, *) = null 4407 * StringUtils.join([], *) = "" 4408 * StringUtils.join([null], *) = "" 4409 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4410 * StringUtils.join(["a", "b", "c"], null) = "abc" 4411 * StringUtils.join([null, "", "a"], ';') = ";;a" 4412 * </pre> 4413 * 4414 * @param list the {@link List} of values to join together, may be null 4415 * @param separator the separator character to use 4416 * @param startIndex the first index to start joining from. It is 4417 * an error to pass in a start index past the end of the list 4418 * @param endIndex the index to stop joining from (exclusive). It is 4419 * an error to pass in an end index past the end of the list 4420 * @return the joined String, {@code null} if null list input 4421 * @since 3.8 4422 */ 4423 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4424 if (list == null) { 4425 return null; 4426 } 4427 final int noOfItems = endIndex - startIndex; 4428 if (noOfItems <= 0) { 4429 return EMPTY; 4430 } 4431 final List<?> subList = list.subList(startIndex, endIndex); 4432 return join(subList.iterator(), separator); 4433 } 4434 4435 /** 4436 * Joins the elements of the provided {@link List} into a single String 4437 * containing the provided list of elements. 4438 * 4439 * <p>No delimiter is added before or after the list. 4440 * Null objects or empty strings within the array are represented by 4441 * empty strings.</p> 4442 * 4443 * <pre> 4444 * StringUtils.join(null, *) = null 4445 * StringUtils.join([], *) = "" 4446 * StringUtils.join([null], *) = "" 4447 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4448 * StringUtils.join(["a", "b", "c"], null) = "abc" 4449 * StringUtils.join([null, "", "a"], ';') = ";;a" 4450 * </pre> 4451 * 4452 * @param list the {@link List} of values to join together, may be null 4453 * @param separator the separator character to use 4454 * @param startIndex the first index to start joining from. It is 4455 * an error to pass in a start index past the end of the list 4456 * @param endIndex the index to stop joining from (exclusive). It is 4457 * an error to pass in an end index past the end of the list 4458 * @return the joined String, {@code null} if null list input 4459 * @since 3.8 4460 */ 4461 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4462 if (list == null) { 4463 return null; 4464 } 4465 final int noOfItems = endIndex - startIndex; 4466 if (noOfItems <= 0) { 4467 return EMPTY; 4468 } 4469 final List<?> subList = list.subList(startIndex, endIndex); 4470 return join(subList.iterator(), separator); 4471 } 4472 4473 4474 /** 4475 * Joins the elements of the provided array into a single String containing the provided list of elements. 4476 * 4477 * <p> 4478 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4479 * by empty strings. 4480 * </p> 4481 * 4482 * <pre> 4483 * StringUtils.join(null, *) = null 4484 * StringUtils.join([], *) = "" 4485 * StringUtils.join([null], *) = "" 4486 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4487 * StringUtils.join([1, 2, 3], null) = "123" 4488 * </pre> 4489 * 4490 * @param array 4491 * the array of values to join together, may be null 4492 * @param separator 4493 * the separator character to use 4494 * @return the joined String, {@code null} if null array input 4495 * @since 3.2 4496 */ 4497 public static String join(final long[] array, final char separator) { 4498 if (array == null) { 4499 return null; 4500 } 4501 return join(array, separator, 0, array.length); 4502 } 4503 4504 /** 4505 * Joins the elements of the provided array into a single String containing the provided list of elements. 4506 * 4507 * <p> 4508 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4509 * by empty strings. 4510 * </p> 4511 * 4512 * <pre> 4513 * StringUtils.join(null, *) = null 4514 * StringUtils.join([], *) = "" 4515 * StringUtils.join([null], *) = "" 4516 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4517 * StringUtils.join([1, 2, 3], null) = "123" 4518 * </pre> 4519 * 4520 * @param array 4521 * the array of values to join together, may be null 4522 * @param delimiter 4523 * the separator character to use 4524 * @param startIndex 4525 * the first index to start joining from. It is an error to pass in a start index past the end of the 4526 * array 4527 * @param endIndex 4528 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4529 * the array 4530 * @return the joined String, {@code null} if null array input 4531 * @since 3.2 4532 */ 4533 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4534 if (array == null) { 4535 return null; 4536 } 4537 if (endIndex - startIndex <= 0) { 4538 return EMPTY; 4539 } 4540 final StringBuilder stringBuilder = new StringBuilder(); 4541 for (int i = startIndex; i < endIndex; i++) { 4542 stringBuilder 4543 .append(array[i]) 4544 .append(delimiter); 4545 } 4546 return stringBuilder.substring(0, stringBuilder.length() - 1); 4547 } 4548 4549 /** 4550 * Joins the elements of the provided array into a single String 4551 * containing the provided list of elements. 4552 * 4553 * <p>No delimiter is added before or after the list. 4554 * Null objects or empty strings within the array are represented by 4555 * empty strings.</p> 4556 * 4557 * <pre> 4558 * StringUtils.join(null, *) = null 4559 * StringUtils.join([], *) = "" 4560 * StringUtils.join([null], *) = "" 4561 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4562 * StringUtils.join(["a", "b", "c"], null) = "abc" 4563 * StringUtils.join([null, "", "a"], ';') = ";;a" 4564 * </pre> 4565 * 4566 * @param array the array of values to join together, may be null 4567 * @param delimiter the separator character to use 4568 * @return the joined String, {@code null} if null array input 4569 * @since 2.0 4570 */ 4571 public static String join(final Object[] array, final char delimiter) { 4572 if (array == null) { 4573 return null; 4574 } 4575 return join(array, delimiter, 0, array.length); 4576 } 4577 4578 /** 4579 * Joins the elements of the provided array into a single String 4580 * containing the provided list of elements. 4581 * 4582 * <p>No delimiter is added before or after the list. 4583 * Null objects or empty strings within the array are represented by 4584 * empty strings.</p> 4585 * 4586 * <pre> 4587 * StringUtils.join(null, *) = null 4588 * StringUtils.join([], *) = "" 4589 * StringUtils.join([null], *) = "" 4590 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4591 * StringUtils.join(["a", "b", "c"], null) = "abc" 4592 * StringUtils.join([null, "", "a"], ';') = ";;a" 4593 * </pre> 4594 * 4595 * @param array the array of values to join together, may be null 4596 * @param delimiter the separator character to use 4597 * @param startIndex the first index to start joining from. It is 4598 * an error to pass in a start index past the end of the array 4599 * @param endIndex the index to stop joining from (exclusive). It is 4600 * an error to pass in an end index past the end of the array 4601 * @return the joined String, {@code null} if null array input 4602 * @since 2.0 4603 */ 4604 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4605 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4606 } 4607 4608 /** 4609 * Joins the elements of the provided array into a single String 4610 * containing the provided list of elements. 4611 * 4612 * <p>No delimiter is added before or after the list. 4613 * A {@code null} separator is the same as an empty String (""). 4614 * Null objects or empty strings within the array are represented by 4615 * empty strings.</p> 4616 * 4617 * <pre> 4618 * StringUtils.join(null, *) = null 4619 * StringUtils.join([], *) = "" 4620 * StringUtils.join([null], *) = "" 4621 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4622 * StringUtils.join(["a", "b", "c"], null) = "abc" 4623 * StringUtils.join(["a", "b", "c"], "") = "abc" 4624 * StringUtils.join([null, "", "a"], ',') = ",,a" 4625 * </pre> 4626 * 4627 * @param array the array of values to join together, may be null 4628 * @param delimiter the separator character to use, null treated as "" 4629 * @return the joined String, {@code null} if null array input 4630 */ 4631 public static String join(final Object[] array, final String delimiter) { 4632 return array != null ? join(array, toStringOrEmpty(delimiter), 0, array.length) : null; 4633 } 4634 4635 /** 4636 * Joins the elements of the provided array into a single String 4637 * containing the provided list of elements. 4638 * 4639 * <p>No delimiter is added before or after the list. 4640 * A {@code null} separator is the same as an empty String (""). 4641 * Null objects or empty strings within the array are represented by 4642 * empty strings.</p> 4643 * 4644 * <pre> 4645 * StringUtils.join(null, *, *, *) = null 4646 * StringUtils.join([], *, *, *) = "" 4647 * StringUtils.join([null], *, *, *) = "" 4648 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4649 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4650 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4651 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4652 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4653 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4654 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4655 * </pre> 4656 * 4657 * @param array the array of values to join together, may be null 4658 * @param delimiter the separator character to use, null treated as "" 4659 * @param startIndex the first index to start joining from. 4660 * @param endIndex the index to stop joining from (exclusive). 4661 * @return the joined String, {@code null} if null array input; or the empty string 4662 * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by 4663 * {@code endIndex - startIndex} 4664 * @throws ArrayIndexOutOfBoundsException ife<br> 4665 * {@code startIndex < 0} or <br> 4666 * {@code startIndex >= array.length()} or <br> 4667 * {@code endIndex < 0} or <br> 4668 * {@code endIndex > array.length()} 4669 */ 4670 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4671 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4672 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, StringUtils::toStringOrEmpty)) : 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. Null objects or empty strings within the array are represented 4680 * by empty strings. 4681 * </p> 4682 * 4683 * <pre> 4684 * StringUtils.join(null, *) = null 4685 * StringUtils.join([], *) = "" 4686 * StringUtils.join([null], *) = "" 4687 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4688 * StringUtils.join([1, 2, 3], null) = "123" 4689 * </pre> 4690 * 4691 * @param array 4692 * the array of values to join together, may be null 4693 * @param delimiter 4694 * the separator character to use 4695 * @return the joined String, {@code null} if null array input 4696 * @since 3.2 4697 */ 4698 public static String join(final short[] array, final char delimiter) { 4699 if (array == null) { 4700 return null; 4701 } 4702 return join(array, delimiter, 0, array.length); 4703 } 4704 4705 /** 4706 * Joins the elements of the provided array into a single String containing the provided list of elements. 4707 * 4708 * <p> 4709 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4710 * by empty strings. 4711 * </p> 4712 * 4713 * <pre> 4714 * StringUtils.join(null, *) = null 4715 * StringUtils.join([], *) = "" 4716 * StringUtils.join([null], *) = "" 4717 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4718 * StringUtils.join([1, 2, 3], null) = "123" 4719 * </pre> 4720 * 4721 * @param array 4722 * the array of values to join together, may be null 4723 * @param delimiter 4724 * the separator character to use 4725 * @param startIndex 4726 * the first index to start joining from. It is an error to pass in a start index past the end of the 4727 * array 4728 * @param endIndex 4729 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4730 * the array 4731 * @return the joined String, {@code null} if null array input 4732 * @since 3.2 4733 */ 4734 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4735 if (array == null) { 4736 return null; 4737 } 4738 if (endIndex - startIndex <= 0) { 4739 return EMPTY; 4740 } 4741 final StringBuilder stringBuilder = new StringBuilder(); 4742 for (int i = startIndex; i < endIndex; i++) { 4743 stringBuilder 4744 .append(array[i]) 4745 .append(delimiter); 4746 } 4747 return stringBuilder.substring(0, stringBuilder.length() - 1); 4748 } 4749 4750 /** 4751 * Joins the elements of the provided array into a single String 4752 * containing the provided list of elements. 4753 * 4754 * <p>No separator is added to the joined String. 4755 * Null objects or empty strings within the array are represented by 4756 * empty strings.</p> 4757 * 4758 * <pre> 4759 * StringUtils.join(null) = null 4760 * StringUtils.join([]) = "" 4761 * StringUtils.join([null]) = "" 4762 * StringUtils.join(["a", "b", "c"]) = "abc" 4763 * StringUtils.join([null, "", "a"]) = "a" 4764 * </pre> 4765 * 4766 * @param <T> the specific type of values to join together 4767 * @param elements the values to join together, may be null 4768 * @return the joined String, {@code null} if null array input 4769 * @since 2.0 4770 * @since 3.0 Changed signature to use varargs 4771 */ 4772 @SafeVarargs 4773 public static <T> String join(final T... elements) { 4774 return join(elements, null); 4775 } 4776 4777 /** 4778 * Joins the elements of the provided varargs into a 4779 * single String containing the provided elements. 4780 * 4781 * <p>No delimiter is added before or after the list. 4782 * {@code null} elements and separator are treated as empty Strings ("").</p> 4783 * 4784 * <pre> 4785 * StringUtils.joinWith(",", {"a", "b"}) = "a,b" 4786 * StringUtils.joinWith(",", {"a", "b",""}) = "a,b," 4787 * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b" 4788 * StringUtils.joinWith(null, {"a", "b"}) = "ab" 4789 * </pre> 4790 * 4791 * @param delimiter the separator character to use, null treated as "" 4792 * @param array the varargs providing the values to join together. {@code null} elements are treated as "" 4793 * @return the joined String. 4794 * @throws IllegalArgumentException if a null varargs is provided 4795 * @since 3.5 4796 */ 4797 public static String joinWith(final String delimiter, final Object... array) { 4798 if (array == null) { 4799 throw new IllegalArgumentException("Object varargs must not be null"); 4800 } 4801 return join(array, delimiter); 4802 } 4803 4804 /** 4805 * Finds the last index within a CharSequence, handling {@code null}. 4806 * This method uses {@link String#lastIndexOf(String)} if possible. 4807 * 4808 * <p>A {@code null} CharSequence will return {@code -1}.</p> 4809 * 4810 * <pre> 4811 * StringUtils.lastIndexOf(null, *) = -1 4812 * StringUtils.lastIndexOf(*, null) = -1 4813 * StringUtils.lastIndexOf("", "") = 0 4814 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4815 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4816 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4817 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4818 * </pre> 4819 * 4820 * @param seq the CharSequence to check, may be null 4821 * @param searchSeq the CharSequence to find, may be null 4822 * @return the last index of the search String, 4823 * -1 if no match or {@code null} string input 4824 * @since 2.0 4825 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4826 */ 4827 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4828 if (seq == null) { 4829 return INDEX_NOT_FOUND; 4830 } 4831 return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length()); 4832 } 4833 4834 /** 4835 * Finds the last index within a CharSequence, handling {@code null}. 4836 * This method uses {@link String#lastIndexOf(String, int)} if possible. 4837 * 4838 * <p>A {@code null} CharSequence will return {@code -1}. 4839 * A negative start position returns {@code -1}. 4840 * An empty ("") search CharSequence always matches unless the start position is negative. 4841 * A start position greater than the string length searches the whole string. 4842 * The search starts at the startPos and works backwards; matches starting after the start 4843 * position are ignored. 4844 * </p> 4845 * 4846 * <pre> 4847 * StringUtils.lastIndexOf(null, *, *) = -1 4848 * StringUtils.lastIndexOf(*, null, *) = -1 4849 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4850 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4851 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4852 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4853 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4854 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4855 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4856 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4857 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4858 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4859 * </pre> 4860 * 4861 * @param seq the CharSequence to check, may be null 4862 * @param searchSeq the CharSequence to find, may be null 4863 * @param startPos the start position, negative treated as zero 4864 * @return the last index of the search CharSequence (always ≤ startPos), 4865 * -1 if no match or {@code null} string input 4866 * @since 2.0 4867 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4868 */ 4869 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4870 return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos); 4871 } 4872 4873 /** 4874 * Returns the index within {@code seq} of the last occurrence of 4875 * the specified character. For values of {@code searchChar} in the 4876 * range from 0 to 0xFFFF (inclusive), the index (in Unicode code 4877 * units) returned is the largest value <i>k</i> such that: 4878 * <blockquote><pre> 4879 * this.charAt(<i>k</i>) == searchChar 4880 * </pre></blockquote> 4881 * is true. For other values of {@code searchChar}, it is the 4882 * largest value <i>k</i> such that: 4883 * <blockquote><pre> 4884 * this.codePointAt(<i>k</i>) == searchChar 4885 * </pre></blockquote> 4886 * is true. In either case, if no such character occurs in this 4887 * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4888 * {@link CharSequence} will return {@code -1}. The 4889 * {@code seq} {@link CharSequence} object is searched backwards 4890 * starting at the last character. 4891 * 4892 * <pre> 4893 * StringUtils.lastIndexOf(null, *) = -1 4894 * StringUtils.lastIndexOf("", *) = -1 4895 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4896 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4897 * </pre> 4898 * 4899 * @param seq the {@link CharSequence} to check, may be null 4900 * @param searchChar the character to find 4901 * @return the last index of the search character, 4902 * -1 if no match or {@code null} string input 4903 * @since 2.0 4904 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4905 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4906 */ 4907 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4908 if (isEmpty(seq)) { 4909 return INDEX_NOT_FOUND; 4910 } 4911 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4912 } 4913 4914 /** 4915 * Returns the index within {@code seq} of the last occurrence of 4916 * the specified character, searching backward starting at the 4917 * specified index. For values of {@code searchChar} in the range 4918 * from 0 to 0xFFFF (inclusive), the index returned is the largest 4919 * value <i>k</i> such that: 4920 * <blockquote><pre> 4921 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4922 * </pre></blockquote> 4923 * is true. For other values of {@code searchChar}, it is the 4924 * largest value <i>k</i> such that: 4925 * <blockquote><pre> 4926 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4927 * </pre></blockquote> 4928 * is true. In either case, if no such character occurs in {@code seq} 4929 * at or before position {@code startPos}, then 4930 * {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4931 * {@link CharSequence} will return {@code -1}. A start position greater 4932 * than the string length searches the whole string. 4933 * The search starts at the {@code startPos} and works backwards; 4934 * matches starting after the start position are ignored. 4935 * 4936 * <p>All indices are specified in {@code char} values 4937 * (Unicode code units). 4938 * 4939 * <pre> 4940 * StringUtils.lastIndexOf(null, *, *) = -1 4941 * StringUtils.lastIndexOf("", *, *) = -1 4942 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4943 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4944 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4945 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4946 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4947 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 4948 * </pre> 4949 * 4950 * @param seq the CharSequence to check, may be null 4951 * @param searchChar the character to find 4952 * @param startPos the start position 4953 * @return the last index of the search character (always ≤ startPos), 4954 * -1 if no match or {@code null} string input 4955 * @since 2.0 4956 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 4957 */ 4958 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 4959 if (isEmpty(seq)) { 4960 return INDEX_NOT_FOUND; 4961 } 4962 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 4963 } 4964 4965 /** 4966 * Find the latest index of any substring in a set of potential substrings. 4967 * 4968 * <p>A {@code null} CharSequence will return {@code -1}. 4969 * A {@code null} search array will return {@code -1}. 4970 * A {@code null} or zero length search array entry will be ignored, 4971 * but a search array containing "" will return the length of {@code str} 4972 * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p> 4973 * 4974 * <pre> 4975 * StringUtils.lastIndexOfAny(null, *) = -1 4976 * StringUtils.lastIndexOfAny(*, null) = -1 4977 * StringUtils.lastIndexOfAny(*, []) = -1 4978 * StringUtils.lastIndexOfAny(*, [null]) = -1 4979 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 4980 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 4981 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4982 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4983 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 4984 * </pre> 4985 * 4986 * @param str the CharSequence to check, may be null 4987 * @param searchStrs the CharSequences to search for, may be null 4988 * @return the last index of any of the CharSequences, -1 if no match 4989 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 4990 */ 4991 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 4992 if (str == null || searchStrs == null) { 4993 return INDEX_NOT_FOUND; 4994 } 4995 int ret = INDEX_NOT_FOUND; 4996 int tmp; 4997 for (final CharSequence search : searchStrs) { 4998 if (search == null) { 4999 continue; 5000 } 5001 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 5002 if (tmp > ret) { 5003 ret = tmp; 5004 } 5005 } 5006 return ret; 5007 } 5008 5009 /** 5010 * Case in-sensitive find of the last index within a CharSequence. 5011 * 5012 * <p>A {@code null} CharSequence will return {@code -1}. 5013 * A negative start position returns {@code -1}. 5014 * An empty ("") search CharSequence always matches unless the start position is negative. 5015 * A start position greater than the string length searches the whole string.</p> 5016 * 5017 * <pre> 5018 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5019 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5020 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5021 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5022 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5023 * </pre> 5024 * 5025 * @param str the CharSequence to check, may be null 5026 * @param searchStr the CharSequence to find, may be null 5027 * @return the first index of the search CharSequence, 5028 * -1 if no match or {@code null} string input 5029 * @since 2.5 5030 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5031 */ 5032 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5033 if (str == null || searchStr == null) { 5034 return INDEX_NOT_FOUND; 5035 } 5036 return lastIndexOfIgnoreCase(str, searchStr, str.length()); 5037 } 5038 5039 /** 5040 * Case in-sensitive find of the last index within a CharSequence 5041 * from the specified position. 5042 * 5043 * <p>A {@code null} CharSequence will return {@code -1}. 5044 * A negative start position returns {@code -1}. 5045 * An empty ("") search CharSequence always matches unless the start position is negative. 5046 * A start position greater than the string length searches the whole string. 5047 * The search starts at the startPos and works backwards; matches starting after the start 5048 * position are ignored. 5049 * </p> 5050 * 5051 * <pre> 5052 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5053 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5054 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5055 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5056 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5057 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5058 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5059 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5060 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5061 * </pre> 5062 * 5063 * @param str the CharSequence to check, may be null 5064 * @param searchStr the CharSequence to find, may be null 5065 * @param startPos the start position 5066 * @return the last index of the search CharSequence (always ≤ startPos), 5067 * -1 if no match or {@code null} input 5068 * @since 2.5 5069 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5070 */ 5071 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 5072 if (str == null || searchStr == null) { 5073 return INDEX_NOT_FOUND; 5074 } 5075 final int searchStrLength = searchStr.length(); 5076 final int strLength = str.length(); 5077 if (startPos > strLength - searchStrLength) { 5078 startPos = strLength - searchStrLength; 5079 } 5080 if (startPos < 0) { 5081 return INDEX_NOT_FOUND; 5082 } 5083 if (searchStrLength == 0) { 5084 return startPos; 5085 } 5086 5087 for (int i = startPos; i >= 0; i--) { 5088 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStrLength)) { 5089 return i; 5090 } 5091 } 5092 return INDEX_NOT_FOUND; 5093 } 5094 5095 /** 5096 * Finds the n-th last index within a String, handling {@code null}. 5097 * This method uses {@link String#lastIndexOf(String)}. 5098 * 5099 * <p>A {@code null} String will return {@code -1}.</p> 5100 * 5101 * <pre> 5102 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5103 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5104 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5105 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5106 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5107 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5108 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5109 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5110 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5111 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5112 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5113 * </pre> 5114 * 5115 * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p> 5116 * 5117 * <pre> 5118 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5119 * </pre> 5120 * 5121 * @param str the CharSequence to check, may be null 5122 * @param searchStr the CharSequence to find, may be null 5123 * @param ordinal the n-th last {@code searchStr} to find 5124 * @return the n-th last index of the search CharSequence, 5125 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5126 * @since 2.5 5127 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5128 */ 5129 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5130 return ordinalIndexOf(str, searchStr, ordinal, true); 5131 } 5132 5133 /** 5134 * Gets the leftmost {@code len} characters of a String. 5135 * 5136 * <p>If {@code len} characters are not available, or the 5137 * String is {@code null}, the String will be returned without 5138 * an exception. An empty String is returned if len is negative.</p> 5139 * 5140 * <pre> 5141 * StringUtils.left(null, *) = null 5142 * StringUtils.left(*, -ve) = "" 5143 * StringUtils.left("", *) = "" 5144 * StringUtils.left("abc", 0) = "" 5145 * StringUtils.left("abc", 2) = "ab" 5146 * StringUtils.left("abc", 4) = "abc" 5147 * </pre> 5148 * 5149 * @param str the String to get the leftmost characters from, may be null 5150 * @param len the length of the required String 5151 * @return the leftmost characters, {@code null} if null String input 5152 */ 5153 public static String left(final String str, final int len) { 5154 if (str == null) { 5155 return null; 5156 } 5157 if (len < 0) { 5158 return EMPTY; 5159 } 5160 if (str.length() <= len) { 5161 return str; 5162 } 5163 return str.substring(0, len); 5164 } 5165 5166 /** 5167 * Left pad a String with spaces (' '). 5168 * 5169 * <p>The String is padded to the size of {@code size}.</p> 5170 * 5171 * <pre> 5172 * StringUtils.leftPad(null, *) = null 5173 * StringUtils.leftPad("", 3) = " " 5174 * StringUtils.leftPad("bat", 3) = "bat" 5175 * StringUtils.leftPad("bat", 5) = " bat" 5176 * StringUtils.leftPad("bat", 1) = "bat" 5177 * StringUtils.leftPad("bat", -1) = "bat" 5178 * </pre> 5179 * 5180 * @param str the String to pad out, may be null 5181 * @param size the size to pad to 5182 * @return left padded String or original String if no padding is necessary, 5183 * {@code null} if null String input 5184 */ 5185 public static String leftPad(final String str, final int size) { 5186 return leftPad(str, size, ' '); 5187 } 5188 5189 /** 5190 * Left pad a String with a specified character. 5191 * 5192 * <p>Pad to a size of {@code size}.</p> 5193 * 5194 * <pre> 5195 * StringUtils.leftPad(null, *, *) = null 5196 * StringUtils.leftPad("", 3, 'z') = "zzz" 5197 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5198 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5199 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5200 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5201 * </pre> 5202 * 5203 * @param str the String to pad out, may be null 5204 * @param size the size to pad to 5205 * @param padChar the character to pad with 5206 * @return left padded String or original String if no padding is necessary, 5207 * {@code null} if null String input 5208 * @since 2.0 5209 */ 5210 public static String leftPad(final String str, final int size, final char padChar) { 5211 if (str == null) { 5212 return null; 5213 } 5214 final int pads = size - str.length(); 5215 if (pads <= 0) { 5216 return str; // returns original String when possible 5217 } 5218 if (pads > PAD_LIMIT) { 5219 return leftPad(str, size, String.valueOf(padChar)); 5220 } 5221 return repeat(padChar, pads).concat(str); 5222 } 5223 5224 /** 5225 * Left pad a String with a specified String. 5226 * 5227 * <p>Pad to a size of {@code size}.</p> 5228 * 5229 * <pre> 5230 * StringUtils.leftPad(null, *, *) = null 5231 * StringUtils.leftPad("", 3, "z") = "zzz" 5232 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5233 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5234 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5235 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5236 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5237 * StringUtils.leftPad("bat", 5, null) = " bat" 5238 * StringUtils.leftPad("bat", 5, "") = " bat" 5239 * </pre> 5240 * 5241 * @param str the String to pad out, may be null 5242 * @param size the size to pad to 5243 * @param padStr the String to pad with, null or empty treated as single space 5244 * @return left padded String or original String if no padding is necessary, 5245 * {@code null} if null String input 5246 */ 5247 public static String leftPad(final String str, final int size, String padStr) { 5248 if (str == null) { 5249 return null; 5250 } 5251 if (isEmpty(padStr)) { 5252 padStr = SPACE; 5253 } 5254 final int padLen = padStr.length(); 5255 final int strLen = str.length(); 5256 final int pads = size - strLen; 5257 if (pads <= 0) { 5258 return str; // returns original String when possible 5259 } 5260 if (padLen == 1 && pads <= PAD_LIMIT) { 5261 return leftPad(str, size, padStr.charAt(0)); 5262 } 5263 5264 if (pads == padLen) { 5265 return padStr.concat(str); 5266 } 5267 if (pads < padLen) { 5268 return padStr.substring(0, pads).concat(str); 5269 } 5270 final char[] padding = new char[pads]; 5271 final char[] padChars = padStr.toCharArray(); 5272 for (int i = 0; i < pads; i++) { 5273 padding[i] = padChars[i % padLen]; 5274 } 5275 return new String(padding).concat(str); 5276 } 5277 5278 /** 5279 * Gets a CharSequence length or {@code 0} if the CharSequence is 5280 * {@code null}. 5281 * 5282 * @param cs 5283 * a CharSequence or {@code null} 5284 * @return CharSequence length or {@code 0} if the CharSequence is 5285 * {@code null}. 5286 * @since 2.4 5287 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5288 */ 5289 public static int length(final CharSequence cs) { 5290 return cs == null ? 0 : cs.length(); 5291 } 5292 5293 /** 5294 * Converts a String to lower case as per {@link String#toLowerCase()}. 5295 * 5296 * <p>A {@code null} input String returns {@code null}.</p> 5297 * 5298 * <pre> 5299 * StringUtils.lowerCase(null) = null 5300 * StringUtils.lowerCase("") = "" 5301 * StringUtils.lowerCase("aBc") = "abc" 5302 * </pre> 5303 * 5304 * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, 5305 * the result of this method is affected by the current locale. 5306 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5307 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5308 * 5309 * @param str the String to lower case, may be null 5310 * @return the lower cased String, {@code null} if null String input 5311 */ 5312 public static String lowerCase(final String str) { 5313 if (str == null) { 5314 return null; 5315 } 5316 return str.toLowerCase(); 5317 } 5318 5319 /** 5320 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5321 * 5322 * <p>A {@code null} input String returns {@code null}.</p> 5323 * 5324 * <pre> 5325 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5326 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5327 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5328 * </pre> 5329 * 5330 * @param str the String to lower case, may be null 5331 * @param locale the locale that defines the case transformation rules, must not be null 5332 * @return the lower cased String, {@code null} if null String input 5333 * @since 2.5 5334 */ 5335 public static String lowerCase(final String str, final Locale locale) { 5336 if (str == null) { 5337 return null; 5338 } 5339 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5340 } 5341 5342 private static int[] matches(final CharSequence first, final CharSequence second) { 5343 final CharSequence max; 5344 final CharSequence min; 5345 if (first.length() > second.length()) { 5346 max = first; 5347 min = second; 5348 } else { 5349 max = second; 5350 min = first; 5351 } 5352 final int range = Math.max(max.length() / 2 - 1, 0); 5353 final int[] matchIndexes = new int[min.length()]; 5354 Arrays.fill(matchIndexes, -1); 5355 final boolean[] matchFlags = new boolean[max.length()]; 5356 int matches = 0; 5357 for (int mi = 0; mi < min.length(); mi++) { 5358 final char c1 = min.charAt(mi); 5359 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5360 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5361 matchIndexes[mi] = xi; 5362 matchFlags[xi] = true; 5363 matches++; 5364 break; 5365 } 5366 } 5367 } 5368 final char[] ms1 = new char[matches]; 5369 final char[] ms2 = new char[matches]; 5370 for (int i = 0, si = 0; i < min.length(); i++) { 5371 if (matchIndexes[i] != -1) { 5372 ms1[si] = min.charAt(i); 5373 si++; 5374 } 5375 } 5376 for (int i = 0, si = 0; i < max.length(); i++) { 5377 if (matchFlags[i]) { 5378 ms2[si] = max.charAt(i); 5379 si++; 5380 } 5381 } 5382 int transpositions = 0; 5383 for (int mi = 0; mi < ms1.length; mi++) { 5384 if (ms1[mi] != ms2[mi]) { 5385 transpositions++; 5386 } 5387 } 5388 int prefix = 0; 5389 for (int mi = 0; mi < min.length(); mi++) { 5390 if (first.charAt(mi) != second.charAt(mi)) { 5391 break; 5392 } 5393 prefix++; 5394 } 5395 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5396 } 5397 5398 /** 5399 * Gets {@code len} characters from the middle of a String. 5400 * 5401 * <p>If {@code len} characters are not available, the remainder 5402 * of the String will be returned without an exception. If the 5403 * String is {@code null}, {@code null} will be returned. 5404 * An empty String is returned if len is negative or exceeds the 5405 * length of {@code str}.</p> 5406 * 5407 * <pre> 5408 * StringUtils.mid(null, *, *) = null 5409 * StringUtils.mid(*, *, -ve) = "" 5410 * StringUtils.mid("", 0, *) = "" 5411 * StringUtils.mid("abc", 0, 2) = "ab" 5412 * StringUtils.mid("abc", 0, 4) = "abc" 5413 * StringUtils.mid("abc", 2, 4) = "c" 5414 * StringUtils.mid("abc", 4, 2) = "" 5415 * StringUtils.mid("abc", -2, 2) = "ab" 5416 * </pre> 5417 * 5418 * @param str the String to get the characters from, may be null 5419 * @param pos the position to start from, negative treated as zero 5420 * @param len the length of the required String 5421 * @return the middle characters, {@code null} if null String input 5422 */ 5423 public static String mid(final String str, int pos, final int len) { 5424 if (str == null) { 5425 return null; 5426 } 5427 if (len < 0 || pos > str.length()) { 5428 return EMPTY; 5429 } 5430 if (pos < 0) { 5431 pos = 0; 5432 } 5433 if (str.length() <= pos + len) { 5434 return str.substring(pos); 5435 } 5436 return str.substring(pos, pos + len); 5437 } 5438 5439 /** 5440 * Similar to <a 5441 * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize 5442 * -space</a> 5443 * 5444 * <p> 5445 * The function returns the argument string with whitespace normalized by using 5446 * {@code {@link #trim(String)}} to remove leading and trailing whitespace 5447 * and then replacing sequences of whitespace characters by a single space. 5448 * </p> 5449 * In XML Whitespace characters are the same as those allowed by the <a 5450 * href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+ 5451 * <p> 5452 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5453 * 5454 * <p>For reference:</p> 5455 * <ul> 5456 * <li>\x0B = vertical tab</li> 5457 * <li>\f = #xC = form feed</li> 5458 * <li>#x20 = space</li> 5459 * <li>#x9 = \t</li> 5460 * <li>#xA = \n</li> 5461 * <li>#xD = \r</li> 5462 * </ul> 5463 * 5464 * <p> 5465 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also 5466 * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char <= 32) from both 5467 * ends of this String. 5468 * </p> 5469 * 5470 * @see Pattern 5471 * @see #trim(String) 5472 * @see <a 5473 * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5474 * @param str the source String to normalize whitespaces from, may be null 5475 * @return the modified string with whitespace normalized, {@code null} if null String input 5476 * 5477 * @since 3.0 5478 */ 5479 public static String normalizeSpace(final String str) { 5480 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5481 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5482 if (isEmpty(str)) { 5483 return str; 5484 } 5485 final int size = str.length(); 5486 final char[] newChars = new char[size]; 5487 int count = 0; 5488 int whitespacesCount = 0; 5489 boolean startWhitespaces = true; 5490 for (int i = 0; i < size; i++) { 5491 final char actualChar = str.charAt(i); 5492 final boolean isWhitespace = Character.isWhitespace(actualChar); 5493 if (isWhitespace) { 5494 if (whitespacesCount == 0 && !startWhitespaces) { 5495 newChars[count++] = SPACE.charAt(0); 5496 } 5497 whitespacesCount++; 5498 } else { 5499 startWhitespaces = false; 5500 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5501 whitespacesCount = 0; 5502 } 5503 } 5504 if (startWhitespaces) { 5505 return EMPTY; 5506 } 5507 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5508 } 5509 5510 /** 5511 * Finds the n-th index within a CharSequence, handling {@code null}. 5512 * This method uses {@link String#indexOf(String)} if possible. 5513 * <p><b>Note:</b> The code starts looking for a match at the start of the target, 5514 * incrementing the starting index by one after each successful match 5515 * (unless {@code searchStr} is an empty string in which case the position 5516 * is never incremented and {@code 0} is returned immediately). 5517 * This means that matches may overlap.</p> 5518 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5519 * 5520 * <pre> 5521 * StringUtils.ordinalIndexOf(null, *, *) = -1 5522 * StringUtils.ordinalIndexOf(*, null, *) = -1 5523 * StringUtils.ordinalIndexOf("", "", *) = 0 5524 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5525 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5526 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5527 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5528 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5529 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5530 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5531 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5532 * </pre> 5533 * 5534 * <p>Matches may overlap:</p> 5535 * <pre> 5536 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5537 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5538 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5539 * 5540 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5541 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5542 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5543 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5544 * </pre> 5545 * 5546 * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p> 5547 * 5548 * <pre> 5549 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5550 * </pre> 5551 * 5552 * @param str the CharSequence to check, may be null 5553 * @param searchStr the CharSequence to find, may be null 5554 * @param ordinal the n-th {@code searchStr} to find 5555 * @return the n-th index of the search CharSequence, 5556 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5557 * @since 2.1 5558 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5559 */ 5560 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5561 return ordinalIndexOf(str, searchStr, ordinal, false); 5562 } 5563 5564 /** 5565 * Finds the n-th index within a String, handling {@code null}. 5566 * This method uses {@link String#indexOf(String)} if possible. 5567 * <p>Note that matches may overlap<p> 5568 * 5569 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5570 * 5571 * @param str the CharSequence to check, may be null 5572 * @param searchStr the CharSequence to find, may be null 5573 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5574 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf() 5575 * @return the n-th index of the search CharSequence, 5576 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5577 */ 5578 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5579 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5580 if (str == null || searchStr == null || ordinal <= 0) { 5581 return INDEX_NOT_FOUND; 5582 } 5583 if (searchStr.length() == 0) { 5584 return lastIndex ? str.length() : 0; 5585 } 5586 int found = 0; 5587 // set the initial index beyond the end of the string 5588 // this is to allow for the initial index decrement/increment 5589 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5590 do { 5591 if (lastIndex) { 5592 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5593 } else { 5594 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5595 } 5596 if (index < 0) { 5597 return index; 5598 } 5599 found++; 5600 } while (found < ordinal); 5601 return index; 5602 } 5603 5604 /** 5605 * Overlays part of a String with another String. 5606 * 5607 * <p>A {@code null} string input returns {@code null}. 5608 * A negative index is treated as zero. 5609 * An index greater than the string length is treated as the string length. 5610 * The start index is always the smaller of the two indices.</p> 5611 * 5612 * <pre> 5613 * StringUtils.overlay(null, *, *, *) = null 5614 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5615 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5616 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5617 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5618 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5619 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5620 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5621 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5622 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5623 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5624 * </pre> 5625 * 5626 * @param str the String to do overlaying in, may be null 5627 * @param overlay the String to overlay, may be null 5628 * @param start the position to start overlaying at 5629 * @param end the position to stop overlaying before 5630 * @return overlayed String, {@code null} if null String input 5631 * @since 2.0 5632 */ 5633 public static String overlay(final String str, String overlay, int start, int end) { 5634 if (str == null) { 5635 return null; 5636 } 5637 if (overlay == null) { 5638 overlay = EMPTY; 5639 } 5640 final int len = str.length(); 5641 if (start < 0) { 5642 start = 0; 5643 } 5644 if (start > len) { 5645 start = len; 5646 } 5647 if (end < 0) { 5648 end = 0; 5649 } 5650 if (end > len) { 5651 end = len; 5652 } 5653 if (start > end) { 5654 final int temp = start; 5655 start = end; 5656 end = temp; 5657 } 5658 return str.substring(0, start) + 5659 overlay + 5660 str.substring(end); 5661 } 5662 5663 /** 5664 * Prepends the prefix to the start of the string if the string does not 5665 * already start with any of the prefixes. 5666 * 5667 * @param str The string. 5668 * @param prefix The prefix to prepend to the start of the string. 5669 * @param ignoreCase Indicates whether the compare should ignore case. 5670 * @param prefixes Additional prefixes that are valid (optional). 5671 * 5672 * @return A new String if prefix was prepended, the same string otherwise. 5673 */ 5674 private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) { 5675 if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) { 5676 return str; 5677 } 5678 if (ArrayUtils.isNotEmpty(prefixes)) { 5679 for (final CharSequence p : prefixes) { 5680 if (startsWith(str, p, ignoreCase)) { 5681 return str; 5682 } 5683 } 5684 } 5685 return prefix.toString() + str; 5686 } 5687 5688 /** 5689 * Prepends the prefix to the start of the string if the string does not 5690 * already start with any of the prefixes. 5691 * 5692 * <pre> 5693 * StringUtils.prependIfMissing(null, null) = null 5694 * StringUtils.prependIfMissing("abc", null) = "abc" 5695 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5696 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5697 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5698 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5699 * </pre> 5700 * <p>With additional prefixes,</p> 5701 * <pre> 5702 * StringUtils.prependIfMissing(null, null, null) = null 5703 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5704 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5705 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5706 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5707 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5708 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5709 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5710 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5711 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5712 * </pre> 5713 * 5714 * @param str The string. 5715 * @param prefix The prefix to prepend to the start of the string. 5716 * @param prefixes Additional prefixes that are valid. 5717 * 5718 * @return A new String if prefix was prepended, the same string otherwise. 5719 * 5720 * @since 3.2 5721 */ 5722 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5723 return prependIfMissing(str, prefix, false, prefixes); 5724 } 5725 5726 /** 5727 * Prepends the prefix to the start of the string if the string does not 5728 * already start, case-insensitive, with any of the prefixes. 5729 * 5730 * <pre> 5731 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5732 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5733 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5734 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5735 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5736 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5737 * </pre> 5738 * <p>With additional prefixes,</p> 5739 * <pre> 5740 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5741 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5742 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5743 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5744 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5745 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5746 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5747 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5748 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5749 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5750 * </pre> 5751 * 5752 * @param str The string. 5753 * @param prefix The prefix to prepend to the start of the string. 5754 * @param prefixes Additional prefixes that are valid (optional). 5755 * 5756 * @return A new String if prefix was prepended, the same string otherwise. 5757 * 5758 * @since 3.2 5759 */ 5760 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5761 return prependIfMissing(str, prefix, true, prefixes); 5762 } 5763 5764 /** 5765 * Removes all occurrences of a character from within the source string. 5766 * 5767 * <p>A {@code null} source string will return {@code null}. 5768 * An empty ("") source string will return the empty string.</p> 5769 * 5770 * <pre> 5771 * StringUtils.remove(null, *) = null 5772 * StringUtils.remove("", *) = "" 5773 * StringUtils.remove("queued", 'u') = "qeed" 5774 * StringUtils.remove("queued", 'z') = "queued" 5775 * </pre> 5776 * 5777 * @param str the source String to search, may be null 5778 * @param remove the char to search for and remove, may be null 5779 * @return the substring with the char removed if found, 5780 * {@code null} if null String input 5781 * @since 2.1 5782 */ 5783 public static String remove(final String str, final char remove) { 5784 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5785 return str; 5786 } 5787 final char[] chars = str.toCharArray(); 5788 int pos = 0; 5789 for (int i = 0; i < chars.length; i++) { 5790 if (chars[i] != remove) { 5791 chars[pos++] = chars[i]; 5792 } 5793 } 5794 return new String(chars, 0, pos); 5795 } 5796 5797 /** 5798 * Removes all occurrences of a substring from within the source string. 5799 * 5800 * <p>A {@code null} source string will return {@code null}. 5801 * An empty ("") source string will return the empty string. 5802 * A {@code null} remove string will return the source string. 5803 * An empty ("") remove string will return the source string.</p> 5804 * 5805 * <pre> 5806 * StringUtils.remove(null, *) = null 5807 * StringUtils.remove("", *) = "" 5808 * StringUtils.remove(*, null) = * 5809 * StringUtils.remove(*, "") = * 5810 * StringUtils.remove("queued", "ue") = "qd" 5811 * StringUtils.remove("queued", "zz") = "queued" 5812 * </pre> 5813 * 5814 * @param str the source String to search, may be null 5815 * @param remove the String to search for and remove, may be null 5816 * @return the substring with the string removed if found, 5817 * {@code null} if null String input 5818 * @since 2.1 5819 */ 5820 public static String remove(final String str, final String remove) { 5821 if (isEmpty(str) || isEmpty(remove)) { 5822 return str; 5823 } 5824 return replace(str, remove, EMPTY, -1); 5825 } 5826 5827 /** 5828 * Removes each substring of the text String that matches the given regular expression. 5829 * 5830 * This method is a {@code null} safe equivalent to: 5831 * <ul> 5832 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5833 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5834 * </ul> 5835 * 5836 * <p>A {@code null} reference passed to this method is a no-op.</p> 5837 * 5838 * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option 5839 * is NOT automatically added. 5840 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5841 * DOTALL is also known as single-line mode in Perl.</p> 5842 * 5843 * <pre> 5844 * StringUtils.removeAll(null, *) = null 5845 * StringUtils.removeAll("any", (String) null) = "any" 5846 * StringUtils.removeAll("any", "") = "any" 5847 * StringUtils.removeAll("any", ".*") = "" 5848 * StringUtils.removeAll("any", ".+") = "" 5849 * StringUtils.removeAll("abc", ".?") = "" 5850 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5851 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5852 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5853 * </pre> 5854 * 5855 * @param text text to remove from, may be null 5856 * @param regex the regular expression to which this string is to be matched 5857 * @return the text with any removes processed, 5858 * {@code null} if null String input 5859 * 5860 * @throws java.util.regex.PatternSyntaxException 5861 * if the regular expression's syntax is invalid 5862 * 5863 * @see #replaceAll(String, String, String) 5864 * @see #removePattern(String, String) 5865 * @see String#replaceAll(String, String) 5866 * @see java.util.regex.Pattern 5867 * @see java.util.regex.Pattern#DOTALL 5868 * @since 3.5 5869 * 5870 * @deprecated Moved to RegExUtils. 5871 */ 5872 @Deprecated 5873 public static String removeAll(final String text, final String regex) { 5874 return RegExUtils.removeAll(text, regex); 5875 } 5876 5877 /** 5878 * Removes a substring only if it is at the end of a source string, 5879 * otherwise returns the source string. 5880 * 5881 * <p>A {@code null} source string will return {@code null}. 5882 * An empty ("") source string will return the empty string. 5883 * A {@code null} search string will return the source string.</p> 5884 * 5885 * <pre> 5886 * StringUtils.removeEnd(null, *) = null 5887 * StringUtils.removeEnd("", *) = "" 5888 * StringUtils.removeEnd(*, null) = * 5889 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5890 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5891 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5892 * StringUtils.removeEnd("abc", "") = "abc" 5893 * </pre> 5894 * 5895 * @param str the source String to search, may be null 5896 * @param remove the String to search for and remove, may be null 5897 * @return the substring with the string removed if found, 5898 * {@code null} if null String input 5899 * @since 2.1 5900 */ 5901 public static String removeEnd(final String str, final String remove) { 5902 if (isEmpty(str) || isEmpty(remove)) { 5903 return str; 5904 } 5905 if (str.endsWith(remove)) { 5906 return str.substring(0, str.length() - remove.length()); 5907 } 5908 return str; 5909 } 5910 5911 /** 5912 * Case insensitive removal of a substring if it is at the end of a source string, 5913 * otherwise returns the source string. 5914 * 5915 * <p>A {@code null} source string will return {@code null}. 5916 * An empty ("") source string will return the empty string. 5917 * A {@code null} search string will return the source string.</p> 5918 * 5919 * <pre> 5920 * StringUtils.removeEndIgnoreCase(null, *) = null 5921 * StringUtils.removeEndIgnoreCase("", *) = "" 5922 * StringUtils.removeEndIgnoreCase(*, null) = * 5923 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5924 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5925 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5926 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5927 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 5928 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 5929 * </pre> 5930 * 5931 * @param str the source String to search, may be null 5932 * @param remove the String to search for (case-insensitive) and remove, may be null 5933 * @return the substring with the string removed if found, 5934 * {@code null} if null String input 5935 * @since 2.4 5936 */ 5937 public static String removeEndIgnoreCase(final String str, final String remove) { 5938 if (isEmpty(str) || isEmpty(remove)) { 5939 return str; 5940 } 5941 if (endsWithIgnoreCase(str, remove)) { 5942 return str.substring(0, str.length() - remove.length()); 5943 } 5944 return str; 5945 } 5946 5947 /** 5948 * Removes the first substring of the text string that matches the given regular expression. 5949 * 5950 * This method is a {@code null} safe equivalent to: 5951 * <ul> 5952 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 5953 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 5954 * </ul> 5955 * 5956 * <p>A {@code null} reference passed to this method is a no-op.</p> 5957 * 5958 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 5959 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5960 * DOTALL is also known as single-line mode in Perl.</p> 5961 * 5962 * <pre> 5963 * StringUtils.removeFirst(null, *) = null 5964 * StringUtils.removeFirst("any", (String) null) = "any" 5965 * StringUtils.removeFirst("any", "") = "any" 5966 * StringUtils.removeFirst("any", ".*") = "" 5967 * StringUtils.removeFirst("any", ".+") = "" 5968 * StringUtils.removeFirst("abc", ".?") = "bc" 5969 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5970 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5971 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5972 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5973 * </pre> 5974 * 5975 * @param text text to remove from, may be null 5976 * @param regex the regular expression to which this string is to be matched 5977 * @return the text with the first replacement processed, 5978 * {@code null} if null String input 5979 * 5980 * @throws java.util.regex.PatternSyntaxException 5981 * if the regular expression's syntax is invalid 5982 * 5983 * @see #replaceFirst(String, String, String) 5984 * @see String#replaceFirst(String, String) 5985 * @see java.util.regex.Pattern 5986 * @see java.util.regex.Pattern#DOTALL 5987 * @since 3.5 5988 * 5989 * @deprecated Moved to RegExUtils. 5990 */ 5991 @Deprecated 5992 public static String removeFirst(final String text, final String regex) { 5993 return replaceFirst(text, regex, EMPTY); 5994 } 5995 5996 /** 5997 * Case insensitive removal of all occurrences of a substring from within 5998 * the source string. 5999 * 6000 * <p> 6001 * A {@code null} source string will return {@code null}. An empty ("") 6002 * source string will return the empty string. A {@code null} remove string 6003 * will return the source string. An empty ("") remove string will return 6004 * 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 6019 * the source String to search, may be null 6020 * @param remove 6021 * the String to search for (case-insensitive) and remove, may be 6022 * null 6023 * @return the substring with the string removed if found, {@code null} if 6024 * null String input 6025 * @since 3.5 6026 */ 6027 public static String removeIgnoreCase(final String str, final String remove) { 6028 return replaceIgnoreCase(str, remove, EMPTY, -1); 6029 } 6030 6031 /** 6032 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6033 * 6034 * This call is a {@code null} safe equivalent to: 6035 * <ul> 6036 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6037 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6038 * </ul> 6039 * 6040 * <p>A {@code null} reference passed to this method is a no-op.</p> 6041 * 6042 * <pre> 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 6050 * the source string 6051 * @param regex 6052 * the regular expression to which this string is to be matched 6053 * @return The resulting {@link String} 6054 * @see #replacePattern(String, String, String) 6055 * @see String#replaceAll(String, String) 6056 * @see Pattern#DOTALL 6057 * @since 3.2 6058 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6059 * 6060 * @deprecated Moved to RegExUtils. 6061 */ 6062 @Deprecated 6063 public static String removePattern(final String source, final String regex) { 6064 return RegExUtils.removePattern(source, regex); 6065 } 6066 6067 /** 6068 * Removes a char only if it is at the beginning of a source string, 6069 * otherwise returns the source string. 6070 * 6071 * <p>A {@code null} source string will return {@code null}. 6072 * An empty ("") source string will return the empty string. 6073 * A {@code null} search char will return the source string.</p> 6074 * 6075 * <pre> 6076 * StringUtils.removeStart(null, *) = null 6077 * StringUtils.removeStart("", *) = "" 6078 * StringUtils.removeStart(*, null) = * 6079 * StringUtils.removeStart("/path", '/') = "path" 6080 * StringUtils.removeStart("path", '/') = "path" 6081 * StringUtils.removeStart("path", 0) = "path" 6082 * </pre> 6083 * 6084 * @param str the source String to search, may be null. 6085 * @param remove the char to search for and remove. 6086 * @return the substring with the char removed if found, 6087 * {@code null} if null String input. 6088 * @since 3.13.0 6089 */ 6090 public static String removeStart(final String str, final char remove) { 6091 if (isEmpty(str)) { 6092 return str; 6093 } 6094 return str.charAt(0) == remove ? str.substring(1) : str; 6095 } 6096 6097 /** 6098 * Removes a substring only if it is at the beginning of a source string, 6099 * otherwise returns the source string. 6100 * 6101 * <p>A {@code null} source string will return {@code null}. 6102 * An empty ("") source string will return the empty string. 6103 * A {@code null} search string will return the source string.</p> 6104 * 6105 * <pre> 6106 * StringUtils.removeStart(null, *) = null 6107 * StringUtils.removeStart("", *) = "" 6108 * StringUtils.removeStart(*, null) = * 6109 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6110 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6111 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6112 * StringUtils.removeStart("abc", "") = "abc" 6113 * </pre> 6114 * 6115 * @param str the source String to search, may be null 6116 * @param remove the String to search for and remove, may be null 6117 * @return the substring with the string removed if found, 6118 * {@code null} if null String input 6119 * @since 2.1 6120 */ 6121 public static String removeStart(final String str, final String remove) { 6122 if (isEmpty(str) || isEmpty(remove)) { 6123 return str; 6124 } 6125 if (str.startsWith(remove)) { 6126 return str.substring(remove.length()); 6127 } 6128 return str; 6129 } 6130 6131 /** 6132 * Case insensitive removal of a substring if it is at the beginning of a source string, 6133 * otherwise returns the source string. 6134 * 6135 * <p>A {@code null} source string will return {@code null}. 6136 * An empty ("") source string will return the empty string. 6137 * A {@code null} search string will return the source string.</p> 6138 * 6139 * <pre> 6140 * StringUtils.removeStartIgnoreCase(null, *) = null 6141 * StringUtils.removeStartIgnoreCase("", *) = "" 6142 * StringUtils.removeStartIgnoreCase(*, null) = * 6143 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6144 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6145 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6146 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6147 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6148 * </pre> 6149 * 6150 * @param str the source String to search, may be null 6151 * @param remove the String to search for (case-insensitive) and remove, may be null 6152 * @return the substring with the string removed if found, 6153 * {@code null} if null String input 6154 * @since 2.4 6155 */ 6156 public static String removeStartIgnoreCase(final String str, final String remove) { 6157 if (str != null && startsWithIgnoreCase(str, remove)) { 6158 return str.substring(length(remove)); 6159 } 6160 return str; 6161 } 6162 6163 /** 6164 * Returns padding using the specified delimiter repeated 6165 * to a given length. 6166 * 6167 * <pre> 6168 * StringUtils.repeat('e', 0) = "" 6169 * StringUtils.repeat('e', 3) = "eee" 6170 * StringUtils.repeat('e', -2) = "" 6171 * </pre> 6172 * 6173 * <p>Note: this method does not support padding with 6174 * <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6175 * as they require a pair of {@code char}s to be represented. 6176 * If you are needing to support full I18N of your applications 6177 * consider using {@link #repeat(String, int)} instead. 6178 * </p> 6179 * 6180 * @param ch character to repeat 6181 * @param repeat number of times to repeat char, negative treated as zero 6182 * @return String with repeated character 6183 * @see #repeat(String, int) 6184 */ 6185 public static String repeat(final char ch, final int repeat) { 6186 if (repeat <= 0) { 6187 return EMPTY; 6188 } 6189 final char[] buf = new char[repeat]; 6190 Arrays.fill(buf, ch); 6191 return new String(buf); 6192 } 6193 6194 /** 6195 * Repeat a String {@code repeat} times to form a 6196 * new String. 6197 * 6198 * <pre> 6199 * StringUtils.repeat(null, 2) = null 6200 * StringUtils.repeat("", 0) = "" 6201 * StringUtils.repeat("", 2) = "" 6202 * StringUtils.repeat("a", 3) = "aaa" 6203 * StringUtils.repeat("ab", 2) = "abab" 6204 * StringUtils.repeat("a", -2) = "" 6205 * </pre> 6206 * 6207 * @param str the String to repeat, may be null 6208 * @param repeat number of times to repeat str, negative treated as zero 6209 * @return a new String consisting of the original String repeated, 6210 * {@code null} if null String input 6211 */ 6212 public static String repeat(final String str, final int repeat) { 6213 // Performance tuned for 2.0 (JDK1.4) 6214 if (str == null) { 6215 return null; 6216 } 6217 if (repeat <= 0) { 6218 return EMPTY; 6219 } 6220 final int inputLength = str.length(); 6221 if (repeat == 1 || inputLength == 0) { 6222 return str; 6223 } 6224 if (inputLength == 1 && repeat <= PAD_LIMIT) { 6225 return repeat(str.charAt(0), repeat); 6226 } 6227 6228 final int outputLength = inputLength * repeat; 6229 switch (inputLength) { 6230 case 1 : 6231 return repeat(str.charAt(0), repeat); 6232 case 2 : 6233 final char ch0 = str.charAt(0); 6234 final char ch1 = str.charAt(1); 6235 final char[] output2 = new char[outputLength]; 6236 for (int i = repeat * 2 - 2; i >= 0; i--, i--) { 6237 output2[i] = ch0; 6238 output2[i + 1] = ch1; 6239 } 6240 return new String(output2); 6241 default : 6242 final StringBuilder buf = new StringBuilder(outputLength); 6243 for (int i = 0; i < repeat; i++) { 6244 buf.append(str); 6245 } 6246 return buf.toString(); 6247 } 6248 } 6249 6250 /** 6251 * Repeat a String {@code repeat} times to form a 6252 * new String, with a String separator injected each time. 6253 * 6254 * <pre> 6255 * StringUtils.repeat(null, null, 2) = null 6256 * StringUtils.repeat(null, "x", 2) = null 6257 * StringUtils.repeat("", null, 0) = "" 6258 * StringUtils.repeat("", "", 2) = "" 6259 * StringUtils.repeat("", "x", 3) = "xx" 6260 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6261 * </pre> 6262 * 6263 * @param str the String to repeat, may be null 6264 * @param separator the String to inject, may be null 6265 * @param repeat number of times to repeat str, negative treated as zero 6266 * @return a new String consisting of the original String repeated, 6267 * {@code null} if null String input 6268 * @since 2.5 6269 */ 6270 public static String repeat(final String str, final String separator, final int repeat) { 6271 if (str == null || separator == null) { 6272 return repeat(str, repeat); 6273 } 6274 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6275 final String result = repeat(str + separator, repeat); 6276 return removeEnd(result, separator); 6277 } 6278 6279 /** 6280 * Replaces all occurrences of a String within another String. 6281 * 6282 * <p>A {@code null} reference passed to this method is a no-op.</p> 6283 * 6284 * <pre> 6285 * StringUtils.replace(null, *, *) = null 6286 * StringUtils.replace("", *, *) = "" 6287 * StringUtils.replace("any", null, *) = "any" 6288 * StringUtils.replace("any", *, null) = "any" 6289 * StringUtils.replace("any", "", *) = "any" 6290 * StringUtils.replace("aba", "a", null) = "aba" 6291 * StringUtils.replace("aba", "a", "") = "b" 6292 * StringUtils.replace("aba", "a", "z") = "zbz" 6293 * </pre> 6294 * 6295 * @see #replace(String text, String searchString, String replacement, int max) 6296 * @param text text to search and replace in, may be null 6297 * @param searchString the String to search for, may be null 6298 * @param replacement the String to replace it with, may be null 6299 * @return the text with any replacements processed, 6300 * {@code null} if null String input 6301 */ 6302 public static String replace(final String text, final String searchString, final String replacement) { 6303 return replace(text, searchString, replacement, -1); 6304 } 6305 6306 /** 6307 * Replaces a String with another String inside a larger String, 6308 * for the first {@code max} values of the search String. 6309 * 6310 * <p>A {@code null} reference passed to this method is a no-op.</p> 6311 * 6312 * <pre> 6313 * StringUtils.replace(null, *, *, *) = null 6314 * StringUtils.replace("", *, *, *) = "" 6315 * StringUtils.replace("any", null, *, *) = "any" 6316 * StringUtils.replace("any", *, null, *) = "any" 6317 * StringUtils.replace("any", "", *, *) = "any" 6318 * StringUtils.replace("any", *, *, 0) = "any" 6319 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6320 * StringUtils.replace("abaa", "a", "", -1) = "b" 6321 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6322 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6323 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6324 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6325 * </pre> 6326 * 6327 * @param text text to search and replace in, may be null 6328 * @param searchString the String to search for, may be null 6329 * @param replacement the String to replace it with, may be null 6330 * @param max maximum number of values to replace, or {@code -1} if no maximum 6331 * @return the text with any replacements processed, 6332 * {@code null} if null String input 6333 */ 6334 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6335 return replace(text, searchString, replacement, max, false); 6336 } 6337 6338 /** 6339 * Replaces a String with another String inside a larger String, 6340 * for the first {@code max} values of the search String, 6341 * case-sensitively/insensitively based on {@code ignoreCase} value. 6342 * 6343 * <p>A {@code null} reference passed to this method is a no-op.</p> 6344 * 6345 * <pre> 6346 * StringUtils.replace(null, *, *, *, false) = null 6347 * StringUtils.replace("", *, *, *, false) = "" 6348 * StringUtils.replace("any", null, *, *, false) = "any" 6349 * StringUtils.replace("any", *, null, *, false) = "any" 6350 * StringUtils.replace("any", "", *, *, false) = "any" 6351 * StringUtils.replace("any", *, *, 0, false) = "any" 6352 * StringUtils.replace("abaa", "a", null, -1, false) = "abaa" 6353 * StringUtils.replace("abaa", "a", "", -1, false) = "b" 6354 * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa" 6355 * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa" 6356 * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa" 6357 * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza" 6358 * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz" 6359 * </pre> 6360 * 6361 * @param text text to search and replace in, may be null 6362 * @param searchString the String to search for (case-insensitive), may be null 6363 * @param replacement the String to replace it with, may be null 6364 * @param max maximum number of values to replace, or {@code -1} if no maximum 6365 * @param ignoreCase if true replace is case-insensitive, otherwise case-sensitive 6366 * @return the text with any replacements processed, 6367 * {@code null} if null String input 6368 */ 6369 private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) { 6370 if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 6371 return text; 6372 } 6373 if (ignoreCase) { 6374 searchString = searchString.toLowerCase(); 6375 } 6376 int start = 0; 6377 int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6378 if (end == INDEX_NOT_FOUND) { 6379 return text; 6380 } 6381 final int replLength = searchString.length(); 6382 int increase = Math.max(replacement.length() - replLength, 0); 6383 increase *= max < 0 ? 16 : Math.min(max, 64); 6384 final StringBuilder buf = new StringBuilder(text.length() + increase); 6385 while (end != INDEX_NOT_FOUND) { 6386 buf.append(text, start, end).append(replacement); 6387 start = end + replLength; 6388 if (--max == 0) { 6389 break; 6390 } 6391 end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6392 } 6393 buf.append(text, start, text.length()); 6394 return buf.toString(); 6395 } 6396 6397 /** 6398 * Replaces each substring of the text String that matches the given regular expression 6399 * with the given replacement. 6400 * 6401 * This method is a {@code null} safe equivalent to: 6402 * <ul> 6403 * <li>{@code text.replaceAll(regex, replacement)}</li> 6404 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6405 * </ul> 6406 * 6407 * <p>A {@code null} reference passed to this method is a no-op.</p> 6408 * 6409 * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option 6410 * is NOT automatically added. 6411 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6412 * DOTALL is also known as single-line mode in Perl.</p> 6413 * 6414 * <pre> 6415 * StringUtils.replaceAll(null, *, *) = null 6416 * StringUtils.replaceAll("any", (String) null, *) = "any" 6417 * StringUtils.replaceAll("any", *, null) = "any" 6418 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6419 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6420 * StringUtils.replaceAll("", ".+", "zzz") = "" 6421 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6422 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6423 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6424 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6425 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6426 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6427 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6428 * </pre> 6429 * 6430 * @param text text to search and replace in, may be null 6431 * @param regex the regular expression to which this string is to be matched 6432 * @param replacement the string to be substituted for each match 6433 * @return the text with any replacements processed, 6434 * {@code null} if null String input 6435 * 6436 * @throws java.util.regex.PatternSyntaxException 6437 * if the regular expression's syntax is invalid 6438 * 6439 * @see #replacePattern(String, String, String) 6440 * @see String#replaceAll(String, String) 6441 * @see java.util.regex.Pattern 6442 * @see java.util.regex.Pattern#DOTALL 6443 * @since 3.5 6444 * 6445 * @deprecated Moved to RegExUtils. 6446 */ 6447 @Deprecated 6448 public static String replaceAll(final String text, final String regex, final String replacement) { 6449 return RegExUtils.replaceAll(text, regex, replacement); 6450 } 6451 6452 /** 6453 * Replaces all occurrences of a character in a String with another. 6454 * This is a null-safe version of {@link String#replace(char, char)}. 6455 * 6456 * <p>A {@code null} string input returns {@code null}. 6457 * An empty ("") string input returns an empty string.</p> 6458 * 6459 * <pre> 6460 * StringUtils.replaceChars(null, *, *) = null 6461 * StringUtils.replaceChars("", *, *) = "" 6462 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6463 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6464 * </pre> 6465 * 6466 * @param str String to replace characters in, may be null 6467 * @param searchChar the character to search for, may be null 6468 * @param replaceChar the character to replace, may be null 6469 * @return modified String, {@code null} if null string input 6470 * @since 2.0 6471 */ 6472 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6473 if (str == null) { 6474 return null; 6475 } 6476 return str.replace(searchChar, replaceChar); 6477 } 6478 6479 /** 6480 * Replaces multiple characters in a String in one go. 6481 * This method can also be used to delete characters. 6482 * 6483 * <p>For example:<br> 6484 * {@code replaceChars("hello", "ho", "jy") = jelly}.</p> 6485 * 6486 * <p>A {@code null} string input returns {@code null}. 6487 * An empty ("") string input returns an empty string. 6488 * A null or empty set of search characters returns the input string.</p> 6489 * 6490 * <p>The length of the search characters should normally equal the length 6491 * of the replace characters. 6492 * If the search characters is longer, then the extra search characters 6493 * are deleted. 6494 * If the search characters is shorter, then the extra replace characters 6495 * are ignored.</p> 6496 * 6497 * <pre> 6498 * StringUtils.replaceChars(null, *, *) = null 6499 * StringUtils.replaceChars("", *, *) = "" 6500 * StringUtils.replaceChars("abc", null, *) = "abc" 6501 * StringUtils.replaceChars("abc", "", *) = "abc" 6502 * StringUtils.replaceChars("abc", "b", null) = "ac" 6503 * StringUtils.replaceChars("abc", "b", "") = "ac" 6504 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6505 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6506 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6507 * </pre> 6508 * 6509 * @param str String to replace characters in, may be null 6510 * @param searchChars a set of characters to search for, may be null 6511 * @param replaceChars a set of characters to replace, may be null 6512 * @return modified String, {@code null} if null string input 6513 * @since 2.0 6514 */ 6515 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6516 if (isEmpty(str) || isEmpty(searchChars)) { 6517 return str; 6518 } 6519 if (replaceChars == null) { 6520 replaceChars = EMPTY; 6521 } 6522 boolean modified = false; 6523 final int replaceCharsLength = replaceChars.length(); 6524 final int strLength = str.length(); 6525 final StringBuilder buf = new StringBuilder(strLength); 6526 for (int i = 0; i < strLength; i++) { 6527 final char ch = str.charAt(i); 6528 final int index = searchChars.indexOf(ch); 6529 if (index >= 0) { 6530 modified = true; 6531 if (index < replaceCharsLength) { 6532 buf.append(replaceChars.charAt(index)); 6533 } 6534 } else { 6535 buf.append(ch); 6536 } 6537 } 6538 if (modified) { 6539 return buf.toString(); 6540 } 6541 return str; 6542 } 6543 6544 /** 6545 * Replaces all occurrences of Strings within another String. 6546 * 6547 * <p> 6548 * A {@code null} reference passed to this method is a no-op, or if 6549 * any "search string" or "string to replace" is null, that replace will be 6550 * ignored. This will not repeat. For repeating replaces, call the 6551 * overloaded method. 6552 * </p> 6553 * 6554 * <pre> 6555 * StringUtils.replaceEach(null, *, *) = null 6556 * StringUtils.replaceEach("", *, *) = "" 6557 * StringUtils.replaceEach("aba", null, null) = "aba" 6558 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6559 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6560 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6561 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6562 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6563 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6564 * (example of how it does not repeat) 6565 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6566 * </pre> 6567 * 6568 * @param text 6569 * text to search and replace in, no-op if null 6570 * @param searchList 6571 * the Strings to search for, no-op if null 6572 * @param replacementList 6573 * the Strings to replace them with, no-op if null 6574 * @return the text with any replacements processed, {@code null} if 6575 * null String input 6576 * @throws IllegalArgumentException 6577 * if the lengths of the arrays are not the same (null is ok, 6578 * and/or size 0) 6579 * @since 2.4 6580 */ 6581 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6582 return replaceEach(text, searchList, replacementList, false, 0); 6583 } 6584 6585 /** 6586 * Replace all occurrences of Strings within another String. 6587 * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and 6588 * {@link #replaceEach(String, String[], String[])} 6589 * 6590 * <p> 6591 * A {@code null} reference passed to this method is a no-op, or if 6592 * any "search string" or "string to replace" is null, that replace will be 6593 * ignored. 6594 * </p> 6595 * 6596 * <pre> 6597 * StringUtils.replaceEach(null, *, *, *, *) = null 6598 * StringUtils.replaceEach("", *, *, *, *) = "" 6599 * StringUtils.replaceEach("aba", null, null, *, *) = "aba" 6600 * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba" 6601 * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba" 6602 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba" 6603 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b" 6604 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba" 6605 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte" 6606 * (example of how it repeats) 6607 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte" 6608 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte" 6609 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException 6610 * </pre> 6611 * 6612 * @param text 6613 * text to search and replace in, no-op if null 6614 * @param searchList 6615 * the Strings to search for, no-op if null 6616 * @param replacementList 6617 * the Strings to replace them with, no-op if null 6618 * @param repeat if true, then replace repeatedly 6619 * until there are no more possible replacements or timeToLive < 0 6620 * @param timeToLive 6621 * if less than 0 then there is a circular reference and endless 6622 * loop 6623 * @return the text with any replacements processed, {@code null} if 6624 * null String input 6625 * @throws IllegalStateException 6626 * if the search is repeating and there is an endless loop due 6627 * to outputs of one being inputs to another 6628 * @throws IllegalArgumentException 6629 * if the lengths of the arrays are not the same (null is ok, 6630 * and/or size 0) 6631 * @since 2.4 6632 */ 6633 private static String replaceEach( 6634 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 6635 6636 // mchyzer Performance note: This creates very few new objects (one major goal) 6637 // let me know if there are performance requests, we can create a harness to measure 6638 6639 // if recursing, this shouldn't be less than 0 6640 if (timeToLive < 0) { 6641 final Set<String> searchSet = new HashSet<>(Arrays.asList(searchList)); 6642 final Set<String> replacementSet = new HashSet<>(Arrays.asList(replacementList)); 6643 searchSet.retainAll(replacementSet); 6644 if (!searchSet.isEmpty()) { 6645 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6646 "output of one loop is the input of another"); 6647 } 6648 } 6649 6650 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList) || ArrayUtils.isNotEmpty(searchList) && timeToLive == -1) { 6651 return text; 6652 } 6653 6654 final int searchLength = searchList.length; 6655 final int replacementLength = replacementList.length; 6656 6657 // make sure lengths are ok, these need to be equal 6658 if (searchLength != replacementLength) { 6659 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6660 + searchLength 6661 + " vs " 6662 + replacementLength); 6663 } 6664 6665 // keep track of which still have matches 6666 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6667 6668 // index on index that the match was found 6669 int textIndex = -1; 6670 int replaceIndex = -1; 6671 int tempIndex; 6672 6673 // index of replace array that will replace the search string found 6674 // NOTE: logic duplicated below START 6675 for (int i = 0; i < searchLength; i++) { 6676 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6677 continue; 6678 } 6679 tempIndex = text.indexOf(searchList[i]); 6680 6681 // see if we need to keep searching for this 6682 if (tempIndex == -1) { 6683 noMoreMatchesForReplIndex[i] = true; 6684 } else if (textIndex == -1 || tempIndex < textIndex) { 6685 textIndex = tempIndex; 6686 replaceIndex = i; 6687 } 6688 } 6689 // NOTE: logic mostly below END 6690 6691 // no search strings found, we are done 6692 if (textIndex == -1) { 6693 return text; 6694 } 6695 6696 int start = 0; 6697 6698 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6699 int increase = 0; 6700 6701 // count the replacement text elements that are larger than their corresponding text being replaced 6702 for (int i = 0; i < searchList.length; i++) { 6703 if (searchList[i] == null || replacementList[i] == null) { 6704 continue; 6705 } 6706 final int greater = replacementList[i].length() - searchList[i].length(); 6707 if (greater > 0) { 6708 increase += 3 * greater; // assume 3 matches 6709 } 6710 } 6711 // have upper-bound at 20% increase, then let Java take over 6712 increase = Math.min(increase, text.length() / 5); 6713 6714 final StringBuilder buf = new StringBuilder(text.length() + increase); 6715 6716 while (textIndex != -1) { 6717 6718 for (int i = start; i < textIndex; i++) { 6719 buf.append(text.charAt(i)); 6720 } 6721 buf.append(replacementList[replaceIndex]); 6722 6723 start = textIndex + searchList[replaceIndex].length(); 6724 6725 textIndex = -1; 6726 replaceIndex = -1; 6727 // find the next earliest match 6728 // NOTE: logic mostly duplicated above START 6729 for (int i = 0; i < searchLength; i++) { 6730 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6731 continue; 6732 } 6733 tempIndex = text.indexOf(searchList[i], start); 6734 6735 // see if we need to keep searching for this 6736 if (tempIndex == -1) { 6737 noMoreMatchesForReplIndex[i] = true; 6738 } else if (textIndex == -1 || tempIndex < textIndex) { 6739 textIndex = tempIndex; 6740 replaceIndex = i; 6741 } 6742 } 6743 // NOTE: logic duplicated above END 6744 6745 } 6746 final int textLength = text.length(); 6747 for (int i = start; i < textLength; i++) { 6748 buf.append(text.charAt(i)); 6749 } 6750 final String result = buf.toString(); 6751 if (!repeat) { 6752 return result; 6753 } 6754 6755 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6756 } 6757 6758 /** 6759 * Replaces all occurrences of Strings within another String. 6760 * 6761 * <p> 6762 * A {@code null} reference passed to this method is a no-op, or if 6763 * any "search string" or "string to replace" is null, that replace will be 6764 * ignored. 6765 * </p> 6766 * 6767 * <pre> 6768 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6769 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6770 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6771 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6772 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6773 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6774 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6775 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6776 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6777 * (example of how it repeats) 6778 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6779 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException 6780 * </pre> 6781 * 6782 * @param text 6783 * text to search and replace in, no-op if null 6784 * @param searchList 6785 * the Strings to search for, no-op if null 6786 * @param replacementList 6787 * the Strings to replace them with, no-op if null 6788 * @return the text with any replacements processed, {@code null} if 6789 * null String input 6790 * @throws IllegalStateException 6791 * if the search is repeating and there is an endless loop due 6792 * to outputs of one being inputs to another 6793 * @throws IllegalArgumentException 6794 * if the lengths of the arrays are not the same (null is ok, 6795 * and/or size 0) 6796 * @since 2.4 6797 */ 6798 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6799 return replaceEach(text, searchList, replacementList, true, ArrayUtils.getLength(searchList)); 6800 } 6801 6802 /** 6803 * Replaces the first substring of the text string that matches the given regular expression 6804 * with the given replacement. 6805 * 6806 * This method is a {@code null} safe equivalent to: 6807 * <ul> 6808 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6809 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6810 * </ul> 6811 * 6812 * <p>A {@code null} reference passed to this method is a no-op.</p> 6813 * 6814 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6815 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6816 * DOTALL is also known as single-line mode in Perl.</p> 6817 * 6818 * <pre> 6819 * StringUtils.replaceFirst(null, *, *) = null 6820 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6821 * StringUtils.replaceFirst("any", *, null) = "any" 6822 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6823 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6824 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6825 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6826 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6827 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6828 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6829 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6830 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6831 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6832 * </pre> 6833 * 6834 * @param text text to search and replace in, may be null 6835 * @param regex the regular expression to which this string is to be matched 6836 * @param replacement the string to be substituted for the first match 6837 * @return the text with the first replacement processed, 6838 * {@code null} if null String input 6839 * 6840 * @throws java.util.regex.PatternSyntaxException 6841 * if the regular expression's syntax is invalid 6842 * 6843 * @see String#replaceFirst(String, String) 6844 * @see java.util.regex.Pattern 6845 * @see java.util.regex.Pattern#DOTALL 6846 * @since 3.5 6847 * 6848 * @deprecated Moved to RegExUtils. 6849 */ 6850 @Deprecated 6851 public static String replaceFirst(final String text, final String regex, final String replacement) { 6852 return RegExUtils.replaceFirst(text, regex, replacement); 6853 } 6854 6855 /** 6856 * Case insensitively replaces all occurrences of a String within another String. 6857 * 6858 * <p>A {@code null} reference passed to this method is a no-op.</p> 6859 * 6860 * <pre> 6861 * StringUtils.replaceIgnoreCase(null, *, *) = null 6862 * StringUtils.replaceIgnoreCase("", *, *) = "" 6863 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6864 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6865 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6866 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6867 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6868 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6869 * </pre> 6870 * 6871 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6872 * @param text text to search and replace in, may be null 6873 * @param searchString the String to search for (case-insensitive), may be null 6874 * @param replacement the String to replace it with, may be null 6875 * @return the text with any replacements processed, 6876 * {@code null} if null String input 6877 * @since 3.5 6878 */ 6879 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6880 return replaceIgnoreCase(text, searchString, replacement, -1); 6881 } 6882 6883 /** 6884 * Case insensitively replaces a String with another String inside a larger String, 6885 * for the first {@code max} values of the search String. 6886 * 6887 * <p>A {@code null} reference passed to this method is a no-op.</p> 6888 * 6889 * <pre> 6890 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6891 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6892 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6893 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6894 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6895 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6896 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6897 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6898 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6899 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6900 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6901 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6902 * </pre> 6903 * 6904 * @param text text to search and replace in, may be null 6905 * @param searchString the String to search for (case-insensitive), may be null 6906 * @param replacement the String to replace it with, may be null 6907 * @param max maximum number of values to replace, or {@code -1} if no maximum 6908 * @return the text with any replacements processed, 6909 * {@code null} if null String input 6910 * @since 3.5 6911 */ 6912 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6913 return replace(text, searchString, replacement, max, true); 6914 } 6915 6916 /** 6917 * Replaces a String with another String inside a larger String, once. 6918 * 6919 * <p>A {@code null} reference passed to this method is a no-op.</p> 6920 * 6921 * <pre> 6922 * StringUtils.replaceOnce(null, *, *) = null 6923 * StringUtils.replaceOnce("", *, *) = "" 6924 * StringUtils.replaceOnce("any", null, *) = "any" 6925 * StringUtils.replaceOnce("any", *, null) = "any" 6926 * StringUtils.replaceOnce("any", "", *) = "any" 6927 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6928 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6929 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6930 * </pre> 6931 * 6932 * @see #replace(String text, String searchString, String replacement, int max) 6933 * @param text text to search and replace in, may be null 6934 * @param searchString the String to search for, may be null 6935 * @param replacement the String to replace with, may be null 6936 * @return the text with any replacements processed, 6937 * {@code null} if null String input 6938 */ 6939 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6940 return replace(text, searchString, replacement, 1); 6941 } 6942 6943 /** 6944 * Case insensitively replaces a String with another String inside a larger String, once. 6945 * 6946 * <p>A {@code null} reference passed to this method is a no-op.</p> 6947 * 6948 * <pre> 6949 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6950 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6951 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6952 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6953 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6954 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6955 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6956 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6957 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6958 * </pre> 6959 * 6960 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6961 * @param text text to search and replace in, may be null 6962 * @param searchString the String to search for (case-insensitive), may be null 6963 * @param replacement the String to replace with, may be null 6964 * @return the text with any replacements processed, 6965 * {@code null} if null String input 6966 * @since 3.5 6967 */ 6968 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6969 return replaceIgnoreCase(text, searchString, replacement, 1); 6970 } 6971 6972 /** 6973 * Replaces each substring of the source String that matches the given regular expression with the given 6974 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl. 6975 * 6976 * This call is a {@code null} safe equivalent to: 6977 * <ul> 6978 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6979 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6980 * </ul> 6981 * 6982 * <p>A {@code null} reference passed to this method is a no-op.</p> 6983 * 6984 * <pre> 6985 * StringUtils.replacePattern(null, *, *) = null 6986 * StringUtils.replacePattern("any", (String) null, *) = "any" 6987 * StringUtils.replacePattern("any", *, null) = "any" 6988 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6989 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6990 * StringUtils.replacePattern("", ".+", "zzz") = "" 6991 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6992 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6993 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6994 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6995 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6996 * </pre> 6997 * 6998 * @param source 6999 * the source string 7000 * @param regex 7001 * the regular expression to which this string is to be matched 7002 * @param replacement 7003 * the string to be substituted for each match 7004 * @return The resulting {@link String} 7005 * @see #replaceAll(String, String, String) 7006 * @see String#replaceAll(String, String) 7007 * @see Pattern#DOTALL 7008 * @since 3.2 7009 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 7010 * 7011 * @deprecated Moved to RegExUtils. 7012 */ 7013 @Deprecated 7014 public static String replacePattern(final String source, final String regex, final String replacement) { 7015 return RegExUtils.replacePattern(source, regex, replacement); 7016 } 7017 7018 /** 7019 * Reverses a String as per {@link StringBuilder#reverse()}. 7020 * 7021 * <p>A {@code null} String returns {@code null}.</p> 7022 * 7023 * <pre> 7024 * StringUtils.reverse(null) = null 7025 * StringUtils.reverse("") = "" 7026 * StringUtils.reverse("bat") = "tab" 7027 * </pre> 7028 * 7029 * @param str the String to reverse, may be null 7030 * @return the reversed String, {@code null} if null String input 7031 */ 7032 public static String reverse(final String str) { 7033 if (str == null) { 7034 return null; 7035 } 7036 return new StringBuilder(str).reverse().toString(); 7037 } 7038 7039 /** 7040 * Reverses a String that is delimited by a specific character. 7041 * 7042 * <p>The Strings between the delimiters are not reversed. 7043 * Thus java.lang.String becomes String.lang.java (if the delimiter 7044 * is {@code '.'}).</p> 7045 * 7046 * <pre> 7047 * StringUtils.reverseDelimited(null, *) = null 7048 * StringUtils.reverseDelimited("", *) = "" 7049 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 7050 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 7051 * </pre> 7052 * 7053 * @param str the String to reverse, may be null 7054 * @param separatorChar the separator character to use 7055 * @return the reversed String, {@code null} if null String input 7056 * @since 2.0 7057 */ 7058 public static String reverseDelimited(final String str, final char separatorChar) { 7059 if (str == null) { 7060 return null; 7061 } 7062 // could implement manually, but simple way is to reuse other, 7063 // probably slower, methods. 7064 final String[] strs = split(str, separatorChar); 7065 ArrayUtils.reverse(strs); 7066 return join(strs, separatorChar); 7067 } 7068 7069 /** 7070 * Gets the rightmost {@code len} characters of a String. 7071 * 7072 * <p>If {@code len} characters are not available, or the String 7073 * is {@code null}, the String will be returned without an 7074 * an exception. An empty String is returned if len is negative.</p> 7075 * 7076 * <pre> 7077 * StringUtils.right(null, *) = null 7078 * StringUtils.right(*, -ve) = "" 7079 * StringUtils.right("", *) = "" 7080 * StringUtils.right("abc", 0) = "" 7081 * StringUtils.right("abc", 2) = "bc" 7082 * StringUtils.right("abc", 4) = "abc" 7083 * </pre> 7084 * 7085 * @param str the String to get the rightmost characters from, may be null 7086 * @param len the length of the required String 7087 * @return the rightmost characters, {@code null} if null String input 7088 */ 7089 public static String right(final String str, final int len) { 7090 if (str == null) { 7091 return null; 7092 } 7093 if (len < 0) { 7094 return EMPTY; 7095 } 7096 if (str.length() <= len) { 7097 return str; 7098 } 7099 return str.substring(str.length() - len); 7100 } 7101 7102 /** 7103 * Right pad a String with spaces (' '). 7104 * 7105 * <p>The String is padded to the size of {@code size}.</p> 7106 * 7107 * <pre> 7108 * StringUtils.rightPad(null, *) = null 7109 * StringUtils.rightPad("", 3) = " " 7110 * StringUtils.rightPad("bat", 3) = "bat" 7111 * StringUtils.rightPad("bat", 5) = "bat " 7112 * StringUtils.rightPad("bat", 1) = "bat" 7113 * StringUtils.rightPad("bat", -1) = "bat" 7114 * </pre> 7115 * 7116 * @param str the String to pad out, may be null 7117 * @param size the size to pad to 7118 * @return right padded String or original String if no padding is necessary, 7119 * {@code null} if null String input 7120 */ 7121 public static String rightPad(final String str, final int size) { 7122 return rightPad(str, size, ' '); 7123 } 7124 7125 /** 7126 * Right pad a String with a specified character. 7127 * 7128 * <p>The String is padded to the size of {@code size}.</p> 7129 * 7130 * <pre> 7131 * StringUtils.rightPad(null, *, *) = null 7132 * StringUtils.rightPad("", 3, 'z') = "zzz" 7133 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7134 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7135 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7136 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7137 * </pre> 7138 * 7139 * @param str the String to pad out, may be null 7140 * @param size the size to pad to 7141 * @param padChar the character to pad with 7142 * @return right padded String or original String if no padding is necessary, 7143 * {@code null} if null String input 7144 * @since 2.0 7145 */ 7146 public static String rightPad(final String str, final int size, final char padChar) { 7147 if (str == null) { 7148 return null; 7149 } 7150 final int pads = size - str.length(); 7151 if (pads <= 0) { 7152 return str; // returns original String when possible 7153 } 7154 if (pads > PAD_LIMIT) { 7155 return rightPad(str, size, String.valueOf(padChar)); 7156 } 7157 return str.concat(repeat(padChar, pads)); 7158 } 7159 7160 /** 7161 * Right pad a String with a specified String. 7162 * 7163 * <p>The String is padded to the size of {@code size}.</p> 7164 * 7165 * <pre> 7166 * StringUtils.rightPad(null, *, *) = null 7167 * StringUtils.rightPad("", 3, "z") = "zzz" 7168 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7169 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7170 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7171 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7172 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7173 * StringUtils.rightPad("bat", 5, null) = "bat " 7174 * StringUtils.rightPad("bat", 5, "") = "bat " 7175 * </pre> 7176 * 7177 * @param str the String to pad out, may be null 7178 * @param size the size to pad to 7179 * @param padStr the String to pad with, null or empty treated as single space 7180 * @return right padded String or original String if no padding is necessary, 7181 * {@code null} if null String input 7182 */ 7183 public static String rightPad(final String str, final int size, String padStr) { 7184 if (str == null) { 7185 return null; 7186 } 7187 if (isEmpty(padStr)) { 7188 padStr = SPACE; 7189 } 7190 final int padLen = padStr.length(); 7191 final int strLen = str.length(); 7192 final int pads = size - strLen; 7193 if (pads <= 0) { 7194 return str; // returns original String when possible 7195 } 7196 if (padLen == 1 && pads <= PAD_LIMIT) { 7197 return rightPad(str, size, padStr.charAt(0)); 7198 } 7199 7200 if (pads == padLen) { 7201 return str.concat(padStr); 7202 } 7203 if (pads < padLen) { 7204 return str.concat(padStr.substring(0, pads)); 7205 } 7206 final char[] padding = new char[pads]; 7207 final char[] padChars = padStr.toCharArray(); 7208 for (int i = 0; i < pads; i++) { 7209 padding[i] = padChars[i % padLen]; 7210 } 7211 return str.concat(new String(padding)); 7212 } 7213 7214 /** 7215 * Rotate (circular shift) a String of {@code shift} characters. 7216 * <ul> 7217 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7218 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7219 * </ul> 7220 * 7221 * <pre> 7222 * StringUtils.rotate(null, *) = null 7223 * StringUtils.rotate("", *) = "" 7224 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7225 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7226 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7227 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7228 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7229 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7230 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7231 * </pre> 7232 * 7233 * @param str the String to rotate, may be null 7234 * @param shift number of time to shift (positive : right shift, negative : left shift) 7235 * @return the rotated String, 7236 * or the original String if {@code shift == 0}, 7237 * or {@code null} if null String input 7238 * @since 3.5 7239 */ 7240 public static String rotate(final String str, final int shift) { 7241 if (str == null) { 7242 return null; 7243 } 7244 7245 final int strLen = str.length(); 7246 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7247 return str; 7248 } 7249 7250 final StringBuilder builder = new StringBuilder(strLen); 7251 final int offset = - (shift % strLen); 7252 builder.append(substring(str, offset)); 7253 builder.append(substring(str, 0, offset)); 7254 return builder.toString(); 7255 } 7256 7257 /** 7258 * Splits the provided text into an array, using whitespace as the 7259 * separator. 7260 * Whitespace is defined by {@link Character#isWhitespace(char)}. 7261 * 7262 * <p>The separator is not included in the returned String array. 7263 * Adjacent separators are treated as one separator. 7264 * For more control over the split use the StrTokenizer class.</p> 7265 * 7266 * <p>A {@code null} input String returns {@code null}.</p> 7267 * 7268 * <pre> 7269 * StringUtils.split(null) = null 7270 * StringUtils.split("") = [] 7271 * StringUtils.split("abc def") = ["abc", "def"] 7272 * StringUtils.split("abc def") = ["abc", "def"] 7273 * StringUtils.split(" abc ") = ["abc"] 7274 * </pre> 7275 * 7276 * @param str the String to parse, may be null 7277 * @return an array of parsed Strings, {@code null} if null String input 7278 */ 7279 public static String[] split(final String str) { 7280 return split(str, null, -1); 7281 } 7282 7283 /** 7284 * Splits the provided text into an array, separator specified. 7285 * This is an alternative to using StringTokenizer. 7286 * 7287 * <p>The separator is not included in the returned String array. 7288 * Adjacent separators are treated as one separator. 7289 * For more control over the split use the StrTokenizer class.</p> 7290 * 7291 * <p>A {@code null} input String returns {@code null}.</p> 7292 * 7293 * <pre> 7294 * StringUtils.split(null, *) = null 7295 * StringUtils.split("", *) = [] 7296 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7297 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7298 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7299 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7300 * </pre> 7301 * 7302 * @param str the String to parse, may be null 7303 * @param separatorChar the character used as the delimiter 7304 * @return an array of parsed Strings, {@code null} if null String input 7305 * @since 2.0 7306 */ 7307 public static String[] split(final String str, final char separatorChar) { 7308 return splitWorker(str, separatorChar, false); 7309 } 7310 7311 /** 7312 * Splits the provided text into an array, separators specified. 7313 * This is an alternative to using StringTokenizer. 7314 * 7315 * <p>The separator is not included in the returned String array. 7316 * Adjacent separators are treated as one separator. 7317 * For more control over the split use the StrTokenizer class.</p> 7318 * 7319 * <p>A {@code null} input String returns {@code null}. 7320 * A {@code null} separatorChars splits on whitespace.</p> 7321 * 7322 * <pre> 7323 * StringUtils.split(null, *) = null 7324 * StringUtils.split("", *) = [] 7325 * StringUtils.split("abc def", null) = ["abc", "def"] 7326 * StringUtils.split("abc def", " ") = ["abc", "def"] 7327 * StringUtils.split("abc def", " ") = ["abc", "def"] 7328 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7329 * </pre> 7330 * 7331 * @param str the String to parse, may be null 7332 * @param separatorChars the characters used as the delimiters, 7333 * {@code null} splits on whitespace 7334 * @return an array of parsed Strings, {@code null} if null String input 7335 */ 7336 public static String[] split(final String str, final String separatorChars) { 7337 return splitWorker(str, separatorChars, -1, false); 7338 } 7339 7340 /** 7341 * Splits the provided text into an array with a maximum length, 7342 * separators specified. 7343 * 7344 * <p>The separator is not included in the returned String array. 7345 * Adjacent separators are treated as one separator.</p> 7346 * 7347 * <p>A {@code null} input String returns {@code null}. 7348 * A {@code null} separatorChars splits on whitespace.</p> 7349 * 7350 * <p>If more than {@code max} delimited substrings are found, the last 7351 * returned string includes all characters after the first {@code max - 1} 7352 * returned strings (including separator characters).</p> 7353 * 7354 * <pre> 7355 * StringUtils.split(null, *, *) = null 7356 * StringUtils.split("", *, *) = [] 7357 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7358 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7359 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7360 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7361 * </pre> 7362 * 7363 * @param str the String to parse, may be null 7364 * @param separatorChars the characters used as the delimiters, 7365 * {@code null} splits on whitespace 7366 * @param max the maximum number of elements to include in the 7367 * array. A zero or negative value implies no limit 7368 * @return an array of parsed Strings, {@code null} if null String input 7369 */ 7370 public static String[] split(final String str, final String separatorChars, final int max) { 7371 return splitWorker(str, separatorChars, max, false); 7372 } 7373 7374 /** 7375 * Splits a String by Character type as returned by 7376 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7377 * characters of the same type are returned as complete tokens. 7378 * <pre> 7379 * StringUtils.splitByCharacterType(null) = null 7380 * StringUtils.splitByCharacterType("") = [] 7381 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7382 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7383 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7384 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7385 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7386 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7387 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7388 * </pre> 7389 * @param str the String to split, may be {@code null} 7390 * @return an array of parsed Strings, {@code null} if null String input 7391 * @since 2.4 7392 */ 7393 public static String[] splitByCharacterType(final String str) { 7394 return splitByCharacterType(str, false); 7395 } 7396 7397 /** 7398 * <p>Splits a String by Character type as returned by 7399 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7400 * characters of the same type are returned as complete tokens, with the 7401 * following exception: if {@code camelCase} is {@code true}, 7402 * the character of type {@code Character.UPPERCASE_LETTER}, if any, 7403 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} 7404 * will belong to the following token rather than to the preceding, if any, 7405 * {@code Character.UPPERCASE_LETTER} token. 7406 * @param str the String to split, may be {@code null} 7407 * @param camelCase whether to use so-called "camel-case" for letter types 7408 * @return an array of parsed Strings, {@code null} if null String input 7409 * @since 2.4 7410 */ 7411 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7412 if (str == null) { 7413 return null; 7414 } 7415 if (str.isEmpty()) { 7416 return ArrayUtils.EMPTY_STRING_ARRAY; 7417 } 7418 final char[] c = str.toCharArray(); 7419 final List<String> list = new ArrayList<>(); 7420 int tokenStart = 0; 7421 int currentType = Character.getType(c[tokenStart]); 7422 for (int pos = tokenStart + 1; pos < c.length; pos++) { 7423 final int type = Character.getType(c[pos]); 7424 if (type == currentType) { 7425 continue; 7426 } 7427 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7428 final int newTokenStart = pos - 1; 7429 if (newTokenStart != tokenStart) { 7430 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7431 tokenStart = newTokenStart; 7432 } 7433 } else { 7434 list.add(new String(c, tokenStart, pos - tokenStart)); 7435 tokenStart = pos; 7436 } 7437 currentType = type; 7438 } 7439 list.add(new String(c, tokenStart, c.length - tokenStart)); 7440 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7441 } 7442 7443 /** 7444 * <p>Splits a String by Character type as returned by 7445 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7446 * characters of the same type are returned as complete tokens, with the 7447 * following exception: the character of type 7448 * {@code Character.UPPERCASE_LETTER}, if any, immediately 7449 * preceding a token of type {@code Character.LOWERCASE_LETTER} 7450 * will belong to the following token rather than to the preceding, if any, 7451 * {@code Character.UPPERCASE_LETTER} token. 7452 * <pre> 7453 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7454 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7455 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7456 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7457 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7458 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7459 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7460 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7461 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7462 * </pre> 7463 * @param str the String to split, may be {@code null} 7464 * @return an array of parsed Strings, {@code null} if null String input 7465 * @since 2.4 7466 */ 7467 public static String[] splitByCharacterTypeCamelCase(final String str) { 7468 return splitByCharacterType(str, true); 7469 } 7470 7471 /** 7472 * <p>Splits the provided text into an array, separator string specified. 7473 * 7474 * <p>The separator(s) will not be included in the returned String array. 7475 * Adjacent separators are treated as one separator.</p> 7476 * 7477 * <p>A {@code null} input String returns {@code null}. 7478 * A {@code null} separator splits on whitespace.</p> 7479 * 7480 * <pre> 7481 * StringUtils.splitByWholeSeparator(null, *) = null 7482 * StringUtils.splitByWholeSeparator("", *) = [] 7483 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7484 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7485 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7486 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7487 * </pre> 7488 * 7489 * @param str the String to parse, may be null 7490 * @param separator String containing the String to be used as a delimiter, 7491 * {@code null} splits on whitespace 7492 * @return an array of parsed Strings, {@code null} if null String was input 7493 */ 7494 public static String[] splitByWholeSeparator(final String str, final String separator) { 7495 return splitByWholeSeparatorWorker(str, separator, -1, false); 7496 } 7497 7498 /** 7499 * Splits the provided text into an array, separator string specified. 7500 * Returns a maximum of {@code max} substrings. 7501 * 7502 * <p>The separator(s) will not be included in the returned String array. 7503 * Adjacent separators are treated as one separator.</p> 7504 * 7505 * <p>A {@code null} input String returns {@code null}. 7506 * A {@code null} separator splits on whitespace.</p> 7507 * 7508 * <pre> 7509 * StringUtils.splitByWholeSeparator(null, *, *) = null 7510 * StringUtils.splitByWholeSeparator("", *, *) = [] 7511 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7512 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7513 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7514 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7515 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7516 * </pre> 7517 * 7518 * @param str the String to parse, may be null 7519 * @param separator String containing the String to be used as a delimiter, 7520 * {@code null} splits on whitespace 7521 * @param max the maximum number of elements to include in the returned 7522 * array. A zero or negative value implies no limit. 7523 * @return an array of parsed Strings, {@code null} if null String was input 7524 */ 7525 public static String[] splitByWholeSeparator( final String str, final String separator, final int max) { 7526 return splitByWholeSeparatorWorker(str, separator, max, false); 7527 } 7528 7529 /** 7530 * Splits the provided text into an array, separator string specified. 7531 * 7532 * <p>The separator is not included in the returned String array. 7533 * Adjacent separators are treated as separators for empty tokens. 7534 * For more control over the split use the StrTokenizer class.</p> 7535 * 7536 * <p>A {@code null} input String returns {@code null}. 7537 * A {@code null} separator splits on whitespace.</p> 7538 * 7539 * <pre> 7540 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7541 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7542 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7543 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7544 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7545 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7546 * </pre> 7547 * 7548 * @param str the String to parse, may be null 7549 * @param separator String containing the String to be used as a delimiter, 7550 * {@code null} splits on whitespace 7551 * @return an array of parsed Strings, {@code null} if null String was input 7552 * @since 2.4 7553 */ 7554 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7555 return splitByWholeSeparatorWorker(str, separator, -1, true); 7556 } 7557 7558 /** 7559 * Splits the provided text into an array, separator string specified. 7560 * Returns a maximum of {@code max} substrings. 7561 * 7562 * <p>The separator is not included in the returned String array. 7563 * Adjacent separators are treated as separators for empty tokens. 7564 * For more control over the split use the StrTokenizer class.</p> 7565 * 7566 * <p>A {@code null} input String returns {@code null}. 7567 * A {@code null} separator splits on whitespace.</p> 7568 * 7569 * <pre> 7570 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7571 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7572 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7573 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7574 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7575 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7576 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7577 * </pre> 7578 * 7579 * @param str the String to parse, may be null 7580 * @param separator String containing the String to be used as a delimiter, 7581 * {@code null} splits on whitespace 7582 * @param max the maximum number of elements to include in the returned 7583 * array. A zero or negative value implies no limit. 7584 * @return an array of parsed Strings, {@code null} if null String was input 7585 * @since 2.4 7586 */ 7587 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7588 return splitByWholeSeparatorWorker(str, separator, max, true); 7589 } 7590 7591 /** 7592 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7593 * 7594 * @param str the String to parse, may be {@code null} 7595 * @param separator String containing the String to be used as a delimiter, 7596 * {@code null} splits on whitespace 7597 * @param max the maximum number of elements to include in the returned 7598 * array. A zero or negative value implies no limit. 7599 * @param preserveAllTokens if {@code true}, adjacent separators are 7600 * treated as empty token separators; if {@code false}, adjacent 7601 * separators are treated as one separator. 7602 * @return an array of parsed Strings, {@code null} if null String input 7603 * @since 2.4 7604 */ 7605 private static String[] splitByWholeSeparatorWorker( 7606 final String str, final String separator, final int max, final boolean preserveAllTokens) { 7607 if (str == null) { 7608 return null; 7609 } 7610 7611 final int len = str.length(); 7612 7613 if (len == 0) { 7614 return ArrayUtils.EMPTY_STRING_ARRAY; 7615 } 7616 7617 if (separator == null || EMPTY.equals(separator)) { 7618 // Split on whitespace. 7619 return splitWorker(str, null, max, preserveAllTokens); 7620 } 7621 7622 final int separatorLength = separator.length(); 7623 7624 final ArrayList<String> substrings = new ArrayList<>(); 7625 int numberOfSubstrings = 0; 7626 int beg = 0; 7627 int end = 0; 7628 while (end < len) { 7629 end = str.indexOf(separator, beg); 7630 7631 if (end > -1) { 7632 if (end > beg) { 7633 numberOfSubstrings += 1; 7634 7635 if (numberOfSubstrings == max) { 7636 end = len; 7637 substrings.add(str.substring(beg)); 7638 } else { 7639 // The following is OK, because String.substring( beg, end ) excludes 7640 // the character at the position 'end'. 7641 substrings.add(str.substring(beg, end)); 7642 7643 // Set the starting point for the next search. 7644 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7645 // which is the right calculation: 7646 beg = end + separatorLength; 7647 } 7648 } else { 7649 // We found a consecutive occurrence of the separator, so skip it. 7650 if (preserveAllTokens) { 7651 numberOfSubstrings += 1; 7652 if (numberOfSubstrings == max) { 7653 end = len; 7654 substrings.add(str.substring(beg)); 7655 } else { 7656 substrings.add(EMPTY); 7657 } 7658 } 7659 beg = end + separatorLength; 7660 } 7661 } else { 7662 // String.substring( beg ) goes from 'beg' to the end of the String. 7663 substrings.add(str.substring(beg)); 7664 end = len; 7665 } 7666 } 7667 7668 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7669 } 7670 7671 /** 7672 * Splits the provided text into an array, using whitespace as the 7673 * separator, preserving all tokens, including empty tokens created by 7674 * adjacent separators. This is an alternative to using StringTokenizer. 7675 * Whitespace is defined by {@link Character#isWhitespace(char)}. 7676 * 7677 * <p>The separator is not included in the returned String array. 7678 * Adjacent separators are treated as separators for empty tokens. 7679 * For more control over the split use the StrTokenizer class.</p> 7680 * 7681 * <p>A {@code null} input String returns {@code null}.</p> 7682 * 7683 * <pre> 7684 * StringUtils.splitPreserveAllTokens(null) = null 7685 * StringUtils.splitPreserveAllTokens("") = [] 7686 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7687 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7688 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7689 * </pre> 7690 * 7691 * @param str the String to parse, may be {@code null} 7692 * @return an array of parsed Strings, {@code null} if null String input 7693 * @since 2.1 7694 */ 7695 public static String[] splitPreserveAllTokens(final String str) { 7696 return splitWorker(str, null, -1, true); 7697 } 7698 7699 /** 7700 * Splits the provided text into an array, separator specified, 7701 * preserving all tokens, including empty tokens created by adjacent 7702 * separators. This is an alternative to using StringTokenizer. 7703 * 7704 * <p>The separator is not included in the returned String array. 7705 * Adjacent separators are treated as separators for empty tokens. 7706 * For more control over the split use the StrTokenizer class.</p> 7707 * 7708 * <p>A {@code null} input String returns {@code null}.</p> 7709 * 7710 * <pre> 7711 * StringUtils.splitPreserveAllTokens(null, *) = null 7712 * StringUtils.splitPreserveAllTokens("", *) = [] 7713 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7714 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7715 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7716 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7717 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7718 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7719 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7720 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"] 7721 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"] 7722 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""] 7723 * </pre> 7724 * 7725 * @param str the String to parse, may be {@code null} 7726 * @param separatorChar the character used as the delimiter, 7727 * {@code null} splits on whitespace 7728 * @return an array of parsed Strings, {@code null} if null String input 7729 * @since 2.1 7730 */ 7731 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7732 return splitWorker(str, separatorChar, true); 7733 } 7734 7735 /** 7736 * Splits the provided text into an array, separators specified, 7737 * preserving all tokens, including empty tokens created by adjacent 7738 * separators. This is an alternative to using StringTokenizer. 7739 * 7740 * <p>The separator is not included in the returned String array. 7741 * Adjacent separators are treated as separators for empty tokens. 7742 * For more control over the split use the StrTokenizer class.</p> 7743 * 7744 * <p>A {@code null} input String returns {@code null}. 7745 * A {@code null} separatorChars splits on whitespace.</p> 7746 * 7747 * <pre> 7748 * StringUtils.splitPreserveAllTokens(null, *) = null 7749 * StringUtils.splitPreserveAllTokens("", *) = [] 7750 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7751 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7752 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"] 7753 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7754 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7755 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7756 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"] 7757 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"] 7758 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"] 7759 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""] 7760 * </pre> 7761 * 7762 * @param str the String to parse, may be {@code null} 7763 * @param separatorChars the characters used as the delimiters, 7764 * {@code null} splits on whitespace 7765 * @return an array of parsed Strings, {@code null} if null String input 7766 * @since 2.1 7767 */ 7768 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7769 return splitWorker(str, separatorChars, -1, true); 7770 } 7771 7772 /** 7773 * Splits the provided text into an array with a maximum length, 7774 * separators specified, preserving all tokens, including empty tokens 7775 * created by adjacent separators. 7776 * 7777 * <p>The separator is not included in the returned String array. 7778 * Adjacent separators are treated as separators for empty tokens. 7779 * Adjacent separators are treated as one separator.</p> 7780 * 7781 * <p>A {@code null} input String returns {@code null}. 7782 * A {@code null} separatorChars splits on whitespace.</p> 7783 * 7784 * <p>If more than {@code max} delimited substrings are found, the last 7785 * returned string includes all characters after the first {@code max - 1} 7786 * returned strings (including separator characters).</p> 7787 * 7788 * <pre> 7789 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7790 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7791 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7792 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7793 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7794 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7795 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7796 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7797 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7798 * </pre> 7799 * 7800 * @param str the String to parse, may be {@code null} 7801 * @param separatorChars the characters used as the delimiters, 7802 * {@code null} splits on whitespace 7803 * @param max the maximum number of elements to include in the 7804 * array. A zero or negative value implies no limit 7805 * @return an array of parsed Strings, {@code null} if null String input 7806 * @since 2.1 7807 */ 7808 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7809 return splitWorker(str, separatorChars, max, true); 7810 } 7811 7812 /** 7813 * Performs the logic for the {@code split} and 7814 * {@code splitPreserveAllTokens} methods that do not return a 7815 * maximum array length. 7816 * 7817 * @param str the String to parse, may be {@code null} 7818 * @param separatorChar the separate character 7819 * @param preserveAllTokens if {@code true}, adjacent separators are 7820 * treated as empty token separators; if {@code false}, adjacent 7821 * separators are treated as one separator. 7822 * @return an array of parsed Strings, {@code null} if null String input 7823 */ 7824 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7825 // Performance tuned for 2.0 (JDK1.4) 7826 7827 if (str == null) { 7828 return null; 7829 } 7830 final int len = str.length(); 7831 if (len == 0) { 7832 return ArrayUtils.EMPTY_STRING_ARRAY; 7833 } 7834 final List<String> list = new ArrayList<>(); 7835 int i = 0; 7836 int start = 0; 7837 boolean match = false; 7838 boolean lastMatch = false; 7839 while (i < len) { 7840 if (str.charAt(i) == separatorChar) { 7841 if (match || preserveAllTokens) { 7842 list.add(str.substring(start, i)); 7843 match = false; 7844 lastMatch = true; 7845 } 7846 start = ++i; 7847 continue; 7848 } 7849 lastMatch = false; 7850 match = true; 7851 i++; 7852 } 7853 if (match || preserveAllTokens && lastMatch) { 7854 list.add(str.substring(start, i)); 7855 } 7856 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7857 } 7858 7859 /** 7860 * Performs the logic for the {@code split} and 7861 * {@code splitPreserveAllTokens} methods that return a maximum array 7862 * length. 7863 * 7864 * @param str the String to parse, may be {@code null} 7865 * @param separatorChars the separate character 7866 * @param max the maximum number of elements to include in the 7867 * array. A zero or negative value implies no limit. 7868 * @param preserveAllTokens if {@code true}, adjacent separators are 7869 * treated as empty token separators; if {@code false}, adjacent 7870 * separators are treated as one separator. 7871 * @return an array of parsed Strings, {@code null} if null String input 7872 */ 7873 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7874 // Performance tuned for 2.0 (JDK1.4) 7875 // Direct code is quicker than StringTokenizer. 7876 // Also, StringTokenizer uses isSpace() not isWhitespace() 7877 7878 if (str == null) { 7879 return null; 7880 } 7881 final int len = str.length(); 7882 if (len == 0) { 7883 return ArrayUtils.EMPTY_STRING_ARRAY; 7884 } 7885 final List<String> list = new ArrayList<>(); 7886 int sizePlus1 = 1; 7887 int i = 0; 7888 int start = 0; 7889 boolean match = false; 7890 boolean lastMatch = false; 7891 if (separatorChars == null) { 7892 // Null separator means use whitespace 7893 while (i < len) { 7894 if (Character.isWhitespace(str.charAt(i))) { 7895 if (match || preserveAllTokens) { 7896 lastMatch = true; 7897 if (sizePlus1++ == max) { 7898 i = len; 7899 lastMatch = false; 7900 } 7901 list.add(str.substring(start, i)); 7902 match = false; 7903 } 7904 start = ++i; 7905 continue; 7906 } 7907 lastMatch = false; 7908 match = true; 7909 i++; 7910 } 7911 } else if (separatorChars.length() == 1) { 7912 // Optimise 1 character case 7913 final char sep = separatorChars.charAt(0); 7914 while (i < len) { 7915 if (str.charAt(i) == sep) { 7916 if (match || preserveAllTokens) { 7917 lastMatch = true; 7918 if (sizePlus1++ == max) { 7919 i = len; 7920 lastMatch = false; 7921 } 7922 list.add(str.substring(start, i)); 7923 match = false; 7924 } 7925 start = ++i; 7926 continue; 7927 } 7928 lastMatch = false; 7929 match = true; 7930 i++; 7931 } 7932 } else { 7933 // standard case 7934 while (i < len) { 7935 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 7936 if (match || preserveAllTokens) { 7937 lastMatch = true; 7938 if (sizePlus1++ == max) { 7939 i = len; 7940 lastMatch = false; 7941 } 7942 list.add(str.substring(start, i)); 7943 match = false; 7944 } 7945 start = ++i; 7946 continue; 7947 } 7948 lastMatch = false; 7949 match = true; 7950 i++; 7951 } 7952 } 7953 if (match || preserveAllTokens && lastMatch) { 7954 list.add(str.substring(start, i)); 7955 } 7956 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7957 } 7958 7959 /** 7960 * Check if a CharSequence starts with a specified prefix. 7961 * 7962 * <p>{@code null}s are handled without exceptions. Two {@code null} 7963 * references are considered to be equal. The comparison is case-sensitive.</p> 7964 * 7965 * <pre> 7966 * StringUtils.startsWith(null, null) = true 7967 * StringUtils.startsWith(null, "abc") = false 7968 * StringUtils.startsWith("abcdef", null) = false 7969 * StringUtils.startsWith("abcdef", "abc") = true 7970 * StringUtils.startsWith("ABCDEF", "abc") = false 7971 * </pre> 7972 * 7973 * @see String#startsWith(String) 7974 * @param str the CharSequence to check, may be null 7975 * @param prefix the prefix to find, may be null 7976 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or 7977 * both {@code null} 7978 * @since 2.4 7979 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 7980 */ 7981 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7982 return startsWith(str, prefix, false); 7983 } 7984 7985 /** 7986 * Check if a CharSequence starts with a specified prefix (optionally case insensitive). 7987 * 7988 * @see String#startsWith(String) 7989 * @param str the CharSequence to check, may be null 7990 * @param prefix the prefix to find, may be null 7991 * @param ignoreCase indicates whether the compare should ignore case 7992 * (case-insensitive) or not. 7993 * @return {@code true} if the CharSequence starts with the prefix or 7994 * both {@code null} 7995 */ 7996 private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) { 7997 if (str == null || prefix == null) { 7998 return str == prefix; 7999 } 8000 // Get length once instead of twice in the unlikely case that it changes. 8001 final int preLen = prefix.length(); 8002 if (preLen > str.length()) { 8003 return false; 8004 } 8005 return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, preLen); 8006 } 8007 8008 /** 8009 * Check if a CharSequence starts with any of the provided case-sensitive prefixes. 8010 * 8011 * <pre> 8012 * StringUtils.startsWithAny(null, null) = false 8013 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 8014 * StringUtils.startsWithAny("abcxyz", null) = false 8015 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 8016 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 8017 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 8018 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 8019 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 8020 * </pre> 8021 * 8022 * @param sequence the CharSequence to check, may be null 8023 * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null} 8024 * @see StringUtils#startsWith(CharSequence, CharSequence) 8025 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 8026 * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}. 8027 * @since 2.5 8028 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 8029 */ 8030 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 8031 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 8032 return false; 8033 } 8034 for (final CharSequence searchString : searchStrings) { 8035 if (startsWith(sequence, searchString)) { 8036 return true; 8037 } 8038 } 8039 return false; 8040 } 8041 8042 /** 8043 * Case insensitive check if a CharSequence starts with a specified prefix. 8044 * 8045 * <p>{@code null}s are handled without exceptions. Two {@code null} 8046 * references are considered to be equal. The comparison is case insensitive.</p> 8047 * 8048 * <pre> 8049 * StringUtils.startsWithIgnoreCase(null, null) = true 8050 * StringUtils.startsWithIgnoreCase(null, "abc") = false 8051 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 8052 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 8053 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 8054 * </pre> 8055 * 8056 * @see String#startsWith(String) 8057 * @param str the CharSequence to check, may be null 8058 * @param prefix the prefix to find, may be null 8059 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or 8060 * both {@code null} 8061 * @since 2.4 8062 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 8063 */ 8064 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 8065 return startsWith(str, prefix, true); 8066 } 8067 8068 /** 8069 * Strips whitespace from the start and end of a String. 8070 * 8071 * <p>This is similar to {@link #trim(String)} but removes whitespace. 8072 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8073 * 8074 * <p>A {@code null} input String returns {@code null}.</p> 8075 * 8076 * <pre> 8077 * StringUtils.strip(null) = null 8078 * StringUtils.strip("") = "" 8079 * StringUtils.strip(" ") = "" 8080 * StringUtils.strip("abc") = "abc" 8081 * StringUtils.strip(" abc") = "abc" 8082 * StringUtils.strip("abc ") = "abc" 8083 * StringUtils.strip(" abc ") = "abc" 8084 * StringUtils.strip(" ab c ") = "ab c" 8085 * </pre> 8086 * 8087 * @param str the String to remove whitespace from, may be null 8088 * @return the stripped String, {@code null} if null String input 8089 */ 8090 public static String strip(final String str) { 8091 return strip(str, null); 8092 } 8093 8094 /** 8095 * Strips any of a set of characters from the start and end of a String. 8096 * This is similar to {@link String#trim()} but allows the characters 8097 * to be stripped to be controlled. 8098 * 8099 * <p>A {@code null} input String returns {@code null}. 8100 * An empty string ("") input returns the empty string.</p> 8101 * 8102 * <p>If the stripChars String is {@code null}, whitespace is 8103 * stripped as defined by {@link Character#isWhitespace(char)}. 8104 * Alternatively use {@link #strip(String)}.</p> 8105 * 8106 * <pre> 8107 * StringUtils.strip(null, *) = null 8108 * StringUtils.strip("", *) = "" 8109 * StringUtils.strip("abc", null) = "abc" 8110 * StringUtils.strip(" abc", null) = "abc" 8111 * StringUtils.strip("abc ", null) = "abc" 8112 * StringUtils.strip(" abc ", null) = "abc" 8113 * StringUtils.strip(" abcyx", "xyz") = " abc" 8114 * </pre> 8115 * 8116 * @param str the String to remove characters from, may be null 8117 * @param stripChars the characters to remove, null treated as whitespace 8118 * @return the stripped String, {@code null} if null String input 8119 */ 8120 public static String strip(String str, final String stripChars) { 8121 str = stripStart(str, stripChars); 8122 return stripEnd(str, stripChars); 8123 } 8124 8125 /** 8126 * Removes diacritics (~= accents) from a string. The case will not be altered. 8127 * <p>For instance, 'à' will be replaced by 'a'.</p> 8128 * <p>Note that ligatures will be left as is.</p> 8129 * 8130 * <pre> 8131 * StringUtils.stripAccents(null) = null 8132 * StringUtils.stripAccents("") = "" 8133 * StringUtils.stripAccents("control") = "control" 8134 * StringUtils.stripAccents("éclair") = "eclair" 8135 * </pre> 8136 * 8137 * @param input String to be stripped 8138 * @return input text with diacritics removed 8139 * 8140 * @since 3.0 8141 */ 8142 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 8143 public static String stripAccents(final String input) { 8144 if (input == null) { 8145 return null; 8146 } 8147 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD)); 8148 convertRemainingAccentCharacters(decomposed); 8149 // Note that this doesn't correctly remove ligatures... 8150 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 8151 } 8152 8153 /** 8154 * Strips whitespace from the start and end of every String in an array. 8155 * Whitespace is defined by {@link Character#isWhitespace(char)}. 8156 * 8157 * <p>A new array is returned each time, except for length zero. 8158 * A {@code null} array will return {@code null}. 8159 * An empty array will return itself. 8160 * A {@code null} array entry will be ignored.</p> 8161 * 8162 * <pre> 8163 * StringUtils.stripAll(null) = null 8164 * StringUtils.stripAll([]) = [] 8165 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 8166 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 8167 * </pre> 8168 * 8169 * @param strs the array to remove whitespace from, may be null 8170 * @return the stripped Strings, {@code null} if null array input 8171 */ 8172 public static String[] stripAll(final String... strs) { 8173 return stripAll(strs, null); 8174 } 8175 8176 /** 8177 * Strips any of a set of characters from the start and end of every 8178 * String in an array. 8179 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8180 * 8181 * <p>A new array is returned each time, except for length zero. 8182 * A {@code null} array will return {@code null}. 8183 * An empty array will return itself. 8184 * A {@code null} array entry will be ignored. 8185 * A {@code null} stripChars will strip whitespace as defined by 8186 * {@link Character#isWhitespace(char)}.</p> 8187 * 8188 * <pre> 8189 * StringUtils.stripAll(null, *) = null 8190 * StringUtils.stripAll([], *) = [] 8191 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 8192 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 8193 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 8194 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 8195 * </pre> 8196 * 8197 * @param strs the array to remove characters from, may be null 8198 * @param stripChars the characters to remove, null treated as whitespace 8199 * @return the stripped Strings, {@code null} if null array input 8200 */ 8201 public static String[] stripAll(final String[] strs, final String stripChars) { 8202 final int strsLen = ArrayUtils.getLength(strs); 8203 if (strsLen == 0) { 8204 return strs; 8205 } 8206 final String[] newArr = new String[strsLen]; 8207 Arrays.setAll(newArr, i -> strip(strs[i], stripChars)); 8208 return newArr; 8209 } 8210 8211 /** 8212 * Strips any of a set of characters from the end of a String. 8213 * 8214 * <p>A {@code null} input String returns {@code null}. 8215 * An empty string ("") input returns the empty string.</p> 8216 * 8217 * <p>If the stripChars String is {@code null}, whitespace is 8218 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8219 * 8220 * <pre> 8221 * StringUtils.stripEnd(null, *) = null 8222 * StringUtils.stripEnd("", *) = "" 8223 * StringUtils.stripEnd("abc", "") = "abc" 8224 * StringUtils.stripEnd("abc", null) = "abc" 8225 * StringUtils.stripEnd(" abc", null) = " abc" 8226 * StringUtils.stripEnd("abc ", null) = "abc" 8227 * StringUtils.stripEnd(" abc ", null) = " abc" 8228 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 8229 * StringUtils.stripEnd("120.00", ".0") = "12" 8230 * </pre> 8231 * 8232 * @param str the String to remove characters from, may be null 8233 * @param stripChars the set of characters to remove, null treated as whitespace 8234 * @return the stripped String, {@code null} if null String input 8235 */ 8236 public static String stripEnd(final String str, final String stripChars) { 8237 int end = length(str); 8238 if (end == 0) { 8239 return str; 8240 } 8241 8242 if (stripChars == null) { 8243 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 8244 end--; 8245 } 8246 } else if (stripChars.isEmpty()) { 8247 return str; 8248 } else { 8249 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 8250 end--; 8251 } 8252 } 8253 return str.substring(0, end); 8254 } 8255 8256 /** 8257 * Strips any of a set of characters from the start of a String. 8258 * 8259 * <p>A {@code null} input String returns {@code null}. 8260 * An empty string ("") input returns the empty string.</p> 8261 * 8262 * <p>If the stripChars String is {@code null}, whitespace is 8263 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 8264 * 8265 * <pre> 8266 * StringUtils.stripStart(null, *) = null 8267 * StringUtils.stripStart("", *) = "" 8268 * StringUtils.stripStart("abc", "") = "abc" 8269 * StringUtils.stripStart("abc", null) = "abc" 8270 * StringUtils.stripStart(" abc", null) = "abc" 8271 * StringUtils.stripStart("abc ", null) = "abc " 8272 * StringUtils.stripStart(" abc ", null) = "abc " 8273 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8274 * </pre> 8275 * 8276 * @param str the String to remove characters from, may be null 8277 * @param stripChars the characters to remove, null treated as whitespace 8278 * @return the stripped String, {@code null} if null String input 8279 */ 8280 public static String stripStart(final String str, final String stripChars) { 8281 final int strLen = length(str); 8282 if (strLen == 0) { 8283 return str; 8284 } 8285 int start = 0; 8286 if (stripChars == null) { 8287 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8288 start++; 8289 } 8290 } else if (stripChars.isEmpty()) { 8291 return str; 8292 } else { 8293 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 8294 start++; 8295 } 8296 } 8297 return str.substring(start); 8298 } 8299 8300 /** 8301 * Strips whitespace from the start and end of a String returning 8302 * an empty String if {@code null} input. 8303 * 8304 * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace. 8305 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8306 * 8307 * <pre> 8308 * StringUtils.stripToEmpty(null) = "" 8309 * StringUtils.stripToEmpty("") = "" 8310 * StringUtils.stripToEmpty(" ") = "" 8311 * StringUtils.stripToEmpty("abc") = "abc" 8312 * StringUtils.stripToEmpty(" abc") = "abc" 8313 * StringUtils.stripToEmpty("abc ") = "abc" 8314 * StringUtils.stripToEmpty(" abc ") = "abc" 8315 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8316 * </pre> 8317 * 8318 * @param str the String to be stripped, may be null 8319 * @return the trimmed String, or an empty String if {@code null} input 8320 * @since 2.0 8321 */ 8322 public static String stripToEmpty(final String str) { 8323 return str == null ? EMPTY : strip(str, null); 8324 } 8325 8326 /** 8327 * Strips whitespace from the start and end of a String returning 8328 * {@code null} if the String is empty ("") after the strip. 8329 * 8330 * <p>This is similar to {@link #trimToNull(String)} but removes whitespace. 8331 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 8332 * 8333 * <pre> 8334 * StringUtils.stripToNull(null) = null 8335 * StringUtils.stripToNull("") = null 8336 * StringUtils.stripToNull(" ") = null 8337 * StringUtils.stripToNull("abc") = "abc" 8338 * StringUtils.stripToNull(" abc") = "abc" 8339 * StringUtils.stripToNull("abc ") = "abc" 8340 * StringUtils.stripToNull(" abc ") = "abc" 8341 * StringUtils.stripToNull(" ab c ") = "ab c" 8342 * </pre> 8343 * 8344 * @param str the String to be stripped, may be null 8345 * @return the stripped String, 8346 * {@code null} if whitespace, empty or null String input 8347 * @since 2.0 8348 */ 8349 public static String stripToNull(String str) { 8350 if (str == null) { 8351 return null; 8352 } 8353 str = strip(str, null); 8354 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here 8355 } 8356 8357 /** 8358 * Gets a substring from the specified String avoiding exceptions. 8359 * 8360 * <p>A negative start position can be used to start {@code n} 8361 * characters from the end of the String.</p> 8362 * 8363 * <p>A {@code null} String will return {@code null}. 8364 * An empty ("") String will return "".</p> 8365 * 8366 * <pre> 8367 * StringUtils.substring(null, *) = null 8368 * StringUtils.substring("", *) = "" 8369 * StringUtils.substring("abc", 0) = "abc" 8370 * StringUtils.substring("abc", 2) = "c" 8371 * StringUtils.substring("abc", 4) = "" 8372 * StringUtils.substring("abc", -2) = "bc" 8373 * StringUtils.substring("abc", -4) = "abc" 8374 * </pre> 8375 * 8376 * @param str the String to get the substring from, may be null 8377 * @param start the position to start from, negative means 8378 * count back from the end of the String by this many characters 8379 * @return substring from start position, {@code null} if null String input 8380 */ 8381 public static String substring(final String str, int start) { 8382 if (str == null) { 8383 return null; 8384 } 8385 8386 // handle negatives, which means last n characters 8387 if (start < 0) { 8388 start = str.length() + start; // remember start is negative 8389 } 8390 8391 if (start < 0) { 8392 start = 0; 8393 } 8394 if (start > str.length()) { 8395 return EMPTY; 8396 } 8397 8398 return str.substring(start); 8399 } 8400 8401 /** 8402 * Gets a substring from the specified String avoiding exceptions. 8403 * 8404 * <p>A negative start position can be used to start/end {@code n} 8405 * characters from the end of the String.</p> 8406 * 8407 * <p>The returned substring starts with the character in the {@code start} 8408 * position and ends before the {@code end} position. All position counting is 8409 * zero-based -- i.e., to start at the beginning of the string use 8410 * {@code start = 0}. Negative start and end positions can be used to 8411 * specify offsets relative to the end of the String.</p> 8412 * 8413 * <p>If {@code start} is not strictly to the left of {@code end}, "" 8414 * is returned.</p> 8415 * 8416 * <pre> 8417 * StringUtils.substring(null, *, *) = null 8418 * StringUtils.substring("", * , *) = ""; 8419 * StringUtils.substring("abc", 0, 2) = "ab" 8420 * StringUtils.substring("abc", 2, 0) = "" 8421 * StringUtils.substring("abc", 2, 4) = "c" 8422 * StringUtils.substring("abc", 4, 6) = "" 8423 * StringUtils.substring("abc", 2, 2) = "" 8424 * StringUtils.substring("abc", -2, -1) = "b" 8425 * StringUtils.substring("abc", -4, 2) = "ab" 8426 * </pre> 8427 * 8428 * @param str the String to get the substring from, may be null 8429 * @param start the position to start from, negative means 8430 * count back from the end of the String by this many characters 8431 * @param end the position to end at (exclusive), negative means 8432 * count back from the end of the String by this many characters 8433 * @return substring from start position to end position, 8434 * {@code null} if null String input 8435 */ 8436 public static String substring(final String str, int start, int end) { 8437 if (str == null) { 8438 return null; 8439 } 8440 8441 // handle negatives 8442 if (end < 0) { 8443 end = str.length() + end; // remember end is negative 8444 } 8445 if (start < 0) { 8446 start = str.length() + start; // remember start is negative 8447 } 8448 8449 // check length next 8450 if (end > str.length()) { 8451 end = str.length(); 8452 } 8453 8454 // if start is greater than end, return "" 8455 if (start > end) { 8456 return EMPTY; 8457 } 8458 8459 if (start < 0) { 8460 start = 0; 8461 } 8462 if (end < 0) { 8463 end = 0; 8464 } 8465 8466 return str.substring(start, end); 8467 } 8468 8469 /** 8470 * Gets the substring after the first occurrence of a separator. 8471 * The separator is not returned. 8472 * 8473 * <p>A {@code null} string input will return {@code null}. 8474 * An empty ("") string input will return the empty string. 8475 * 8476 * <p>If nothing is found, the empty string is returned.</p> 8477 * 8478 * <pre> 8479 * StringUtils.substringAfter(null, *) = null 8480 * StringUtils.substringAfter("", *) = "" 8481 * StringUtils.substringAfter("abc", 'a') = "bc" 8482 * StringUtils.substringAfter("abcba", 'b') = "cba" 8483 * StringUtils.substringAfter("abc", 'c') = "" 8484 * StringUtils.substringAfter("abc", 'd') = "" 8485 * StringUtils.substringAfter(" abc", 32) = "abc" 8486 * </pre> 8487 * 8488 * @param str the String to get a substring from, may be null 8489 * @param separator the character (Unicode code point) to search. 8490 * @return the substring after the first occurrence of the separator, 8491 * {@code null} if null String input 8492 * @since 3.11 8493 */ 8494 public static String substringAfter(final String str, final int separator) { 8495 if (isEmpty(str)) { 8496 return str; 8497 } 8498 final int pos = str.indexOf(separator); 8499 if (pos == INDEX_NOT_FOUND) { 8500 return EMPTY; 8501 } 8502 return str.substring(pos + 1); 8503 } 8504 8505 /** 8506 * Gets the substring after the first occurrence of a separator. 8507 * The separator is not returned. 8508 * 8509 * <p>A {@code null} string input will return {@code null}. 8510 * An empty ("") string input will return the empty string. 8511 * A {@code null} separator will return the empty string if the 8512 * input string is not {@code null}.</p> 8513 * 8514 * <p>If nothing is found, the empty string is returned.</p> 8515 * 8516 * <pre> 8517 * StringUtils.substringAfter(null, *) = null 8518 * StringUtils.substringAfter("", *) = "" 8519 * StringUtils.substringAfter(*, null) = "" 8520 * StringUtils.substringAfter("abc", "a") = "bc" 8521 * StringUtils.substringAfter("abcba", "b") = "cba" 8522 * StringUtils.substringAfter("abc", "c") = "" 8523 * StringUtils.substringAfter("abc", "d") = "" 8524 * StringUtils.substringAfter("abc", "") = "abc" 8525 * </pre> 8526 * 8527 * @param str the String to get a substring from, may be null 8528 * @param separator the String to search for, may be null 8529 * @return the substring after the first occurrence of the separator, 8530 * {@code null} if null String input 8531 * @since 2.0 8532 */ 8533 public static String substringAfter(final String str, final String separator) { 8534 if (isEmpty(str)) { 8535 return str; 8536 } 8537 if (separator == null) { 8538 return EMPTY; 8539 } 8540 final int pos = str.indexOf(separator); 8541 if (pos == INDEX_NOT_FOUND) { 8542 return EMPTY; 8543 } 8544 return str.substring(pos + separator.length()); 8545 } 8546 8547 /** 8548 * Gets the substring after the last occurrence of a separator. 8549 * The separator is not returned. 8550 * 8551 * <p>A {@code null} string input will return {@code null}. 8552 * An empty ("") string input will return the empty string. 8553 * 8554 * <p>If nothing is found, the empty string is returned.</p> 8555 * 8556 * <pre> 8557 * StringUtils.substringAfterLast(null, *) = null 8558 * StringUtils.substringAfterLast("", *) = "" 8559 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8560 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8561 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8562 * StringUtils.substringAfterLast("abc", 'c') = "" 8563 * StringUtils.substringAfterLast("a", 'a') = "" 8564 * StringUtils.substringAfterLast("a", 'z') = "" 8565 * </pre> 8566 * 8567 * @param str the String to get a substring from, may be null 8568 * @param separator the character (Unicode code point) to search. 8569 * @return the substring after the last occurrence of the separator, 8570 * {@code null} if null String input 8571 * @since 3.11 8572 */ 8573 public static String substringAfterLast(final String str, final int separator) { 8574 if (isEmpty(str)) { 8575 return str; 8576 } 8577 final int pos = str.lastIndexOf(separator); 8578 if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) { 8579 return EMPTY; 8580 } 8581 return str.substring(pos + 1); 8582 } 8583 8584 /** 8585 * Gets the substring after the last occurrence of a separator. 8586 * The separator is not returned. 8587 * 8588 * <p>A {@code null} string input will return {@code null}. 8589 * An empty ("") string input will return the empty string. 8590 * An empty or {@code null} separator will return the empty string if 8591 * the input string is not {@code null}.</p> 8592 * 8593 * <p>If nothing is found, the empty string is returned.</p> 8594 * 8595 * <pre> 8596 * StringUtils.substringAfterLast(null, *) = null 8597 * StringUtils.substringAfterLast("", *) = "" 8598 * StringUtils.substringAfterLast(*, "") = "" 8599 * StringUtils.substringAfterLast(*, null) = "" 8600 * StringUtils.substringAfterLast("abc", "a") = "bc" 8601 * StringUtils.substringAfterLast("abcba", "b") = "a" 8602 * StringUtils.substringAfterLast("abc", "c") = "" 8603 * StringUtils.substringAfterLast("a", "a") = "" 8604 * StringUtils.substringAfterLast("a", "z") = "" 8605 * </pre> 8606 * 8607 * @param str the String to get a substring from, may be null 8608 * @param separator the String to search for, may be null 8609 * @return the substring after the last occurrence of the separator, 8610 * {@code null} if null String input 8611 * @since 2.0 8612 */ 8613 public static String substringAfterLast(final String str, final String separator) { 8614 if (isEmpty(str)) { 8615 return str; 8616 } 8617 if (isEmpty(separator)) { 8618 return EMPTY; 8619 } 8620 final int pos = str.lastIndexOf(separator); 8621 if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) { 8622 return EMPTY; 8623 } 8624 return str.substring(pos + separator.length()); 8625 } 8626 8627 /** 8628 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8629 * 8630 * <p> 8631 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8632 * </p> 8633 * 8634 * <p> 8635 * If nothing is found, the string input is returned. 8636 * </p> 8637 * 8638 * <pre> 8639 * StringUtils.substringBefore(null, *) = null 8640 * StringUtils.substringBefore("", *) = "" 8641 * StringUtils.substringBefore("abc", 'a') = "" 8642 * StringUtils.substringBefore("abcba", 'b') = "a" 8643 * StringUtils.substringBefore("abc", 'c') = "ab" 8644 * StringUtils.substringBefore("abc", 'd') = "abc" 8645 * </pre> 8646 * 8647 * @param str the String to get a substring from, may be null 8648 * @param separator the character (Unicode code point) to search. 8649 * @return the substring before the first occurrence of the separator, {@code null} if null String input 8650 * @since 3.12.0 8651 */ 8652 public static String substringBefore(final String str, final int separator) { 8653 if (isEmpty(str)) { 8654 return str; 8655 } 8656 final int pos = str.indexOf(separator); 8657 if (pos == INDEX_NOT_FOUND) { 8658 return str; 8659 } 8660 return str.substring(0, pos); 8661 } 8662 8663 /** 8664 * Gets the substring before the first occurrence of a separator. 8665 * The separator is not returned. 8666 * 8667 * <p>A {@code null} string input will return {@code null}. 8668 * An empty ("") string input will return the empty string. 8669 * A {@code null} separator will return the input string.</p> 8670 * 8671 * <p>If nothing is found, the string input is returned.</p> 8672 * 8673 * <pre> 8674 * StringUtils.substringBefore(null, *) = null 8675 * StringUtils.substringBefore("", *) = "" 8676 * StringUtils.substringBefore("abc", "a") = "" 8677 * StringUtils.substringBefore("abcba", "b") = "a" 8678 * StringUtils.substringBefore("abc", "c") = "ab" 8679 * StringUtils.substringBefore("abc", "d") = "abc" 8680 * StringUtils.substringBefore("abc", "") = "" 8681 * StringUtils.substringBefore("abc", null) = "abc" 8682 * </pre> 8683 * 8684 * @param str the String to get a substring from, may be null 8685 * @param separator the String to search for, may be null 8686 * @return the substring before the first occurrence of the separator, 8687 * {@code null} if null String input 8688 * @since 2.0 8689 */ 8690 public static String substringBefore(final String str, final String separator) { 8691 if (isEmpty(str) || separator == null) { 8692 return str; 8693 } 8694 if (separator.isEmpty()) { 8695 return EMPTY; 8696 } 8697 final int pos = str.indexOf(separator); 8698 if (pos == INDEX_NOT_FOUND) { 8699 return str; 8700 } 8701 return str.substring(0, pos); 8702 } 8703 8704 /** 8705 * Gets the substring before the last occurrence of a separator. 8706 * The separator is not returned. 8707 * 8708 * <p>A {@code null} string input will return {@code null}. 8709 * An empty ("") string input will return the empty string. 8710 * An empty or {@code null} separator will return the input string.</p> 8711 * 8712 * <p>If nothing is found, the string input is returned.</p> 8713 * 8714 * <pre> 8715 * StringUtils.substringBeforeLast(null, *) = null 8716 * StringUtils.substringBeforeLast("", *) = "" 8717 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8718 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8719 * StringUtils.substringBeforeLast("a", "a") = "" 8720 * StringUtils.substringBeforeLast("a", "z") = "a" 8721 * StringUtils.substringBeforeLast("a", null) = "a" 8722 * StringUtils.substringBeforeLast("a", "") = "a" 8723 * </pre> 8724 * 8725 * @param str the String to get a substring from, may be null 8726 * @param separator the String to search for, may be null 8727 * @return the substring before the last occurrence of the separator, 8728 * {@code null} if null String input 8729 * @since 2.0 8730 */ 8731 public static String substringBeforeLast(final String str, final String separator) { 8732 if (isEmpty(str) || isEmpty(separator)) { 8733 return str; 8734 } 8735 final int pos = str.lastIndexOf(separator); 8736 if (pos == INDEX_NOT_FOUND) { 8737 return str; 8738 } 8739 return str.substring(0, pos); 8740 } 8741 8742 /** 8743 * Gets the String that is nested in between two instances of the 8744 * same String. 8745 * 8746 * <p>A {@code null} input String returns {@code null}. 8747 * A {@code null} tag returns {@code null}.</p> 8748 * 8749 * <pre> 8750 * StringUtils.substringBetween(null, *) = null 8751 * StringUtils.substringBetween("", "") = "" 8752 * StringUtils.substringBetween("", "tag") = null 8753 * StringUtils.substringBetween("tagabctag", null) = null 8754 * StringUtils.substringBetween("tagabctag", "") = "" 8755 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8756 * </pre> 8757 * 8758 * @param str the String containing the substring, may be null 8759 * @param tag the String before and after the substring, may be null 8760 * @return the substring, {@code null} if no match 8761 * @since 2.0 8762 */ 8763 public static String substringBetween(final String str, final String tag) { 8764 return substringBetween(str, tag, tag); 8765 } 8766 8767 /** 8768 * Gets the String that is nested in between two Strings. 8769 * Only the first match is returned. 8770 * 8771 * <p>A {@code null} input String returns {@code null}. 8772 * A {@code null} open/close returns {@code null} (no match). 8773 * An empty ("") open and close returns an empty string.</p> 8774 * 8775 * <pre> 8776 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8777 * StringUtils.substringBetween(null, *, *) = null 8778 * StringUtils.substringBetween(*, null, *) = null 8779 * StringUtils.substringBetween(*, *, null) = null 8780 * StringUtils.substringBetween("", "", "") = "" 8781 * StringUtils.substringBetween("", "", "]") = null 8782 * StringUtils.substringBetween("", "[", "]") = null 8783 * StringUtils.substringBetween("yabcz", "", "") = "" 8784 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8785 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8786 * </pre> 8787 * 8788 * @param str the String containing the substring, may be null 8789 * @param open the String before the substring, may be null 8790 * @param close the String after the substring, may be null 8791 * @return the substring, {@code null} if no match 8792 * @since 2.0 8793 */ 8794 public static String substringBetween(final String str, final String open, final String close) { 8795 if (!ObjectUtils.allNotNull(str, open, close)) { 8796 return null; 8797 } 8798 final int start = str.indexOf(open); 8799 if (start != INDEX_NOT_FOUND) { 8800 final int end = str.indexOf(close, start + open.length()); 8801 if (end != INDEX_NOT_FOUND) { 8802 return str.substring(start + open.length(), end); 8803 } 8804 } 8805 return null; 8806 } 8807 8808 /** 8809 * Searches a String for substrings delimited by a start and end tag, 8810 * returning all matching substrings in an array. 8811 * 8812 * <p>A {@code null} input String returns {@code null}. 8813 * A {@code null} open/close returns {@code null} (no match). 8814 * An empty ("") open/close returns {@code null} (no match).</p> 8815 * 8816 * <pre> 8817 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8818 * StringUtils.substringsBetween(null, *, *) = null 8819 * StringUtils.substringsBetween(*, null, *) = null 8820 * StringUtils.substringsBetween(*, *, null) = null 8821 * StringUtils.substringsBetween("", "[", "]") = [] 8822 * </pre> 8823 * 8824 * @param str the String containing the substrings, null returns null, empty returns empty 8825 * @param open the String identifying the start of the substring, empty returns null 8826 * @param close the String identifying the end of the substring, empty returns null 8827 * @return a String Array of substrings, or {@code null} if no match 8828 * @since 2.3 8829 */ 8830 public static String[] substringsBetween(final String str, final String open, final String close) { 8831 if (str == null || isEmpty(open) || isEmpty(close)) { 8832 return null; 8833 } 8834 final int strLen = str.length(); 8835 if (strLen == 0) { 8836 return ArrayUtils.EMPTY_STRING_ARRAY; 8837 } 8838 final int closeLen = close.length(); 8839 final int openLen = open.length(); 8840 final List<String> list = new ArrayList<>(); 8841 int pos = 0; 8842 while (pos < strLen - closeLen) { 8843 int start = str.indexOf(open, pos); 8844 if (start < 0) { 8845 break; 8846 } 8847 start += openLen; 8848 final int end = str.indexOf(close, start); 8849 if (end < 0) { 8850 break; 8851 } 8852 list.add(str.substring(start, end)); 8853 pos = end + closeLen; 8854 } 8855 if (list.isEmpty()) { 8856 return null; 8857 } 8858 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8859 } 8860 8861 /** 8862 * Swaps the case of a String changing upper and title case to 8863 * lower case, and lower case to upper case. 8864 * 8865 * <ul> 8866 * <li>Upper case character converts to Lower case</li> 8867 * <li>Title case character converts to Lower case</li> 8868 * <li>Lower case character converts to Upper case</li> 8869 * </ul> 8870 * 8871 * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. 8872 * A {@code null} input String returns {@code null}.</p> 8873 * 8874 * <pre> 8875 * StringUtils.swapCase(null) = null 8876 * StringUtils.swapCase("") = "" 8877 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8878 * </pre> 8879 * 8880 * <p>NOTE: This method changed in Lang version 2.0. 8881 * It no longer performs a word based algorithm. 8882 * If you only use ASCII, you will notice no change. 8883 * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p> 8884 * 8885 * @param str the String to swap case, may be null 8886 * @return the changed String, {@code null} if null String input 8887 */ 8888 public static String swapCase(final String str) { 8889 if (isEmpty(str)) { 8890 return str; 8891 } 8892 8893 final int strLen = str.length(); 8894 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8895 int outOffset = 0; 8896 for (int i = 0; i < strLen; ) { 8897 final int oldCodepoint = str.codePointAt(i); 8898 final int newCodePoint; 8899 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8900 newCodePoint = Character.toLowerCase(oldCodepoint); 8901 } else if (Character.isLowerCase(oldCodepoint)) { 8902 newCodePoint = Character.toUpperCase(oldCodepoint); 8903 } else { 8904 newCodePoint = oldCodepoint; 8905 } 8906 newCodePoints[outOffset++] = newCodePoint; 8907 i += Character.charCount(newCodePoint); 8908 } 8909 return new String(newCodePoints, 0, outOffset); 8910 } 8911 8912 /** 8913 * Converts a {@link CharSequence} into an array of code points. 8914 * 8915 * <p>Valid pairs of surrogate code units will be converted into a single supplementary 8916 * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or 8917 * a low surrogate not preceded by a high surrogate) will be returned as-is.</p> 8918 * 8919 * <pre> 8920 * StringUtils.toCodePoints(null) = null 8921 * StringUtils.toCodePoints("") = [] // empty array 8922 * </pre> 8923 * 8924 * @param cs the character sequence to convert 8925 * @return an array of code points 8926 * @since 3.6 8927 */ 8928 public static int[] toCodePoints(final CharSequence cs) { 8929 if (cs == null) { 8930 return null; 8931 } 8932 if (cs.length() == 0) { 8933 return ArrayUtils.EMPTY_INT_ARRAY; 8934 } 8935 8936 final String s = cs.toString(); 8937 final int[] result = new int[s.codePointCount(0, s.length())]; 8938 int index = 0; 8939 for (int i = 0; i < result.length; i++) { 8940 result[i] = s.codePointAt(index); 8941 index += Character.charCount(result[i]); 8942 } 8943 return result; 8944 } 8945 8946 /** 8947 * Converts a {@code byte[]} to a String using the specified character encoding. 8948 * 8949 * @param bytes 8950 * the byte array to read from 8951 * @param charset 8952 * the encoding to use, if null then use the platform default 8953 * @return a new String 8954 * @throws NullPointerException 8955 * if {@code bytes} is null 8956 * @since 3.2 8957 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8958 */ 8959 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8960 return new String(bytes, Charsets.toCharset(charset)); 8961 } 8962 8963 /** 8964 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8965 * 8966 * @param source A source String or null. 8967 * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8968 * @since 3.10 8969 */ 8970 public static String toRootLowerCase(final String source) { 8971 return source == null ? null : source.toLowerCase(Locale.ROOT); 8972 } 8973 8974 /** 8975 * Converts the given source String as a upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8976 * 8977 * @param source A source String or null. 8978 * @return the given source String as a upper-case using the {@link Locale#ROOT} locale or null. 8979 * @since 3.10 8980 */ 8981 public static String toRootUpperCase(final String source) { 8982 return source == null ? null : source.toUpperCase(Locale.ROOT); 8983 } 8984 8985 /** 8986 * Converts a {@code byte[]} to a String using the specified character encoding. 8987 * 8988 * @param bytes 8989 * the byte array to read from 8990 * @param charsetName 8991 * the encoding to use, if null then use the platform default 8992 * @return a new String 8993 * @throws UnsupportedEncodingException 8994 * Never thrown 8995 * @throws NullPointerException 8996 * if the input is null 8997 * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code 8998 * @since 3.1 8999 */ 9000 @Deprecated 9001 public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException { 9002 return new String(bytes, Charsets.toCharset(charsetName)); 9003 } 9004 9005 private static String toStringOrEmpty(final Object obj) { 9006 return Objects.toString(obj, EMPTY); 9007 } 9008 9009 /** 9010 * Removes control characters (char <= 32) from both 9011 * ends of this String, handling {@code null} by returning 9012 * {@code null}. 9013 * 9014 * <p>The String is trimmed using {@link String#trim()}. 9015 * Trim removes start and end characters <= 32. 9016 * To strip whitespace use {@link #strip(String)}.</p> 9017 * 9018 * <p>To trim your choice of characters, use the 9019 * {@link #strip(String, String)} methods.</p> 9020 * 9021 * <pre> 9022 * StringUtils.trim(null) = null 9023 * StringUtils.trim("") = "" 9024 * StringUtils.trim(" ") = "" 9025 * StringUtils.trim("abc") = "abc" 9026 * StringUtils.trim(" abc ") = "abc" 9027 * </pre> 9028 * 9029 * @param str the String to be trimmed, may be null 9030 * @return the trimmed string, {@code null} if null String input 9031 */ 9032 public static String trim(final String str) { 9033 return str == null ? null : str.trim(); 9034 } 9035 9036 /** 9037 * Removes control characters (char <= 32) from both 9038 * ends of this String returning an empty String ("") if the String 9039 * is empty ("") after the trim or if it is {@code null}. 9040 * 9041 * <p>The String is trimmed using {@link String#trim()}. 9042 * Trim removes start and end characters <= 32. 9043 * To strip whitespace use {@link #stripToEmpty(String)}. 9044 * 9045 * <pre> 9046 * StringUtils.trimToEmpty(null) = "" 9047 * StringUtils.trimToEmpty("") = "" 9048 * StringUtils.trimToEmpty(" ") = "" 9049 * StringUtils.trimToEmpty("abc") = "abc" 9050 * StringUtils.trimToEmpty(" abc ") = "abc" 9051 * </pre> 9052 * 9053 * @param str the String to be trimmed, may be null 9054 * @return the trimmed String, or an empty String if {@code null} input 9055 * @since 2.0 9056 */ 9057 public static String trimToEmpty(final String str) { 9058 return str == null ? EMPTY : str.trim(); 9059 } 9060 9061 /** 9062 * Removes control characters (char <= 32) from both 9063 * ends of this String returning {@code null} if the String is 9064 * empty ("") after the trim or if it is {@code null}. 9065 * 9066 * <p>The String is trimmed using {@link String#trim()}. 9067 * Trim removes start and end characters <= 32. 9068 * To strip whitespace use {@link #stripToNull(String)}. 9069 * 9070 * <pre> 9071 * StringUtils.trimToNull(null) = null 9072 * StringUtils.trimToNull("") = null 9073 * StringUtils.trimToNull(" ") = null 9074 * StringUtils.trimToNull("abc") = "abc" 9075 * StringUtils.trimToNull(" abc ") = "abc" 9076 * </pre> 9077 * 9078 * @param str the String to be trimmed, may be null 9079 * @return the trimmed String, 9080 * {@code null} if only chars <= 32, empty or null String input 9081 * @since 2.0 9082 */ 9083 public static String trimToNull(final String str) { 9084 final String ts = trim(str); 9085 return isEmpty(ts) ? null : ts; 9086 } 9087 9088 /** 9089 * Truncates a String. This will turn 9090 * "Now is the time for all good men" into "Now is the time for". 9091 * 9092 * <p>Specifically:</p> 9093 * <ul> 9094 * <li>If {@code str} is less than {@code maxWidth} characters 9095 * long, return it.</li> 9096 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 9097 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9098 * {@link IllegalArgumentException}.</li> 9099 * <li>In no case will it return a String of length greater than 9100 * {@code maxWidth}.</li> 9101 * </ul> 9102 * 9103 * <pre> 9104 * StringUtils.truncate(null, 0) = null 9105 * StringUtils.truncate(null, 2) = null 9106 * StringUtils.truncate("", 4) = "" 9107 * StringUtils.truncate("abcdefg", 4) = "abcd" 9108 * StringUtils.truncate("abcdefg", 6) = "abcdef" 9109 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 9110 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 9111 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 9112 * </pre> 9113 * 9114 * @param str the String to truncate, may be null 9115 * @param maxWidth maximum length of result String, must be positive 9116 * @return truncated String, {@code null} if null String input 9117 * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0} 9118 * @since 3.5 9119 */ 9120 public static String truncate(final String str, final int maxWidth) { 9121 return truncate(str, 0, maxWidth); 9122 } 9123 9124 /** 9125 * Truncates a String. This will turn 9126 * "Now is the time for all good men" into "is the time for all". 9127 * 9128 * <p>Works like {@code truncate(String, int)}, but allows you to specify 9129 * a "left edge" offset. 9130 * 9131 * <p>Specifically:</p> 9132 * <ul> 9133 * <li>If {@code str} is less than {@code maxWidth} characters 9134 * long, return it.</li> 9135 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 9136 * <li>If {@code maxWidth} is less than {@code 0}, throw an 9137 * {@link IllegalArgumentException}.</li> 9138 * <li>If {@code offset} is less than {@code 0}, throw an 9139 * {@link IllegalArgumentException}.</li> 9140 * <li>In no case will it return a String of length greater than 9141 * {@code maxWidth}.</li> 9142 * </ul> 9143 * 9144 * <pre> 9145 * StringUtils.truncate(null, 0, 0) = null 9146 * StringUtils.truncate(null, 2, 4) = null 9147 * StringUtils.truncate("", 0, 10) = "" 9148 * StringUtils.truncate("", 2, 10) = "" 9149 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 9150 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 9151 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 9152 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 9153 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 9154 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 9155 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 9156 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 9157 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 9158 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 9159 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 9160 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 9161 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 9162 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 9163 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 9164 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 9165 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 9166 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 9167 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 9168 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 9169 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 9170 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 9171 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 9172 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 9173 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 9174 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 9175 * </pre> 9176 * 9177 * @param str the String to truncate, may be null 9178 * @param offset left edge of source String 9179 * @param maxWidth maximum length of result String, must be positive 9180 * @return truncated String, {@code null} if null String input 9181 * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0} 9182 * @since 3.5 9183 */ 9184 public static String truncate(final String str, final int offset, final int maxWidth) { 9185 if (offset < 0) { 9186 throw new IllegalArgumentException("offset cannot be negative"); 9187 } 9188 if (maxWidth < 0) { 9189 throw new IllegalArgumentException("maxWith cannot be negative"); 9190 } 9191 if (str == null) { 9192 return null; 9193 } 9194 if (offset > str.length()) { 9195 return EMPTY; 9196 } 9197 if (str.length() > maxWidth) { 9198 final int ix = Math.min(offset + maxWidth, str.length()); 9199 return str.substring(offset, ix); 9200 } 9201 return str.substring(offset); 9202 } 9203 9204 /** 9205 * Uncapitalizes a String, changing the first character to lower case as 9206 * per {@link Character#toLowerCase(int)}. No other characters are changed. 9207 * 9208 * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. 9209 * A {@code null} input String returns {@code null}.</p> 9210 * 9211 * <pre> 9212 * StringUtils.uncapitalize(null) = null 9213 * StringUtils.uncapitalize("") = "" 9214 * StringUtils.uncapitalize("cat") = "cat" 9215 * StringUtils.uncapitalize("Cat") = "cat" 9216 * StringUtils.uncapitalize("CAT") = "cAT" 9217 * </pre> 9218 * 9219 * @param str the String to uncapitalize, may be null 9220 * @return the uncapitalized String, {@code null} if null String input 9221 * @see org.apache.commons.text.WordUtils#uncapitalize(String) 9222 * @see #capitalize(String) 9223 * @since 2.0 9224 */ 9225 public static String uncapitalize(final String str) { 9226 final int strLen = length(str); 9227 if (strLen == 0) { 9228 return str; 9229 } 9230 9231 final int firstCodePoint = str.codePointAt(0); 9232 final int newCodePoint = Character.toLowerCase(firstCodePoint); 9233 if (firstCodePoint == newCodePoint) { 9234 // already capitalized 9235 return str; 9236 } 9237 9238 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 9239 int outOffset = 0; 9240 newCodePoints[outOffset++] = newCodePoint; // copy the first code point 9241 for (int inOffset = Character.charCount(firstCodePoint); inOffset < strLen; ) { 9242 final int codePoint = str.codePointAt(inOffset); 9243 newCodePoints[outOffset++] = codePoint; // copy the remaining ones 9244 inOffset += Character.charCount(codePoint); 9245 } 9246 return new String(newCodePoints, 0, outOffset); 9247 } 9248 9249 /** 9250 * Unwraps a given string from a character. 9251 * 9252 * <pre> 9253 * StringUtils.unwrap(null, null) = null 9254 * StringUtils.unwrap(null, '\0') = null 9255 * StringUtils.unwrap(null, '1') = null 9256 * StringUtils.unwrap("a", 'a') = "a" 9257 * StringUtils.unwrap("aa", 'a') = "" 9258 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 9259 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 9260 * StringUtils.unwrap("A", '#') = "A" 9261 * StringUtils.unwrap("#A", '#') = "#A" 9262 * StringUtils.unwrap("A#", '#') = "A#" 9263 * </pre> 9264 * 9265 * @param str 9266 * the String to be unwrapped, can be null 9267 * @param wrapChar 9268 * the character used to unwrap 9269 * @return unwrapped String or the original string 9270 * if it is not quoted properly with the wrapChar 9271 * @since 3.6 9272 */ 9273 public static String unwrap(final String str, final char wrapChar) { 9274 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 9275 return str; 9276 } 9277 9278 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 9279 final int startIndex = 0; 9280 final int endIndex = str.length() - 1; 9281 9282 return str.substring(startIndex + 1, endIndex); 9283 } 9284 9285 return str; 9286 } 9287 9288 /** 9289 * Unwraps a given string from another string. 9290 * 9291 * <pre> 9292 * StringUtils.unwrap(null, null) = null 9293 * StringUtils.unwrap(null, "") = null 9294 * StringUtils.unwrap(null, "1") = null 9295 * StringUtils.unwrap("a", "a") = "a" 9296 * StringUtils.unwrap("aa", "a") = "" 9297 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 9298 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 9299 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 9300 * StringUtils.unwrap("A", "#") = "A" 9301 * StringUtils.unwrap("#A", "#") = "#A" 9302 * StringUtils.unwrap("A#", "#") = "A#" 9303 * </pre> 9304 * 9305 * @param str 9306 * the String to be unwrapped, can be null 9307 * @param wrapToken 9308 * the String used to unwrap 9309 * @return unwrapped String or the original string 9310 * if it is not quoted properly with the wrapToken 9311 * @since 3.6 9312 */ 9313 public static String unwrap(final String str, final String wrapToken) { 9314 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) { 9315 return str; 9316 } 9317 9318 if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) { 9319 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken)); 9320 } 9321 9322 return str; 9323 } 9324 9325 /** 9326 * Converts a String to upper case as per {@link String#toUpperCase()}. 9327 * 9328 * <p>A {@code null} input String returns {@code null}.</p> 9329 * 9330 * <pre> 9331 * StringUtils.upperCase(null) = null 9332 * StringUtils.upperCase("") = "" 9333 * StringUtils.upperCase("aBc") = "ABC" 9334 * </pre> 9335 * 9336 * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, 9337 * the result of this method is affected by the current locale. 9338 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} 9339 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 9340 * 9341 * @param str the String to upper case, may be null 9342 * @return the upper-cased String, {@code null} if null String input 9343 */ 9344 public static String upperCase(final String str) { 9345 if (str == null) { 9346 return null; 9347 } 9348 return str.toUpperCase(); 9349 } 9350 9351 /** 9352 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}. 9353 * 9354 * <p>A {@code null} input String returns {@code null}.</p> 9355 * 9356 * <pre> 9357 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9358 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9359 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9360 * </pre> 9361 * 9362 * @param str the String to upper case, may be null 9363 * @param locale the locale that defines the case transformation rules, must not be null 9364 * @return the upper-cased String, {@code null} if null String input 9365 * @since 2.5 9366 */ 9367 public static String upperCase(final String str, final Locale locale) { 9368 if (str == null) { 9369 return null; 9370 } 9371 return str.toUpperCase(LocaleUtils.toLocale(locale)); 9372 } 9373 9374 /** 9375 * Returns the string representation of the {@code char} array or null. 9376 * 9377 * @param value the character array. 9378 * @return a String or null 9379 * @see String#valueOf(char[]) 9380 * @since 3.9 9381 */ 9382 public static String valueOf(final char[] value) { 9383 return value == null ? null : String.valueOf(value); 9384 } 9385 9386 /** 9387 * Wraps a string with a char. 9388 * 9389 * <pre> 9390 * StringUtils.wrap(null, *) = null 9391 * StringUtils.wrap("", *) = "" 9392 * StringUtils.wrap("ab", '\0') = "ab" 9393 * StringUtils.wrap("ab", 'x') = "xabx" 9394 * StringUtils.wrap("ab", '\'') = "'ab'" 9395 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9396 * </pre> 9397 * 9398 * @param str 9399 * the string to be wrapped, may be {@code null} 9400 * @param wrapWith 9401 * the char that will wrap {@code str} 9402 * @return the wrapped string, or {@code null} if {@code str==null} 9403 * @since 3.4 9404 */ 9405 public static String wrap(final String str, final char wrapWith) { 9406 9407 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9408 return str; 9409 } 9410 9411 return wrapWith + str + wrapWith; 9412 } 9413 9414 /** 9415 * Wraps a String with another String. 9416 * 9417 * <p> 9418 * A {@code null} input String returns {@code null}. 9419 * </p> 9420 * 9421 * <pre> 9422 * StringUtils.wrap(null, *) = null 9423 * StringUtils.wrap("", *) = "" 9424 * StringUtils.wrap("ab", null) = "ab" 9425 * StringUtils.wrap("ab", "x") = "xabx" 9426 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9427 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9428 * StringUtils.wrap("ab", "'") = "'ab'" 9429 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9430 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9431 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9432 * </pre> 9433 * 9434 * @param str 9435 * the String to be wrapper, may be null 9436 * @param wrapWith 9437 * the String that will wrap str 9438 * @return wrapped String, {@code null} if null String input 9439 * @since 3.4 9440 */ 9441 public static String wrap(final String str, final String wrapWith) { 9442 9443 if (isEmpty(str) || isEmpty(wrapWith)) { 9444 return str; 9445 } 9446 9447 return wrapWith.concat(str).concat(wrapWith); 9448 } 9449 9450 /** 9451 * Wraps a string with a char if that char is missing from the start or end of the given string. 9452 * 9453 * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p> 9454 * 9455 * <pre> 9456 * StringUtils.wrapIfMissing(null, *) = null 9457 * StringUtils.wrapIfMissing("", *) = "" 9458 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9459 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9460 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9461 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9462 * StringUtils.wrapIfMissing("/", '/') = "/" 9463 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9464 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9465 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9466 * </pre> 9467 * 9468 * @param str 9469 * the string to be wrapped, may be {@code null} 9470 * @param wrapWith 9471 * the char that will wrap {@code str} 9472 * @return the wrapped string, or {@code null} if {@code str==null} 9473 * @since 3.5 9474 */ 9475 public static String wrapIfMissing(final String str, final char wrapWith) { 9476 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9477 return str; 9478 } 9479 final boolean wrapStart = str.charAt(0) != wrapWith; 9480 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9481 if (!wrapStart && !wrapEnd) { 9482 return str; 9483 } 9484 9485 final StringBuilder builder = new StringBuilder(str.length() + 2); 9486 if (wrapStart) { 9487 builder.append(wrapWith); 9488 } 9489 builder.append(str); 9490 if (wrapEnd) { 9491 builder.append(wrapWith); 9492 } 9493 return builder.toString(); 9494 } 9495 9496 /** 9497 * Wraps a string with a string if that string is missing from the start or end of the given string. 9498 * 9499 * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p> 9500 * 9501 * <pre> 9502 * StringUtils.wrapIfMissing(null, *) = null 9503 * StringUtils.wrapIfMissing("", *) = "" 9504 * StringUtils.wrapIfMissing("ab", null) = "ab" 9505 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9506 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9507 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9508 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9509 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9510 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9511 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9512 * StringUtils.wrapIfMissing("/", "/") = "/" 9513 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9514 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9515 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9516 * </pre> 9517 * 9518 * @param str 9519 * the string to be wrapped, may be {@code null} 9520 * @param wrapWith 9521 * the string that will wrap {@code str} 9522 * @return the wrapped string, or {@code null} if {@code str==null} 9523 * @since 3.5 9524 */ 9525 public static String wrapIfMissing(final String str, final String wrapWith) { 9526 if (isEmpty(str) || isEmpty(wrapWith)) { 9527 return str; 9528 } 9529 9530 final boolean wrapStart = !str.startsWith(wrapWith); 9531 final boolean wrapEnd = !str.endsWith(wrapWith); 9532 if (!wrapStart && !wrapEnd) { 9533 return str; 9534 } 9535 9536 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9537 if (wrapStart) { 9538 builder.append(wrapWith); 9539 } 9540 builder.append(str); 9541 if (wrapEnd) { 9542 builder.append(wrapWith); 9543 } 9544 return builder.toString(); 9545 } 9546 9547 /** 9548 * {@link StringUtils} instances should NOT be constructed in 9549 * standard programming. Instead, the class should be used as 9550 * {@code StringUtils.trim(" foo ");}. 9551 * 9552 * <p>This constructor is public to permit tools that require a JavaBean 9553 * instance to operate.</p> 9554 */ 9555 public StringUtils() { 9556 } 9557 9558 }