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 * 1567 * @see Objects#toString(Object, String) 1568 * @see String#valueOf(Object) 1569 * @param str the String to check, may be null 1570 * @param nullDefault the default String to return 1571 * if the input is {@code null}, may be null 1572 * @return the passed in String, or the default if it was {@code null} 1573 * @deprecated Use {@link Objects#toString(Object, String)} 1574 */ 1575 @Deprecated 1576 public static String defaultString(final String str, final String nullDefault) { 1577 return Objects.toString(str, nullDefault); 1578 } 1579 1580 /** 1581 * Deletes all whitespaces from a String as defined by 1582 * {@link Character#isWhitespace(char)}. 1583 * 1584 * <pre> 1585 * StringUtils.deleteWhitespace(null) = null 1586 * StringUtils.deleteWhitespace("") = "" 1587 * StringUtils.deleteWhitespace("abc") = "abc" 1588 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1589 * </pre> 1590 * 1591 * @param str the String to delete whitespace from, may be null 1592 * @return the String without whitespaces, {@code null} if null String input 1593 */ 1594 public static String deleteWhitespace(final String str) { 1595 if (isEmpty(str)) { 1596 return str; 1597 } 1598 final int sz = str.length(); 1599 final char[] chs = new char[sz]; 1600 int count = 0; 1601 for (int i = 0; i < sz; i++) { 1602 if (!Character.isWhitespace(str.charAt(i))) { 1603 chs[count++] = str.charAt(i); 1604 } 1605 } 1606 if (count == sz) { 1607 return str; 1608 } 1609 if (count == 0) { 1610 return EMPTY; 1611 } 1612 return new String(chs, 0, count); 1613 } 1614 1615 /** 1616 * Compares two Strings, and returns the portion where they differ. 1617 * More precisely, return the remainder of the second String, 1618 * starting from where it's different from the first. This means that 1619 * the difference between "abc" and "ab" is the empty String and not "c". 1620 * 1621 * <p>For example, 1622 * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p> 1623 * 1624 * <pre> 1625 * StringUtils.difference(null, null) = null 1626 * StringUtils.difference("", "") = "" 1627 * StringUtils.difference("", "abc") = "abc" 1628 * StringUtils.difference("abc", "") = "" 1629 * StringUtils.difference("abc", "abc") = "" 1630 * StringUtils.difference("abc", "ab") = "" 1631 * StringUtils.difference("ab", "abxyz") = "xyz" 1632 * StringUtils.difference("abcde", "abxyz") = "xyz" 1633 * StringUtils.difference("abcde", "xyz") = "xyz" 1634 * </pre> 1635 * 1636 * @param str1 the first String, may be null 1637 * @param str2 the second String, may be null 1638 * @return the portion of str2 where it differs from str1; returns the 1639 * empty String if they are equal 1640 * @see #indexOfDifference(CharSequence,CharSequence) 1641 * @since 2.0 1642 */ 1643 public static String difference(final String str1, final String str2) { 1644 if (str1 == null) { 1645 return str2; 1646 } 1647 if (str2 == null) { 1648 return str1; 1649 } 1650 final int at = indexOfDifference(str1, str2); 1651 if (at == INDEX_NOT_FOUND) { 1652 return EMPTY; 1653 } 1654 return str2.substring(at); 1655 } 1656 1657 /** 1658 * Check if a CharSequence ends with a specified suffix. 1659 * 1660 * <p>{@code null}s are handled without exceptions. Two {@code null} 1661 * references are considered to be equal. The comparison is case-sensitive.</p> 1662 * 1663 * <pre> 1664 * StringUtils.endsWith(null, null) = true 1665 * StringUtils.endsWith(null, "def") = false 1666 * StringUtils.endsWith("abcdef", null) = false 1667 * StringUtils.endsWith("abcdef", "def") = true 1668 * StringUtils.endsWith("ABCDEF", "def") = false 1669 * StringUtils.endsWith("ABCDEF", "cde") = false 1670 * StringUtils.endsWith("ABCDEF", "") = true 1671 * </pre> 1672 * 1673 * @see String#endsWith(String) 1674 * @param str the CharSequence to check, may be null 1675 * @param suffix the suffix to find, may be null 1676 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or 1677 * both {@code null} 1678 * @since 2.4 1679 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1680 */ 1681 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1682 return endsWith(str, suffix, false); 1683 } 1684 1685 /** 1686 * Check if a CharSequence ends with a specified suffix (optionally case insensitive). 1687 * 1688 * @see String#endsWith(String) 1689 * @param str the CharSequence to check, may be null 1690 * @param suffix the suffix to find, may be null 1691 * @param ignoreCase indicates whether the compare should ignore case 1692 * (case-insensitive) or not. 1693 * @return {@code true} if the CharSequence starts with the prefix or 1694 * both {@code null} 1695 */ 1696 private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { 1697 if (str == null || suffix == null) { 1698 return str == suffix; 1699 } 1700 if (suffix.length() > str.length()) { 1701 return false; 1702 } 1703 final int strOffset = str.length() - suffix.length(); 1704 return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); 1705 } 1706 1707 /** 1708 * Check if a CharSequence ends with any of the provided case-sensitive suffixes. 1709 * 1710 * <pre> 1711 * StringUtils.endsWithAny(null, null) = false 1712 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1713 * StringUtils.endsWithAny("abcxyz", null) = false 1714 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1715 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1716 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1717 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1718 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1719 * </pre> 1720 * 1721 * @param sequence the CharSequence to check, may be null 1722 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null} 1723 * @see StringUtils#endsWith(CharSequence, CharSequence) 1724 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or 1725 * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}. 1726 * @since 3.0 1727 */ 1728 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1729 if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) { 1730 return false; 1731 } 1732 for (final CharSequence searchString : searchStrings) { 1733 if (endsWith(sequence, searchString)) { 1734 return true; 1735 } 1736 } 1737 return false; 1738 } 1739 1740 /** 1741 * Case insensitive check if a CharSequence ends with a specified suffix. 1742 * 1743 * <p>{@code null}s are handled without exceptions. Two {@code null} 1744 * references are considered to be equal. The comparison is case insensitive.</p> 1745 * 1746 * <pre> 1747 * StringUtils.endsWithIgnoreCase(null, null) = true 1748 * StringUtils.endsWithIgnoreCase(null, "def") = false 1749 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1750 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1751 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1752 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1753 * </pre> 1754 * 1755 * @see String#endsWith(String) 1756 * @param str the CharSequence to check, may be null 1757 * @param suffix the suffix to find, may be null 1758 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or 1759 * both {@code null} 1760 * @since 2.4 1761 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1762 */ 1763 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1764 return endsWith(str, suffix, true); 1765 } 1766 1767 /** 1768 * Compares two CharSequences, returning {@code true} if they represent 1769 * equal sequences of characters. 1770 * 1771 * <p>{@code null}s are handled without exceptions. Two {@code null} 1772 * references are considered to be equal. The comparison is <strong>case-sensitive</strong>.</p> 1773 * 1774 * <pre> 1775 * StringUtils.equals(null, null) = true 1776 * StringUtils.equals(null, "abc") = false 1777 * StringUtils.equals("abc", null) = false 1778 * StringUtils.equals("abc", "abc") = true 1779 * StringUtils.equals("abc", "ABC") = false 1780 * </pre> 1781 * 1782 * @param cs1 the first CharSequence, may be {@code null} 1783 * @param cs2 the second CharSequence, may be {@code null} 1784 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} 1785 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1786 * @see Object#equals(Object) 1787 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1788 */ 1789 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1790 if (cs1 == cs2) { 1791 return true; 1792 } 1793 if (cs1 == null || cs2 == null) { 1794 return false; 1795 } 1796 if (cs1.length() != cs2.length()) { 1797 return false; 1798 } 1799 if (cs1 instanceof String && cs2 instanceof String) { 1800 return cs1.equals(cs2); 1801 } 1802 // Step-wise comparison 1803 final int length = cs1.length(); 1804 for (int i = 0; i < length; i++) { 1805 if (cs1.charAt(i) != cs2.charAt(i)) { 1806 return false; 1807 } 1808 } 1809 return true; 1810 } 1811 1812 /** 1813 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1814 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}. 1815 * 1816 * <pre> 1817 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1818 * StringUtils.equalsAny(null, null, null) = true 1819 * StringUtils.equalsAny(null, "abc", "def") = false 1820 * StringUtils.equalsAny("abc", null, "def") = false 1821 * StringUtils.equalsAny("abc", "abc", "def") = true 1822 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1823 * </pre> 1824 * 1825 * @param string to compare, may be {@code null}. 1826 * @param searchStrings a vararg of strings, may be {@code null}. 1827 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; 1828 * {@code false} if {@code searchStrings} is null or contains no matches. 1829 * @since 3.5 1830 */ 1831 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1832 if (ArrayUtils.isNotEmpty(searchStrings)) { 1833 for (final CharSequence next : searchStrings) { 1834 if (equals(string, next)) { 1835 return true; 1836 } 1837 } 1838 } 1839 return false; 1840 } 1841 1842 /** 1843 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1844 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1845 * 1846 * <pre> 1847 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1848 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1849 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1850 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1851 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1852 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1853 * </pre> 1854 * 1855 * @param string to compare, may be {@code null}. 1856 * @param searchStrings a vararg of strings, may be {@code null}. 1857 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1858 * {@code false} if {@code searchStrings} is null or contains no matches. 1859 * @since 3.5 1860 */ 1861 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) { 1862 if (ArrayUtils.isNotEmpty(searchStrings)) { 1863 for (final CharSequence next : searchStrings) { 1864 if (equalsIgnoreCase(string, next)) { 1865 return true; 1866 } 1867 } 1868 } 1869 return false; 1870 } 1871 1872 /** 1873 * Compares two CharSequences, returning {@code true} if they represent 1874 * equal sequences of characters, ignoring case. 1875 * 1876 * <p>{@code null}s are handled without exceptions. Two {@code null} 1877 * references are considered equal. The comparison is <strong>case insensitive</strong>.</p> 1878 * 1879 * <pre> 1880 * StringUtils.equalsIgnoreCase(null, null) = true 1881 * StringUtils.equalsIgnoreCase(null, "abc") = false 1882 * StringUtils.equalsIgnoreCase("abc", null) = false 1883 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1884 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1885 * </pre> 1886 * 1887 * @param cs1 the first CharSequence, may be {@code null} 1888 * @param cs2 the second CharSequence, may be {@code null} 1889 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null} 1890 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1891 * @see #equals(CharSequence, CharSequence) 1892 */ 1893 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1894 if (cs1 == cs2) { 1895 return true; 1896 } 1897 if (cs1 == null || cs2 == null) { 1898 return false; 1899 } 1900 if (cs1.length() != cs2.length()) { 1901 return false; 1902 } 1903 return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length()); 1904 } 1905 1906 /** 1907 * Returns the first value in the array which is not empty (""), 1908 * {@code null} or whitespace only. 1909 * 1910 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 1911 * 1912 * <p>If all values are blank or the array is {@code null} 1913 * or empty then {@code null} is returned.</p> 1914 * 1915 * <pre> 1916 * StringUtils.firstNonBlank(null, null, null) = null 1917 * StringUtils.firstNonBlank(null, "", " ") = null 1918 * StringUtils.firstNonBlank("abc") = "abc" 1919 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1920 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1921 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1922 * StringUtils.firstNonBlank() = null 1923 * </pre> 1924 * 1925 * @param <T> the specific kind of CharSequence 1926 * @param values the values to test, may be {@code null} or empty 1927 * @return the first value from {@code values} which is not blank, 1928 * or {@code null} if there are no non-blank values 1929 * @since 3.8 1930 */ 1931 @SafeVarargs 1932 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1933 if (values != null) { 1934 for (final T val : values) { 1935 if (isNotBlank(val)) { 1936 return val; 1937 } 1938 } 1939 } 1940 return null; 1941 } 1942 1943 /** 1944 * Returns the first value in the array which is not empty. 1945 * 1946 * <p>If all values are empty or the array is {@code null} 1947 * or empty then {@code null} is returned.</p> 1948 * 1949 * <pre> 1950 * StringUtils.firstNonEmpty(null, null, null) = null 1951 * StringUtils.firstNonEmpty(null, null, "") = null 1952 * StringUtils.firstNonEmpty(null, "", " ") = " " 1953 * StringUtils.firstNonEmpty("abc") = "abc" 1954 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1955 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1956 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1957 * StringUtils.firstNonEmpty() = null 1958 * </pre> 1959 * 1960 * @param <T> the specific kind of CharSequence 1961 * @param values the values to test, may be {@code null} or empty 1962 * @return the first value from {@code values} which is not empty, 1963 * or {@code null} if there are no non-empty values 1964 * @since 3.8 1965 */ 1966 @SafeVarargs 1967 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1968 if (values != null) { 1969 for (final T val : values) { 1970 if (isNotEmpty(val)) { 1971 return val; 1972 } 1973 } 1974 } 1975 return null; 1976 } 1977 1978 /** 1979 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1980 * 1981 * @param string input string 1982 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 1983 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1984 * @see String#getBytes(Charset) 1985 * @since 3.10 1986 */ 1987 public static byte[] getBytes(final String string, final Charset charset) { 1988 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1989 } 1990 1991 /** 1992 * Calls {@link String#getBytes(String)} in a null-safe manner. 1993 * 1994 * @param string input string 1995 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 1996 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 1997 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 1998 * @see String#getBytes(String) 1999 * @since 3.10 2000 */ 2001 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 2002 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 2003 } 2004 2005 /** 2006 * Compares all Strings in an array and returns the initial sequence of 2007 * characters that is common to all of them. 2008 * 2009 * <p>For example, 2010 * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "}</p> 2011 * 2012 * <pre> 2013 * StringUtils.getCommonPrefix(null) = "" 2014 * StringUtils.getCommonPrefix(new String[] {}) = "" 2015 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 2016 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 2017 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 2018 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 2019 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 2020 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 2021 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 2022 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 2023 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 2024 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 2025 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 2026 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 2027 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2028 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2029 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2030 * </pre> 2031 * 2032 * @param strs array of String objects, entries may be null 2033 * @return the initial sequence of characters that are common to all Strings 2034 * in the array; empty String if the array is null, the elements are all null 2035 * or if there is no common prefix. 2036 * @since 2.4 2037 */ 2038 public static String getCommonPrefix(final String... strs) { 2039 if (ArrayUtils.isEmpty(strs)) { 2040 return EMPTY; 2041 } 2042 final int smallestIndexOfDiff = indexOfDifference(strs); 2043 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2044 // all strings were identical 2045 if (strs[0] == null) { 2046 return EMPTY; 2047 } 2048 return strs[0]; 2049 } 2050 if (smallestIndexOfDiff == 0) { 2051 // there were no common initial characters 2052 return EMPTY; 2053 } 2054 // we found a common initial character sequence 2055 return strs[0].substring(0, smallestIndexOfDiff); 2056 } 2057 2058 /** 2059 * Checks if a String {@code str} contains Unicode digits, 2060 * if yes then concatenate all the digits in {@code str} and return it as a String. 2061 * 2062 * <p>An empty ("") String will be returned if no digits found in {@code str}.</p> 2063 * 2064 * <pre> 2065 * StringUtils.getDigits(null) = null 2066 * StringUtils.getDigits("") = "" 2067 * StringUtils.getDigits("abc") = "" 2068 * StringUtils.getDigits("1000$") = "1000" 2069 * StringUtils.getDigits("1123~45") = "112345" 2070 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2071 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2072 * </pre> 2073 * 2074 * @param str the String to extract digits from, may be null 2075 * @return String with only digits, 2076 * or an empty ("") String if no digits found, 2077 * or {@code null} String if {@code str} is null 2078 * @since 3.6 2079 */ 2080 public static String getDigits(final String str) { 2081 if (isEmpty(str)) { 2082 return str; 2083 } 2084 final int sz = str.length(); 2085 final StringBuilder strDigits = new StringBuilder(sz); 2086 for (int i = 0; i < sz; i++) { 2087 final char tempChar = str.charAt(i); 2088 if (Character.isDigit(tempChar)) { 2089 strDigits.append(tempChar); 2090 } 2091 } 2092 return strDigits.toString(); 2093 } 2094 2095 /** 2096 * Find the Fuzzy Distance which indicates the similarity score between two Strings. 2097 * 2098 * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text, 2099 * TextMate, Atom and others. One point is given for every matched character. Subsequent 2100 * matches yield two bonus points. A higher score indicates a higher similarity.</p> 2101 * 2102 * <pre> 2103 * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException 2104 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2105 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2106 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2107 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2108 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2109 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2110 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2111 * </pre> 2112 * 2113 * @param term a full term that should be matched against, must not be null 2114 * @param query the query that will be matched against a term, must not be null 2115 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize 2116 * both Strings to lower case. 2117 * @return result score 2118 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null} 2119 * @since 3.4 2120 * @deprecated As of 3.6, use Apache Commons Text 2121 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2122 * FuzzyScore</a> instead 2123 */ 2124 @Deprecated 2125 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2126 if (term == null || query == null) { 2127 throw new IllegalArgumentException("Strings must not be null"); 2128 } 2129 if (locale == null) { 2130 throw new IllegalArgumentException("Locale must not be null"); 2131 } 2132 2133 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2134 // case right from the start. Turning characters to lower case 2135 // via Character.toLowerCase(char) is unfortunately insufficient 2136 // as it does not accept a locale. 2137 final String termLowerCase = term.toString().toLowerCase(locale); 2138 final String queryLowerCase = query.toString().toLowerCase(locale); 2139 2140 // the resulting score 2141 int score = 0; 2142 2143 // the position in the term which will be scanned next for potential 2144 // query character matches 2145 int termIndex = 0; 2146 2147 // index of the previously matched character in the term 2148 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2149 2150 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2151 final char queryChar = queryLowerCase.charAt(queryIndex); 2152 2153 boolean termCharacterMatchFound = false; 2154 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2155 final char termChar = termLowerCase.charAt(termIndex); 2156 2157 if (queryChar == termChar) { 2158 // simple character matches result in one point 2159 score++; 2160 2161 // subsequent character matches further improve 2162 // the score. 2163 if (previousMatchingCharacterIndex + 1 == termIndex) { 2164 score += 2; 2165 } 2166 2167 previousMatchingCharacterIndex = termIndex; 2168 2169 // we can leave the nested loop. Every character in the 2170 // query can match at most one character in the term. 2171 termCharacterMatchFound = true; 2172 } 2173 } 2174 } 2175 2176 return score; 2177 } 2178 2179 /** 2180 * Returns either the passed in CharSequence, or if the CharSequence is 2181 * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}. 2182 * 2183 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2184 * 2185 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2186 * 2187 * <pre> 2188 * {@code 2189 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2190 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2191 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2192 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2193 * StringUtils.getIfBlank("", () -> null) = null 2194 * StringUtils.getIfBlank("", null) = null 2195 * }</pre> 2196 * @param <T> the specific kind of CharSequence 2197 * @param str the CharSequence to check, may be null 2198 * @param defaultSupplier the supplier of default CharSequence to return 2199 * if the input is whitespace, empty ("") or {@code null}, may be null 2200 * @return the passed in CharSequence, or the default 2201 * @see StringUtils#defaultString(String, String) 2202 * @since 3.10 2203 */ 2204 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2205 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2206 } 2207 2208 /** 2209 * Returns either the passed in CharSequence, or if the CharSequence is 2210 * empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2211 * 2212 * <p>Caller responsible for thread-safety and exception handling of default value supplier</p> 2213 * 2214 * <pre> 2215 * {@code 2216 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2217 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2218 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2219 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2220 * StringUtils.getIfEmpty("", () -> null) = null 2221 * StringUtils.getIfEmpty("", null) = null 2222 * } 2223 * </pre> 2224 * @param <T> the specific kind of CharSequence 2225 * @param str the CharSequence to check, may be null 2226 * @param defaultSupplier the supplier of default CharSequence to return 2227 * if the input is empty ("") or {@code null}, may be null 2228 * @return the passed in CharSequence, or the default 2229 * @see StringUtils#defaultString(String, String) 2230 * @since 3.10 2231 */ 2232 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2233 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2234 } 2235 2236 /** 2237 * Find the Jaro Winkler Distance which indicates the similarity score between two Strings. 2238 * 2239 * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. 2240 * Winkler increased this measure for matching initial characters.</p> 2241 * 2242 * <p>This implementation is based on the Jaro Winkler similarity algorithm 2243 * 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> 2244 * 2245 * <pre> 2246 * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException 2247 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2248 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2249 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2250 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2251 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2252 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2253 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2254 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2255 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2256 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2257 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2258 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2259 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2260 * </pre> 2261 * 2262 * @param first the first String, must not be null 2263 * @param second the second String, must not be null 2264 * @return result distance 2265 * @throws IllegalArgumentException if either String input {@code null} 2266 * @since 3.3 2267 * @deprecated As of 3.6, use Apache Commons Text 2268 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2269 * JaroWinklerDistance</a> instead 2270 */ 2271 @Deprecated 2272 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2273 final double DEFAULT_SCALING_FACTOR = 0.1; 2274 2275 if (first == null || second == null) { 2276 throw new IllegalArgumentException("Strings must not be null"); 2277 } 2278 2279 final int[] mtp = matches(first, second); 2280 final double m = mtp[0]; 2281 if (m == 0) { 2282 return 0D; 2283 } 2284 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2285 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2286 return Math.round(jw * 100.0D) / 100.0D; 2287 } 2288 2289 /** 2290 * Find the Levenshtein distance between two Strings. 2291 * 2292 * <p>This is the number of changes needed to change one String into 2293 * another, where each change is a single character modification (deletion, 2294 * insertion or substitution).</p> 2295 * 2296 * <p>The implementation uses a single-dimensional array of length s.length() + 1. See 2297 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2298 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p> 2299 * 2300 * <pre> 2301 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 2302 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 2303 * StringUtils.getLevenshteinDistance("", "") = 0 2304 * StringUtils.getLevenshteinDistance("", "a") = 1 2305 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2306 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2307 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2308 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2309 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2310 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2311 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2312 * </pre> 2313 * 2314 * @param s the first String, must not be null 2315 * @param t the second String, must not be null 2316 * @return result distance 2317 * @throws IllegalArgumentException if either String input {@code null} 2318 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to 2319 * getLevenshteinDistance(CharSequence, CharSequence) 2320 * @deprecated As of 3.6, use Apache Commons Text 2321 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2322 * LevenshteinDistance</a> instead 2323 */ 2324 @Deprecated 2325 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2326 if (s == null || t == null) { 2327 throw new IllegalArgumentException("Strings must not be null"); 2328 } 2329 2330 int n = s.length(); 2331 int m = t.length(); 2332 2333 if (n == 0) { 2334 return m; 2335 } 2336 if (m == 0) { 2337 return n; 2338 } 2339 2340 if (n > m) { 2341 // swap the input strings to consume less memory 2342 final CharSequence tmp = s; 2343 s = t; 2344 t = tmp; 2345 n = m; 2346 m = t.length(); 2347 } 2348 2349 final int[] p = new int[n + 1]; 2350 // indexes into strings s and t 2351 int i; // iterates through s 2352 int j; // iterates through t 2353 int upperleft; 2354 int upper; 2355 2356 char jOfT; // jth character of t 2357 int cost; 2358 2359 for (i = 0; i <= n; i++) { 2360 p[i] = i; 2361 } 2362 2363 for (j = 1; j <= m; j++) { 2364 upperleft = p[0]; 2365 jOfT = t.charAt(j - 1); 2366 p[0] = j; 2367 2368 for (i = 1; i <= n; i++) { 2369 upper = p[i]; 2370 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2371 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2372 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2373 upperleft = upper; 2374 } 2375 } 2376 2377 return p[n]; 2378 } 2379 2380 /** 2381 * Find the Levenshtein distance between two Strings if it's less than or equal to a given 2382 * threshold. 2383 * 2384 * <p>This is the number of changes needed to change one String into 2385 * another, where each change is a single character modification (deletion, 2386 * insertion or substitution).</p> 2387 * 2388 * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield 2389 * and Chas Emerick's implementation of the Levenshtein distance algorithm from 2390 * <a href="https://web.archive.org/web/20120212021906/http%3A//www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 2391 * 2392 * <pre> 2393 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 2394 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 2395 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 2396 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2397 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2398 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2399 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2400 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2401 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2402 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2403 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2404 * </pre> 2405 * 2406 * @param s the first String, must not be null 2407 * @param t the second String, must not be null 2408 * @param threshold the target threshold, must not be negative 2409 * @return result distance, or {@code -1} if the distance would be greater than the threshold 2410 * @throws IllegalArgumentException if either String input {@code null} or negative threshold 2411 * @deprecated As of 3.6, use Apache Commons Text 2412 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2413 * LevenshteinDistance</a> instead 2414 */ 2415 @Deprecated 2416 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2417 if (s == null || t == null) { 2418 throw new IllegalArgumentException("Strings must not be null"); 2419 } 2420 if (threshold < 0) { 2421 throw new IllegalArgumentException("Threshold must not be negative"); 2422 } 2423 2424 /* 2425 This implementation only computes the distance if it's less than or equal to the 2426 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2427 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2428 computing a diagonal stripe of width 2k + 1 of the cost table. 2429 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2430 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2431 d is the distance. 2432 2433 One subtlety comes from needing to ignore entries on the border of our stripe 2434 eg. 2435 p[] = |#|#|#|* 2436 d[] = *|#|#|#| 2437 We must ignore the entry to the left of the leftmost member 2438 We must ignore the entry above the rightmost member 2439 2440 Another subtlety comes from our stripe running off the matrix if the strings aren't 2441 of the same size. Since string s is always swapped to be the shorter of the two, 2442 the stripe will always run off to the upper right instead of the lower left of the matrix. 2443 2444 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2445 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2446 2447 1 2 3 4 5 2448 1 |#|#| | | | 2449 2 |#|#|#| | | 2450 3 | |#|#|#| | 2451 4 | | |#|#|#| 2452 5 | | | |#|#| 2453 6 | | | | |#| 2454 7 | | | | | | 2455 2456 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2457 into one of length 7 in edit distance of 1. 2458 2459 Additionally, this implementation decreases memory usage by using two 2460 single-dimensional arrays and swapping them back and forth instead of allocating 2461 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2462 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2463 large values so that entries we don't compute are ignored. 2464 2465 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2466 */ 2467 2468 int n = s.length(); // length of s 2469 int m = t.length(); // length of t 2470 2471 // if one string is empty, the edit distance is necessarily the length of the other 2472 if (n == 0) { 2473 return m <= threshold ? m : -1; 2474 } 2475 if (m == 0) { 2476 return n <= threshold ? n : -1; 2477 } 2478 if (Math.abs(n - m) > threshold) { 2479 // no need to calculate the distance if the length difference is greater than the threshold 2480 return -1; 2481 } 2482 2483 if (n > m) { 2484 // swap the two strings to consume less memory 2485 final CharSequence tmp = s; 2486 s = t; 2487 t = tmp; 2488 n = m; 2489 m = t.length(); 2490 } 2491 2492 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2493 int[] d = new int[n + 1]; // cost array, horizontally 2494 int[] tmp; // placeholder to assist in swapping p and d 2495 2496 // fill in starting table values 2497 final int boundary = Math.min(n, threshold) + 1; 2498 for (int i = 0; i < boundary; i++) { 2499 p[i] = i; 2500 } 2501 // these fills ensure that the value above the rightmost entry of our 2502 // stripe will be ignored in following loop iterations 2503 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2504 Arrays.fill(d, Integer.MAX_VALUE); 2505 2506 // iterates through t 2507 for (int j = 1; j <= m; j++) { 2508 final char jOfT = t.charAt(j - 1); // jth character of t 2509 d[0] = j; 2510 2511 // compute stripe indices, constrain to array size 2512 final int min = Math.max(1, j - threshold); 2513 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2514 2515 // the stripe may lead off of the table if s and t are of different sizes 2516 if (min > max) { 2517 return -1; 2518 } 2519 2520 // ignore entry left of leftmost 2521 if (min > 1) { 2522 d[min - 1] = Integer.MAX_VALUE; 2523 } 2524 2525 // iterates through [min, max] in s 2526 for (int i = min; i <= max; i++) { 2527 if (s.charAt(i - 1) == jOfT) { 2528 // diagonally left and up 2529 d[i] = p[i - 1]; 2530 } else { 2531 // 1 + minimum of cell to the left, to the top, diagonally left and up 2532 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2533 } 2534 } 2535 2536 // copy current distance counts to 'previous row' distance counts 2537 tmp = p; 2538 p = d; 2539 d = tmp; 2540 } 2541 2542 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2543 // distance 2544 if (p[n] <= threshold) { 2545 return p[n]; 2546 } 2547 return -1; 2548 } 2549 2550 /** 2551 * Finds the first index within a CharSequence, handling {@code null}. 2552 * This method uses {@link String#indexOf(String, int)} if possible. 2553 * 2554 * <p>A {@code null} CharSequence will return {@code -1}.</p> 2555 * 2556 * <pre> 2557 * StringUtils.indexOf(null, *) = -1 2558 * StringUtils.indexOf(*, null) = -1 2559 * StringUtils.indexOf("", "") = 0 2560 * StringUtils.indexOf("", *) = -1 (except when * = "") 2561 * StringUtils.indexOf("aabaabaa", "a") = 0 2562 * StringUtils.indexOf("aabaabaa", "b") = 2 2563 * StringUtils.indexOf("aabaabaa", "ab") = 1 2564 * StringUtils.indexOf("aabaabaa", "") = 0 2565 * </pre> 2566 * 2567 * @param seq the CharSequence to check, may be null 2568 * @param searchSeq the CharSequence to find, may be null 2569 * @return the first index of the search CharSequence, 2570 * -1 if no match or {@code null} string input 2571 * @since 2.0 2572 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2573 */ 2574 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2575 if (seq == null || searchSeq == null) { 2576 return INDEX_NOT_FOUND; 2577 } 2578 return CharSequenceUtils.indexOf(seq, searchSeq, 0); 2579 } 2580 2581 /** 2582 * Finds the first index within a CharSequence, handling {@code null}. 2583 * This method uses {@link String#indexOf(String, int)} if possible. 2584 * 2585 * <p>A {@code null} CharSequence will return {@code -1}. 2586 * A negative start position is treated as zero. 2587 * An empty ("") search CharSequence always matches. 2588 * A start position greater than the string length only matches 2589 * an empty search CharSequence.</p> 2590 * 2591 * <pre> 2592 * StringUtils.indexOf(null, *, *) = -1 2593 * StringUtils.indexOf(*, null, *) = -1 2594 * StringUtils.indexOf("", "", 0) = 0 2595 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2596 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2597 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2598 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2599 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2600 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2601 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2602 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2603 * StringUtils.indexOf("abc", "", 9) = 3 2604 * </pre> 2605 * 2606 * @param seq the CharSequence to check, may be null 2607 * @param searchSeq the CharSequence to find, may be null 2608 * @param startPos the start position, negative treated as zero 2609 * @return the first index of the search CharSequence (always ≥ startPos), 2610 * -1 if no match or {@code null} string input 2611 * @since 2.0 2612 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2613 */ 2614 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2615 if (seq == null || searchSeq == null) { 2616 return INDEX_NOT_FOUND; 2617 } 2618 return CharSequenceUtils.indexOf(seq, searchSeq, startPos); 2619 } 2620 2621 /** 2622 * Returns the index within {@code seq} of the first occurrence of 2623 * the specified character. If a character with value 2624 * {@code searchChar} occurs in the character sequence represented by 2625 * {@code seq} {@link CharSequence} object, then the index (in Unicode 2626 * code units) of the first such occurrence is returned. For 2627 * values of {@code searchChar} in the range from 0 to 0xFFFF 2628 * (inclusive), this is the smallest value <i>k</i> such that: 2629 * <blockquote><pre> 2630 * this.charAt(<i>k</i>) == searchChar 2631 * </pre></blockquote> 2632 * is true. For other values of {@code searchChar}, it is the 2633 * smallest value <i>k</i> such that: 2634 * <blockquote><pre> 2635 * this.codePointAt(<i>k</i>) == searchChar 2636 * </pre></blockquote> 2637 * is true. In either case, if no such character occurs in {@code seq}, 2638 * then {@code INDEX_NOT_FOUND (-1)} is returned. 2639 * 2640 * <p>Furthermore, a {@code null} or empty ("") CharSequence will 2641 * return {@code INDEX_NOT_FOUND (-1)}.</p> 2642 * 2643 * <pre> 2644 * StringUtils.indexOf(null, *) = -1 2645 * StringUtils.indexOf("", *) = -1 2646 * StringUtils.indexOf("aabaabaa", 'a') = 0 2647 * StringUtils.indexOf("aabaabaa", 'b') = 2 2648 * </pre> 2649 * 2650 * @param seq the CharSequence to check, may be null 2651 * @param searchChar the character to find 2652 * @return the first index of the search character, 2653 * -1 if no match or {@code null} string input 2654 * @since 2.0 2655 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2656 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2657 */ 2658 public static int indexOf(final CharSequence seq, final int searchChar) { 2659 if (isEmpty(seq)) { 2660 return INDEX_NOT_FOUND; 2661 } 2662 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2663 } 2664 2665 /** 2666 * Returns the index within {@code seq} of the first occurrence of the 2667 * specified character, starting the search at the specified index. 2668 * <p> 2669 * If a character with value {@code searchChar} occurs in the 2670 * character sequence represented by the {@code seq} {@link CharSequence} 2671 * object at an index no smaller than {@code startPos}, then 2672 * the index of the first such occurrence is returned. For values 2673 * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), 2674 * this is the smallest value <i>k</i> such that: 2675 * <blockquote><pre> 2676 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2677 * </pre></blockquote> 2678 * is true. For other values of {@code searchChar}, it is the 2679 * smallest value <i>k</i> such that: 2680 * <blockquote><pre> 2681 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> >= startPos) 2682 * </pre></blockquote> 2683 * is true. In either case, if no such character occurs in {@code seq} 2684 * at or after position {@code startPos}, then 2685 * {@code -1} is returned. 2686 * 2687 * <p> 2688 * There is no restriction on the value of {@code startPos}. If it 2689 * is negative, it has the same effect as if it were zero: this entire 2690 * string may be searched. If it is greater than the length of this 2691 * string, it has the same effect as if it were equal to the length of 2692 * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a 2693 * {@code null} or empty ("") CharSequence will 2694 * return {@code (INDEX_NOT_FOUND) -1}. 2695 * 2696 * <p>All indices are specified in {@code char} values 2697 * (Unicode code units). 2698 * 2699 * <pre> 2700 * StringUtils.indexOf(null, *, *) = -1 2701 * StringUtils.indexOf("", *, *) = -1 2702 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2703 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2704 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2705 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2706 * </pre> 2707 * 2708 * @param seq the CharSequence to check, may be null 2709 * @param searchChar the character to find 2710 * @param startPos the start position, negative treated as zero 2711 * @return the first index of the search character (always ≥ startPos), 2712 * -1 if no match or {@code null} string input 2713 * @since 2.0 2714 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2715 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2716 */ 2717 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2718 if (isEmpty(seq)) { 2719 return INDEX_NOT_FOUND; 2720 } 2721 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2722 } 2723 2724 /** 2725 * Search a CharSequence to find the first index of any 2726 * character in the given set of characters. 2727 * 2728 * <p>A {@code null} String will return {@code -1}. 2729 * A {@code null} or zero length search array will return {@code -1}.</p> 2730 * 2731 * <pre> 2732 * StringUtils.indexOfAny(null, *) = -1 2733 * StringUtils.indexOfAny("", *) = -1 2734 * StringUtils.indexOfAny(*, null) = -1 2735 * StringUtils.indexOfAny(*, []) = -1 2736 * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0 2737 * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3 2738 * StringUtils.indexOfAny("aba", ['z']) = -1 2739 * </pre> 2740 * 2741 * @param cs the CharSequence to check, may be null 2742 * @param searchChars the chars to search for, may be null 2743 * @return the index of any of the chars, -1 if no match or null input 2744 * @since 2.0 2745 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2746 */ 2747 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2748 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2749 return INDEX_NOT_FOUND; 2750 } 2751 final int csLen = cs.length(); 2752 final int csLast = csLen - 1; 2753 final int searchLen = searchChars.length; 2754 final int searchLast = searchLen - 1; 2755 for (int i = 0; i < csLen; i++) { 2756 final char ch = cs.charAt(i); 2757 for (int j = 0; j < searchLen; j++) { 2758 if (searchChars[j] == ch) { 2759 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) { 2760 return i; 2761 } 2762 // ch is a supplementary character 2763 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2764 return i; 2765 } 2766 } 2767 } 2768 } 2769 return INDEX_NOT_FOUND; 2770 } 2771 2772 /** 2773 * Find the first index of any of a set of potential substrings. 2774 * 2775 * <p>A {@code null} CharSequence will return {@code -1}. 2776 * A {@code null} or zero length search array will return {@code -1}. 2777 * A {@code null} search array entry will be ignored, but a search 2778 * array containing "" will return {@code 0} if {@code str} is not 2779 * null. This method uses {@link String#indexOf(String)} if possible.</p> 2780 * 2781 * <pre> 2782 * StringUtils.indexOfAny(null, *) = -1 2783 * StringUtils.indexOfAny(*, null) = -1 2784 * StringUtils.indexOfAny(*, []) = -1 2785 * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"]) = 2 2786 * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"]) = 2 2787 * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"]) = -1 2788 * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1 2789 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 2790 * StringUtils.indexOfAny("", [""]) = 0 2791 * StringUtils.indexOfAny("", ["a"]) = -1 2792 * </pre> 2793 * 2794 * @param str the CharSequence to check, may be null 2795 * @param searchStrs the CharSequences to search for, may be null 2796 * @return the first index of any of the searchStrs in str, -1 if no match 2797 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2798 */ 2799 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2800 if (str == null || searchStrs == null) { 2801 return INDEX_NOT_FOUND; 2802 } 2803 2804 // String's can't have a MAX_VALUEth index. 2805 int ret = Integer.MAX_VALUE; 2806 2807 int tmp; 2808 for (final CharSequence search : searchStrs) { 2809 if (search == null) { 2810 continue; 2811 } 2812 tmp = CharSequenceUtils.indexOf(str, search, 0); 2813 if (tmp == INDEX_NOT_FOUND) { 2814 continue; 2815 } 2816 2817 if (tmp < ret) { 2818 ret = tmp; 2819 } 2820 } 2821 2822 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2823 } 2824 2825 /** 2826 * Search a CharSequence to find the first index of any 2827 * character in the given set of characters. 2828 * 2829 * <p>A {@code null} String will return {@code -1}. 2830 * A {@code null} search string will return {@code -1}.</p> 2831 * 2832 * <pre> 2833 * StringUtils.indexOfAny(null, *) = -1 2834 * StringUtils.indexOfAny("", *) = -1 2835 * StringUtils.indexOfAny(*, null) = -1 2836 * StringUtils.indexOfAny(*, "") = -1 2837 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2838 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2839 * StringUtils.indexOfAny("aba", "z") = -1 2840 * </pre> 2841 * 2842 * @param cs the CharSequence to check, may be null 2843 * @param searchChars the chars to search for, may be null 2844 * @return the index of any of the chars, -1 if no match or null input 2845 * @since 2.0 2846 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2847 */ 2848 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2849 if (isEmpty(cs) || isEmpty(searchChars)) { 2850 return INDEX_NOT_FOUND; 2851 } 2852 return indexOfAny(cs, searchChars.toCharArray()); 2853 } 2854 2855 /** 2856 * Searches a CharSequence to find the first index of any 2857 * character not in the given set of characters. 2858 * 2859 * <p>A {@code null} CharSequence will return {@code -1}. 2860 * A {@code null} or zero length search array will return {@code -1}.</p> 2861 * 2862 * <pre> 2863 * StringUtils.indexOfAnyBut(null, *) = -1 2864 * StringUtils.indexOfAnyBut("", *) = -1 2865 * StringUtils.indexOfAnyBut(*, null) = -1 2866 * StringUtils.indexOfAnyBut(*, []) = -1 2867 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2868 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2869 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2870 2871 * </pre> 2872 * 2873 * @param cs the CharSequence to check, may be null 2874 * @param searchChars the chars to search for, may be null 2875 * @return the index of any of the chars, -1 if no match or null input 2876 * @since 2.0 2877 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2878 */ 2879 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2880 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2881 return INDEX_NOT_FOUND; 2882 } 2883 final int csLen = cs.length(); 2884 final int csLast = csLen - 1; 2885 final int searchLen = searchChars.length; 2886 final int searchLast = searchLen - 1; 2887 outer: 2888 for (int i = 0; i < csLen; i++) { 2889 final char ch = cs.charAt(i); 2890 for (int j = 0; j < searchLen; j++) { 2891 if (searchChars[j] == ch) { 2892 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) { 2893 continue outer; 2894 } 2895 if (searchChars[j + 1] == cs.charAt(i + 1)) { 2896 continue outer; 2897 } 2898 } 2899 } 2900 return i; 2901 } 2902 return INDEX_NOT_FOUND; 2903 } 2904 2905 /** 2906 * Search a CharSequence to find the first index of any 2907 * character not in the given set of characters. 2908 * 2909 * <p>A {@code null} CharSequence will return {@code -1}. 2910 * A {@code null} or empty search string will return {@code -1}.</p> 2911 * 2912 * <pre> 2913 * StringUtils.indexOfAnyBut(null, *) = -1 2914 * StringUtils.indexOfAnyBut("", *) = -1 2915 * StringUtils.indexOfAnyBut(*, null) = -1 2916 * StringUtils.indexOfAnyBut(*, "") = -1 2917 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2918 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2919 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2920 * </pre> 2921 * 2922 * @param seq the CharSequence to check, may be null 2923 * @param searchChars the chars to search for, may be null 2924 * @return the index of any of the chars, -1 if no match or null input 2925 * @since 2.0 2926 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2927 */ 2928 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2929 if (isEmpty(seq) || isEmpty(searchChars)) { 2930 return INDEX_NOT_FOUND; 2931 } 2932 final int strLen = seq.length(); 2933 for (int i = 0; i < strLen; i++) { 2934 final char ch = seq.charAt(i); 2935 final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0; 2936 if (i + 1 < strLen && Character.isHighSurrogate(ch)) { 2937 final char ch2 = seq.charAt(i + 1); 2938 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) { 2939 return i; 2940 } 2941 } else if (!chFound) { 2942 return i; 2943 } 2944 } 2945 return INDEX_NOT_FOUND; 2946 } 2947 2948 /** 2949 * Compares all CharSequences in an array and returns the index at which the 2950 * CharSequences begin to differ. 2951 * 2952 * <p>For example, 2953 * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p> 2954 * 2955 * <pre> 2956 * StringUtils.indexOfDifference(null) = -1 2957 * StringUtils.indexOfDifference(new String[] {}) = -1 2958 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2959 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2960 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2961 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2962 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2963 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2964 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2965 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2966 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2967 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2968 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2969 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2970 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2971 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2972 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2973 * </pre> 2974 * 2975 * @param css array of CharSequences, entries may be null 2976 * @return the index where the strings begin to differ; -1 if they are all equal 2977 * @since 2.4 2978 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2979 */ 2980 public static int indexOfDifference(final CharSequence... css) { 2981 if (ArrayUtils.getLength(css) <= 1) { 2982 return INDEX_NOT_FOUND; 2983 } 2984 boolean anyStringNull = false; 2985 boolean allStringsNull = true; 2986 final int arrayLen = css.length; 2987 int shortestStrLen = Integer.MAX_VALUE; 2988 int longestStrLen = 0; 2989 2990 // find the min and max string lengths; this avoids checking to make 2991 // sure we are not exceeding the length of the string each time through 2992 // the bottom loop. 2993 for (final CharSequence cs : css) { 2994 if (cs == null) { 2995 anyStringNull = true; 2996 shortestStrLen = 0; 2997 } else { 2998 allStringsNull = false; 2999 shortestStrLen = Math.min(cs.length(), shortestStrLen); 3000 longestStrLen = Math.max(cs.length(), longestStrLen); 3001 } 3002 } 3003 3004 // handle lists containing all nulls or all empty strings 3005 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 3006 return INDEX_NOT_FOUND; 3007 } 3008 3009 // handle lists containing some nulls or some empty strings 3010 if (shortestStrLen == 0) { 3011 return 0; 3012 } 3013 3014 // find the position with the first difference across all strings 3015 int firstDiff = -1; 3016 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 3017 final char comparisonChar = css[0].charAt(stringPos); 3018 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3019 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3020 firstDiff = stringPos; 3021 break; 3022 } 3023 } 3024 if (firstDiff != -1) { 3025 break; 3026 } 3027 } 3028 3029 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3030 // we compared all of the characters up to the length of the 3031 // shortest string and didn't find a match, but the string lengths 3032 // vary, so return the length of the shortest string. 3033 return shortestStrLen; 3034 } 3035 return firstDiff; 3036 } 3037 3038 /** 3039 * Compares two CharSequences, and returns the index at which the 3040 * CharSequences begin to differ. 3041 * 3042 * <p>For example, 3043 * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p> 3044 * 3045 * <pre> 3046 * StringUtils.indexOfDifference(null, null) = -1 3047 * StringUtils.indexOfDifference("", "") = -1 3048 * StringUtils.indexOfDifference("", "abc") = 0 3049 * StringUtils.indexOfDifference("abc", "") = 0 3050 * StringUtils.indexOfDifference("abc", "abc") = -1 3051 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3052 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3053 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3054 * </pre> 3055 * 3056 * @param cs1 the first CharSequence, may be null 3057 * @param cs2 the second CharSequence, may be null 3058 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal 3059 * @since 2.0 3060 * @since 3.0 Changed signature from indexOfDifference(String, String) to 3061 * indexOfDifference(CharSequence, CharSequence) 3062 */ 3063 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3064 if (cs1 == cs2) { 3065 return INDEX_NOT_FOUND; 3066 } 3067 if (cs1 == null || cs2 == null) { 3068 return 0; 3069 } 3070 int i; 3071 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3072 if (cs1.charAt(i) != cs2.charAt(i)) { 3073 break; 3074 } 3075 } 3076 if (i < cs2.length() || i < cs1.length()) { 3077 return i; 3078 } 3079 return INDEX_NOT_FOUND; 3080 } 3081 3082 /** 3083 * Case in-sensitive find of the first index within a CharSequence. 3084 * 3085 * <p>A {@code null} CharSequence will return {@code -1}. 3086 * A negative start position is treated as zero. 3087 * An empty ("") search CharSequence always matches. 3088 * A start position greater than the string length only matches 3089 * an empty search CharSequence.</p> 3090 * 3091 * <pre> 3092 * StringUtils.indexOfIgnoreCase(null, *) = -1 3093 * StringUtils.indexOfIgnoreCase(*, null) = -1 3094 * StringUtils.indexOfIgnoreCase("", "") = 0 3095 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3096 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3097 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3098 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3099 * </pre> 3100 * 3101 * @param str the CharSequence to check, may be null 3102 * @param searchStr the CharSequence to find, may be null 3103 * @return the first index of the search CharSequence, 3104 * -1 if no match or {@code null} string input 3105 * @since 2.5 3106 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3107 */ 3108 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3109 return indexOfIgnoreCase(str, searchStr, 0); 3110 } 3111 3112 /** 3113 * Case in-sensitive find of the first index within a CharSequence 3114 * from the specified position. 3115 * 3116 * <p>A {@code null} CharSequence will return {@code -1}. 3117 * A negative start position is treated as zero. 3118 * An empty ("") search CharSequence always matches. 3119 * A start position greater than the string length only matches 3120 * an empty search CharSequence.</p> 3121 * 3122 * <pre> 3123 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3124 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3125 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3126 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3127 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3128 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3129 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3130 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3131 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3132 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3133 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3134 * </pre> 3135 * 3136 * @param str the CharSequence to check, may be null 3137 * @param searchStr the CharSequence to find, may be null 3138 * @param startPos the start position, negative treated as zero 3139 * @return the first index of the search CharSequence (always ≥ startPos), 3140 * -1 if no match or {@code null} string input 3141 * @since 2.5 3142 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3143 */ 3144 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 3145 if (str == null || searchStr == null) { 3146 return INDEX_NOT_FOUND; 3147 } 3148 if (startPos < 0) { 3149 startPos = 0; 3150 } 3151 final int endLimit = str.length() - searchStr.length() + 1; 3152 if (startPos > endLimit) { 3153 return INDEX_NOT_FOUND; 3154 } 3155 if (searchStr.length() == 0) { 3156 return startPos; 3157 } 3158 for (int i = startPos; i < endLimit; i++) { 3159 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 3160 return i; 3161 } 3162 } 3163 return INDEX_NOT_FOUND; 3164 } 3165 3166 /** 3167 * Checks if all of the CharSequences are empty (""), null or whitespace only. 3168 * 3169 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3170 * 3171 * <pre> 3172 * StringUtils.isAllBlank(null) = true 3173 * StringUtils.isAllBlank(null, "foo") = false 3174 * StringUtils.isAllBlank(null, null) = true 3175 * StringUtils.isAllBlank("", "bar") = false 3176 * StringUtils.isAllBlank("bob", "") = false 3177 * StringUtils.isAllBlank(" bob ", null) = false 3178 * StringUtils.isAllBlank(" ", "bar") = false 3179 * StringUtils.isAllBlank("foo", "bar") = false 3180 * StringUtils.isAllBlank(new String[] {}) = true 3181 * </pre> 3182 * 3183 * @param css the CharSequences to check, may be null or empty 3184 * @return {@code true} if all of the CharSequences are empty or null or whitespace only 3185 * @since 3.6 3186 */ 3187 public static boolean isAllBlank(final CharSequence... css) { 3188 if (ArrayUtils.isEmpty(css)) { 3189 return true; 3190 } 3191 for (final CharSequence cs : css) { 3192 if (isNotBlank(cs)) { 3193 return false; 3194 } 3195 } 3196 return true; 3197 } 3198 3199 /** 3200 * Checks if all of the CharSequences are empty ("") or null. 3201 * 3202 * <pre> 3203 * StringUtils.isAllEmpty(null) = true 3204 * StringUtils.isAllEmpty(null, "") = true 3205 * StringUtils.isAllEmpty(new String[] {}) = true 3206 * StringUtils.isAllEmpty(null, "foo") = false 3207 * StringUtils.isAllEmpty("", "bar") = false 3208 * StringUtils.isAllEmpty("bob", "") = false 3209 * StringUtils.isAllEmpty(" bob ", null) = false 3210 * StringUtils.isAllEmpty(" ", "bar") = false 3211 * StringUtils.isAllEmpty("foo", "bar") = false 3212 * </pre> 3213 * 3214 * @param css the CharSequences to check, may be null or empty 3215 * @return {@code true} if all of the CharSequences are empty or null 3216 * @since 3.6 3217 */ 3218 public static boolean isAllEmpty(final CharSequence... css) { 3219 if (ArrayUtils.isEmpty(css)) { 3220 return true; 3221 } 3222 for (final CharSequence cs : css) { 3223 if (isNotEmpty(cs)) { 3224 return false; 3225 } 3226 } 3227 return true; 3228 } 3229 3230 /** 3231 * Checks if the CharSequence contains only lowercase characters. 3232 * 3233 * <p>{@code null} will return {@code false}. 3234 * An empty CharSequence (length()=0) will return {@code false}.</p> 3235 * 3236 * <pre> 3237 * StringUtils.isAllLowerCase(null) = false 3238 * StringUtils.isAllLowerCase("") = false 3239 * StringUtils.isAllLowerCase(" ") = false 3240 * StringUtils.isAllLowerCase("abc") = true 3241 * StringUtils.isAllLowerCase("abC") = false 3242 * StringUtils.isAllLowerCase("ab c") = false 3243 * StringUtils.isAllLowerCase("ab1c") = false 3244 * StringUtils.isAllLowerCase("ab/c") = false 3245 * </pre> 3246 * 3247 * @param cs the CharSequence to check, may be null 3248 * @return {@code true} if only contains lowercase characters, and is non-null 3249 * @since 2.5 3250 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3251 */ 3252 public static boolean isAllLowerCase(final CharSequence cs) { 3253 if (isEmpty(cs)) { 3254 return false; 3255 } 3256 final int sz = cs.length(); 3257 for (int i = 0; i < sz; i++) { 3258 if (!Character.isLowerCase(cs.charAt(i))) { 3259 return false; 3260 } 3261 } 3262 return true; 3263 } 3264 3265 /** 3266 * Checks if the CharSequence contains only uppercase characters. 3267 * 3268 * <p>{@code null} will return {@code false}. 3269 * An empty String (length()=0) will return {@code false}.</p> 3270 * 3271 * <pre> 3272 * StringUtils.isAllUpperCase(null) = false 3273 * StringUtils.isAllUpperCase("") = false 3274 * StringUtils.isAllUpperCase(" ") = false 3275 * StringUtils.isAllUpperCase("ABC") = true 3276 * StringUtils.isAllUpperCase("aBC") = false 3277 * StringUtils.isAllUpperCase("A C") = false 3278 * StringUtils.isAllUpperCase("A1C") = false 3279 * StringUtils.isAllUpperCase("A/C") = false 3280 * </pre> 3281 * 3282 * @param cs the CharSequence to check, may be null 3283 * @return {@code true} if only contains uppercase characters, and is non-null 3284 * @since 2.5 3285 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3286 */ 3287 public static boolean isAllUpperCase(final CharSequence cs) { 3288 if (isEmpty(cs)) { 3289 return false; 3290 } 3291 final int sz = cs.length(); 3292 for (int i = 0; i < sz; i++) { 3293 if (!Character.isUpperCase(cs.charAt(i))) { 3294 return false; 3295 } 3296 } 3297 return true; 3298 } 3299 3300 /** 3301 * Checks if the CharSequence contains only Unicode letters. 3302 * 3303 * <p>{@code null} will return {@code false}. 3304 * An empty CharSequence (length()=0) will return {@code false}.</p> 3305 * 3306 * <pre> 3307 * StringUtils.isAlpha(null) = false 3308 * StringUtils.isAlpha("") = false 3309 * StringUtils.isAlpha(" ") = false 3310 * StringUtils.isAlpha("abc") = true 3311 * StringUtils.isAlpha("ab2c") = false 3312 * StringUtils.isAlpha("ab-c") = false 3313 * </pre> 3314 * 3315 * @param cs the CharSequence to check, may be null 3316 * @return {@code true} if only contains letters, and is non-null 3317 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3318 * @since 3.0 Changed "" to return false and not true 3319 */ 3320 public static boolean isAlpha(final CharSequence cs) { 3321 if (isEmpty(cs)) { 3322 return false; 3323 } 3324 final int sz = cs.length(); 3325 for (int i = 0; i < sz; i++) { 3326 if (!Character.isLetter(cs.charAt(i))) { 3327 return false; 3328 } 3329 } 3330 return true; 3331 } 3332 3333 /** 3334 * Checks if the CharSequence contains only Unicode letters or digits. 3335 * 3336 * <p>{@code null} will return {@code false}. 3337 * An empty CharSequence (length()=0) will return {@code false}.</p> 3338 * 3339 * <pre> 3340 * StringUtils.isAlphanumeric(null) = false 3341 * StringUtils.isAlphanumeric("") = false 3342 * StringUtils.isAlphanumeric(" ") = false 3343 * StringUtils.isAlphanumeric("abc") = true 3344 * StringUtils.isAlphanumeric("ab c") = false 3345 * StringUtils.isAlphanumeric("ab2c") = true 3346 * StringUtils.isAlphanumeric("ab-c") = false 3347 * </pre> 3348 * 3349 * @param cs the CharSequence to check, may be null 3350 * @return {@code true} if only contains letters or digits, 3351 * and is non-null 3352 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3353 * @since 3.0 Changed "" to return false and not true 3354 */ 3355 public static boolean isAlphanumeric(final CharSequence cs) { 3356 if (isEmpty(cs)) { 3357 return false; 3358 } 3359 final int sz = cs.length(); 3360 for (int i = 0; i < sz; i++) { 3361 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3362 return false; 3363 } 3364 } 3365 return true; 3366 } 3367 3368 /** 3369 * Checks if the CharSequence contains only Unicode letters, digits 3370 * or space ({@code ' '}). 3371 * 3372 * <p>{@code null} will return {@code false}. 3373 * An empty CharSequence (length()=0) will return {@code true}.</p> 3374 * 3375 * <pre> 3376 * StringUtils.isAlphanumericSpace(null) = false 3377 * StringUtils.isAlphanumericSpace("") = true 3378 * StringUtils.isAlphanumericSpace(" ") = true 3379 * StringUtils.isAlphanumericSpace("abc") = true 3380 * StringUtils.isAlphanumericSpace("ab c") = true 3381 * StringUtils.isAlphanumericSpace("ab2c") = true 3382 * StringUtils.isAlphanumericSpace("ab-c") = false 3383 * </pre> 3384 * 3385 * @param cs the CharSequence to check, may be null 3386 * @return {@code true} if only contains letters, digits or space, 3387 * and is non-null 3388 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3389 */ 3390 public static boolean isAlphanumericSpace(final CharSequence cs) { 3391 if (cs == null) { 3392 return false; 3393 } 3394 final int sz = cs.length(); 3395 for (int i = 0; i < sz; i++) { 3396 final char nowChar = cs.charAt(i); 3397 if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar) ) { 3398 return false; 3399 } 3400 } 3401 return true; 3402 } 3403 3404 /** 3405 * Checks if the CharSequence contains only Unicode letters and 3406 * space (' '). 3407 * 3408 * <p>{@code null} will return {@code false} 3409 * An empty CharSequence (length()=0) will return {@code true}.</p> 3410 * 3411 * <pre> 3412 * StringUtils.isAlphaSpace(null) = false 3413 * StringUtils.isAlphaSpace("") = true 3414 * StringUtils.isAlphaSpace(" ") = true 3415 * StringUtils.isAlphaSpace("abc") = true 3416 * StringUtils.isAlphaSpace("ab c") = true 3417 * StringUtils.isAlphaSpace("ab2c") = false 3418 * StringUtils.isAlphaSpace("ab-c") = false 3419 * </pre> 3420 * 3421 * @param cs the CharSequence to check, may be null 3422 * @return {@code true} if only contains letters and space, 3423 * and is non-null 3424 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3425 */ 3426 public static boolean isAlphaSpace(final CharSequence cs) { 3427 if (cs == null) { 3428 return false; 3429 } 3430 final int sz = cs.length(); 3431 for (int i = 0; i < sz; i++) { 3432 final char nowChar = cs.charAt(i); 3433 if (nowChar != ' ' && !Character.isLetter(nowChar)) { 3434 return false; 3435 } 3436 } 3437 return true; 3438 } 3439 3440 /** 3441 * Checks if any of the CharSequences are empty ("") or null or whitespace only. 3442 * 3443 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3444 * 3445 * <pre> 3446 * StringUtils.isAnyBlank((String) null) = true 3447 * StringUtils.isAnyBlank((String[]) null) = false 3448 * StringUtils.isAnyBlank(null, "foo") = true 3449 * StringUtils.isAnyBlank(null, null) = true 3450 * StringUtils.isAnyBlank("", "bar") = true 3451 * StringUtils.isAnyBlank("bob", "") = true 3452 * StringUtils.isAnyBlank(" bob ", null) = true 3453 * StringUtils.isAnyBlank(" ", "bar") = true 3454 * StringUtils.isAnyBlank(new String[] {}) = false 3455 * StringUtils.isAnyBlank(new String[]{""}) = true 3456 * StringUtils.isAnyBlank("foo", "bar") = false 3457 * </pre> 3458 * 3459 * @param css the CharSequences to check, may be null or empty 3460 * @return {@code true} if any of the CharSequences are empty or null or whitespace only 3461 * @since 3.2 3462 */ 3463 public static boolean isAnyBlank(final CharSequence... css) { 3464 if (ArrayUtils.isEmpty(css)) { 3465 return false; 3466 } 3467 for (final CharSequence cs : css) { 3468 if (isBlank(cs)) { 3469 return true; 3470 } 3471 } 3472 return false; 3473 } 3474 3475 /** 3476 * Checks if any of the CharSequences are empty ("") or null. 3477 * 3478 * <pre> 3479 * StringUtils.isAnyEmpty((String) null) = true 3480 * StringUtils.isAnyEmpty((String[]) null) = false 3481 * StringUtils.isAnyEmpty(null, "foo") = true 3482 * StringUtils.isAnyEmpty("", "bar") = true 3483 * StringUtils.isAnyEmpty("bob", "") = true 3484 * StringUtils.isAnyEmpty(" bob ", null) = true 3485 * StringUtils.isAnyEmpty(" ", "bar") = false 3486 * StringUtils.isAnyEmpty("foo", "bar") = false 3487 * StringUtils.isAnyEmpty(new String[]{}) = false 3488 * StringUtils.isAnyEmpty(new String[]{""}) = true 3489 * </pre> 3490 * 3491 * @param css the CharSequences to check, may be null or empty 3492 * @return {@code true} if any of the CharSequences are empty or null 3493 * @since 3.2 3494 */ 3495 public static boolean isAnyEmpty(final CharSequence... css) { 3496 if (ArrayUtils.isEmpty(css)) { 3497 return false; 3498 } 3499 for (final CharSequence cs : css) { 3500 if (isEmpty(cs)) { 3501 return true; 3502 } 3503 } 3504 return false; 3505 } 3506 3507 /** 3508 * Checks if the CharSequence contains only ASCII printable characters. 3509 * 3510 * <p>{@code null} will return {@code false}. 3511 * An empty CharSequence (length()=0) will return {@code true}.</p> 3512 * 3513 * <pre> 3514 * StringUtils.isAsciiPrintable(null) = false 3515 * StringUtils.isAsciiPrintable("") = true 3516 * StringUtils.isAsciiPrintable(" ") = true 3517 * StringUtils.isAsciiPrintable("Ceki") = true 3518 * StringUtils.isAsciiPrintable("ab2c") = true 3519 * StringUtils.isAsciiPrintable("!ab-c~") = true 3520 * StringUtils.isAsciiPrintable("\u0020") = true 3521 * StringUtils.isAsciiPrintable("\u0021") = true 3522 * StringUtils.isAsciiPrintable("\u007e") = true 3523 * StringUtils.isAsciiPrintable("\u007f") = false 3524 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3525 * </pre> 3526 * 3527 * @param cs the CharSequence to check, may be null 3528 * @return {@code true} if every character is in the range 3529 * 32 through 126 3530 * @since 2.1 3531 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3532 */ 3533 public static boolean isAsciiPrintable(final CharSequence cs) { 3534 if (cs == null) { 3535 return false; 3536 } 3537 final int sz = cs.length(); 3538 for (int i = 0; i < sz; i++) { 3539 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3540 return false; 3541 } 3542 } 3543 return true; 3544 } 3545 3546 /** 3547 * Checks if a CharSequence is empty (""), null or whitespace only. 3548 * 3549 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3550 * 3551 * <pre> 3552 * StringUtils.isBlank(null) = true 3553 * StringUtils.isBlank("") = true 3554 * StringUtils.isBlank(" ") = true 3555 * StringUtils.isBlank("bob") = false 3556 * StringUtils.isBlank(" bob ") = false 3557 * </pre> 3558 * 3559 * @param cs the CharSequence to check, may be null 3560 * @return {@code true} if the CharSequence is null, empty or whitespace only 3561 * @since 2.0 3562 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3563 */ 3564 public static boolean isBlank(final CharSequence cs) { 3565 final int strLen = length(cs); 3566 if (strLen == 0) { 3567 return true; 3568 } 3569 for (int i = 0; i < strLen; i++) { 3570 if (!Character.isWhitespace(cs.charAt(i))) { 3571 return false; 3572 } 3573 } 3574 return true; 3575 } 3576 3577 /** 3578 * Checks if a CharSequence is empty ("") or null. 3579 * 3580 * <pre> 3581 * StringUtils.isEmpty(null) = true 3582 * StringUtils.isEmpty("") = true 3583 * StringUtils.isEmpty(" ") = false 3584 * StringUtils.isEmpty("bob") = false 3585 * StringUtils.isEmpty(" bob ") = false 3586 * </pre> 3587 * 3588 * <p>NOTE: This method changed in Lang version 2.0. 3589 * It no longer trims the CharSequence. 3590 * That functionality is available in isBlank().</p> 3591 * 3592 * @param cs the CharSequence to check, may be null 3593 * @return {@code true} if the CharSequence is empty or null 3594 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3595 */ 3596 public static boolean isEmpty(final CharSequence cs) { 3597 return cs == null || cs.length() == 0; 3598 } 3599 3600 /** 3601 * Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3602 * 3603 * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return 3604 * {@code false}.</p> 3605 * 3606 * <pre> 3607 * StringUtils.isMixedCase(null) = false 3608 * StringUtils.isMixedCase("") = false 3609 * StringUtils.isMixedCase(" ") = false 3610 * StringUtils.isMixedCase("ABC") = false 3611 * StringUtils.isMixedCase("abc") = false 3612 * StringUtils.isMixedCase("aBc") = true 3613 * StringUtils.isMixedCase("A c") = true 3614 * StringUtils.isMixedCase("A1c") = true 3615 * StringUtils.isMixedCase("a/C") = true 3616 * StringUtils.isMixedCase("aC\t") = true 3617 * </pre> 3618 * 3619 * @param cs the CharSequence to check, may be null 3620 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters 3621 * @since 3.5 3622 */ 3623 public static boolean isMixedCase(final CharSequence cs) { 3624 if (isEmpty(cs) || cs.length() == 1) { 3625 return false; 3626 } 3627 boolean containsUppercase = false; 3628 boolean containsLowercase = false; 3629 final int sz = cs.length(); 3630 for (int i = 0; i < sz; i++) { 3631 if (containsUppercase && containsLowercase) { 3632 return true; 3633 } 3634 if (Character.isUpperCase(cs.charAt(i))) { 3635 containsUppercase = true; 3636 } else if (Character.isLowerCase(cs.charAt(i))) { 3637 containsLowercase = true; 3638 } 3639 } 3640 return containsUppercase && containsLowercase; 3641 } 3642 3643 /** 3644 * Checks if none of the CharSequences are empty (""), null or whitespace only. 3645 * 3646 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3647 * 3648 * <pre> 3649 * StringUtils.isNoneBlank((String) null) = false 3650 * StringUtils.isNoneBlank((String[]) null) = true 3651 * StringUtils.isNoneBlank(null, "foo") = false 3652 * StringUtils.isNoneBlank(null, null) = false 3653 * StringUtils.isNoneBlank("", "bar") = false 3654 * StringUtils.isNoneBlank("bob", "") = false 3655 * StringUtils.isNoneBlank(" bob ", null) = false 3656 * StringUtils.isNoneBlank(" ", "bar") = false 3657 * StringUtils.isNoneBlank(new String[] {}) = true 3658 * StringUtils.isNoneBlank(new String[]{""}) = false 3659 * StringUtils.isNoneBlank("foo", "bar") = true 3660 * </pre> 3661 * 3662 * @param css the CharSequences to check, may be null or empty 3663 * @return {@code true} if none of the CharSequences are empty or null or whitespace only 3664 * @since 3.2 3665 */ 3666 public static boolean isNoneBlank(final CharSequence... css) { 3667 return !isAnyBlank(css); 3668 } 3669 3670 /** 3671 * Checks if none of the CharSequences are empty ("") or null. 3672 * 3673 * <pre> 3674 * StringUtils.isNoneEmpty((String) null) = false 3675 * StringUtils.isNoneEmpty((String[]) null) = true 3676 * StringUtils.isNoneEmpty(null, "foo") = false 3677 * StringUtils.isNoneEmpty("", "bar") = false 3678 * StringUtils.isNoneEmpty("bob", "") = false 3679 * StringUtils.isNoneEmpty(" bob ", null) = false 3680 * StringUtils.isNoneEmpty(new String[] {}) = true 3681 * StringUtils.isNoneEmpty(new String[]{""}) = false 3682 * StringUtils.isNoneEmpty(" ", "bar") = true 3683 * StringUtils.isNoneEmpty("foo", "bar") = true 3684 * </pre> 3685 * 3686 * @param css the CharSequences to check, may be null or empty 3687 * @return {@code true} if none of the CharSequences are empty or null 3688 * @since 3.2 3689 */ 3690 public static boolean isNoneEmpty(final CharSequence... css) { 3691 return !isAnyEmpty(css); 3692 } 3693 3694 /** 3695 * Checks if a CharSequence is not empty (""), not null and not whitespace only. 3696 * 3697 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3698 * 3699 * <pre> 3700 * StringUtils.isNotBlank(null) = false 3701 * StringUtils.isNotBlank("") = false 3702 * StringUtils.isNotBlank(" ") = false 3703 * StringUtils.isNotBlank("bob") = true 3704 * StringUtils.isNotBlank(" bob ") = true 3705 * </pre> 3706 * 3707 * @param cs the CharSequence to check, may be null 3708 * @return {@code true} if the CharSequence is 3709 * not empty and not null and not whitespace only 3710 * @since 2.0 3711 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3712 */ 3713 public static boolean isNotBlank(final CharSequence cs) { 3714 return !isBlank(cs); 3715 } 3716 3717 /** 3718 * Checks if a CharSequence is not empty ("") and not null. 3719 * 3720 * <pre> 3721 * StringUtils.isNotEmpty(null) = false 3722 * StringUtils.isNotEmpty("") = false 3723 * StringUtils.isNotEmpty(" ") = true 3724 * StringUtils.isNotEmpty("bob") = true 3725 * StringUtils.isNotEmpty(" bob ") = true 3726 * </pre> 3727 * 3728 * @param cs the CharSequence to check, may be null 3729 * @return {@code true} if the CharSequence is not empty and not null 3730 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3731 */ 3732 public static boolean isNotEmpty(final CharSequence cs) { 3733 return !isEmpty(cs); 3734 } 3735 3736 /** 3737 * Checks if the CharSequence contains only Unicode digits. 3738 * A decimal point is not a Unicode digit and returns false. 3739 * 3740 * <p>{@code null} will return {@code false}. 3741 * An empty CharSequence (length()=0) will return {@code false}.</p> 3742 * 3743 * <p>Note that the method does not allow for a leading sign, either positive or negative. 3744 * Also, if a String passes the numeric test, it may still generate a NumberFormatException 3745 * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range 3746 * for int or long respectively.</p> 3747 * 3748 * <pre> 3749 * StringUtils.isNumeric(null) = false 3750 * StringUtils.isNumeric("") = false 3751 * StringUtils.isNumeric(" ") = false 3752 * StringUtils.isNumeric("123") = true 3753 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3754 * StringUtils.isNumeric("12 3") = false 3755 * StringUtils.isNumeric("ab2c") = false 3756 * StringUtils.isNumeric("12-3") = false 3757 * StringUtils.isNumeric("12.3") = false 3758 * StringUtils.isNumeric("-123") = false 3759 * StringUtils.isNumeric("+123") = false 3760 * </pre> 3761 * 3762 * @param cs the CharSequence to check, may be null 3763 * @return {@code true} if only contains digits, and is non-null 3764 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3765 * @since 3.0 Changed "" to return false and not true 3766 */ 3767 public static boolean isNumeric(final CharSequence cs) { 3768 if (isEmpty(cs)) { 3769 return false; 3770 } 3771 final int sz = cs.length(); 3772 for (int i = 0; i < sz; i++) { 3773 if (!Character.isDigit(cs.charAt(i))) { 3774 return false; 3775 } 3776 } 3777 return true; 3778 } 3779 3780 /** 3781 * Checks if the CharSequence contains only Unicode digits or space 3782 * ({@code ' '}). 3783 * A decimal point is not a Unicode digit and returns false. 3784 * 3785 * <p>{@code null} will return {@code false}. 3786 * An empty CharSequence (length()=0) will return {@code true}.</p> 3787 * 3788 * <pre> 3789 * StringUtils.isNumericSpace(null) = false 3790 * StringUtils.isNumericSpace("") = true 3791 * StringUtils.isNumericSpace(" ") = true 3792 * StringUtils.isNumericSpace("123") = true 3793 * StringUtils.isNumericSpace("12 3") = true 3794 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3795 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3796 * StringUtils.isNumericSpace("ab2c") = false 3797 * StringUtils.isNumericSpace("12-3") = false 3798 * StringUtils.isNumericSpace("12.3") = false 3799 * </pre> 3800 * 3801 * @param cs the CharSequence to check, may be null 3802 * @return {@code true} if only contains digits or space, 3803 * and is non-null 3804 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3805 */ 3806 public static boolean isNumericSpace(final CharSequence cs) { 3807 if (cs == null) { 3808 return false; 3809 } 3810 final int sz = cs.length(); 3811 for (int i = 0; i < sz; i++) { 3812 final char nowChar = cs.charAt(i); 3813 if (nowChar != ' ' && !Character.isDigit(nowChar)) { 3814 return false; 3815 } 3816 } 3817 return true; 3818 } 3819 3820 /** 3821 * Checks if the CharSequence contains only whitespace. 3822 * 3823 * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 3824 * 3825 * <p>{@code null} will return {@code false}. 3826 * An empty CharSequence (length()=0) will return {@code true}.</p> 3827 * 3828 * <pre> 3829 * StringUtils.isWhitespace(null) = false 3830 * StringUtils.isWhitespace("") = true 3831 * StringUtils.isWhitespace(" ") = true 3832 * StringUtils.isWhitespace("abc") = false 3833 * StringUtils.isWhitespace("ab2c") = false 3834 * StringUtils.isWhitespace("ab-c") = false 3835 * </pre> 3836 * 3837 * @param cs the CharSequence to check, may be null 3838 * @return {@code true} if only contains whitespace, and is non-null 3839 * @since 2.0 3840 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3841 */ 3842 public static boolean isWhitespace(final CharSequence cs) { 3843 if (cs == null) { 3844 return false; 3845 } 3846 final int sz = cs.length(); 3847 for (int i = 0; i < sz; i++) { 3848 if (!Character.isWhitespace(cs.charAt(i))) { 3849 return false; 3850 } 3851 } 3852 return true; 3853 } 3854 3855 /** 3856 * Joins the elements of the provided array into a single String containing the provided list of elements. 3857 * 3858 * <p> 3859 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3860 * by empty strings. 3861 * </p> 3862 * 3863 * <pre> 3864 * StringUtils.join(null, *) = null 3865 * StringUtils.join([], *) = "" 3866 * StringUtils.join([null], *) = "" 3867 * StringUtils.join([false, false], ';') = "false;false" 3868 * </pre> 3869 * 3870 * @param array 3871 * the array of values to join together, may be null 3872 * @param delimiter 3873 * the separator character to use 3874 * @return the joined String, {@code null} if null array input 3875 * @since 3.12.0 3876 */ 3877 public static String join(final boolean[] array, final char delimiter) { 3878 if (array == null) { 3879 return null; 3880 } 3881 return join(array, delimiter, 0, array.length); 3882 } 3883 3884 /** 3885 * Joins the elements of the provided array into a single String containing the provided list of elements. 3886 * 3887 * <p> 3888 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3889 * by empty strings. 3890 * </p> 3891 * 3892 * <pre> 3893 * StringUtils.join(null, *) = null 3894 * StringUtils.join([], *) = "" 3895 * StringUtils.join([null], *) = "" 3896 * StringUtils.join([true, false, true], ';') = "true;false;true" 3897 * </pre> 3898 * 3899 * @param array 3900 * the array of values to join together, may be null 3901 * @param delimiter 3902 * the separator character to use 3903 * @param startIndex 3904 * the first index to start joining from. It is an error to pass in a start index past the end of the 3905 * array 3906 * @param endIndex 3907 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3908 * the array 3909 * @return the joined String, {@code null} if null array input 3910 * @since 3.12.0 3911 */ 3912 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3913 if (array == null) { 3914 return null; 3915 } 3916 if (endIndex - startIndex <= 0) { 3917 return EMPTY; 3918 } 3919 final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1); 3920 for (int i = startIndex; i < endIndex; i++) { 3921 stringBuilder 3922 .append(array[i]) 3923 .append(delimiter); 3924 } 3925 return stringBuilder.substring(0, stringBuilder.length() - 1); 3926 } 3927 3928 /** 3929 * Joins the elements of the provided array into a single String containing the provided list of elements. 3930 * 3931 * <p> 3932 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3933 * by empty strings. 3934 * </p> 3935 * 3936 * <pre> 3937 * StringUtils.join(null, *) = null 3938 * StringUtils.join([], *) = "" 3939 * StringUtils.join([null], *) = "" 3940 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3941 * StringUtils.join([1, 2, 3], null) = "123" 3942 * </pre> 3943 * 3944 * @param array 3945 * the array of values to join together, may be null 3946 * @param delimiter 3947 * the separator character to use 3948 * @return the joined String, {@code null} if null array input 3949 * @since 3.2 3950 */ 3951 public static String join(final byte[] array, final char delimiter) { 3952 if (array == null) { 3953 return null; 3954 } 3955 return join(array, delimiter, 0, array.length); 3956 } 3957 3958 /** 3959 * Joins the elements of the provided array into a single String containing the provided list of elements. 3960 * 3961 * <p> 3962 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3963 * by empty strings. 3964 * </p> 3965 * 3966 * <pre> 3967 * StringUtils.join(null, *) = null 3968 * StringUtils.join([], *) = "" 3969 * StringUtils.join([null], *) = "" 3970 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3971 * StringUtils.join([1, 2, 3], null) = "123" 3972 * </pre> 3973 * 3974 * @param array 3975 * the array of values to join together, may be null 3976 * @param delimiter 3977 * the separator character to use 3978 * @param startIndex 3979 * the first index to start joining from. It is an error to pass in a start index past the end of the 3980 * array 3981 * @param endIndex 3982 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3983 * the array 3984 * @return the joined String, {@code null} if null array input 3985 * @since 3.2 3986 */ 3987 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 3988 if (array == null) { 3989 return null; 3990 } 3991 if (endIndex - startIndex <= 0) { 3992 return EMPTY; 3993 } 3994 final StringBuilder stringBuilder = new StringBuilder(); 3995 for (int i = startIndex; i < endIndex; i++) { 3996 stringBuilder 3997 .append(array[i]) 3998 .append(delimiter); 3999 } 4000 return stringBuilder.substring(0, stringBuilder.length() - 1); 4001 } 4002 4003 /** 4004 * Joins the elements of the provided array into a single String containing the provided list of elements. 4005 * 4006 * <p> 4007 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4008 * by empty strings. 4009 * </p> 4010 * 4011 * <pre> 4012 * StringUtils.join(null, *) = null 4013 * StringUtils.join([], *) = "" 4014 * StringUtils.join([null], *) = "" 4015 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4016 * StringUtils.join([1, 2, 3], null) = "123" 4017 * </pre> 4018 * 4019 * @param array 4020 * the array of values to join together, may be null 4021 * @param delimiter 4022 * the separator character to use 4023 * @return the joined String, {@code null} if null array input 4024 * @since 3.2 4025 */ 4026 public static String join(final char[] array, final char delimiter) { 4027 if (array == null) { 4028 return null; 4029 } 4030 return join(array, delimiter, 0, array.length); 4031 } 4032 4033 /** 4034 * Joins the elements of the provided array into a single String containing the provided list of elements. 4035 * 4036 * <p> 4037 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4038 * by empty strings. 4039 * </p> 4040 * 4041 * <pre> 4042 * StringUtils.join(null, *) = null 4043 * StringUtils.join([], *) = "" 4044 * StringUtils.join([null], *) = "" 4045 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4046 * StringUtils.join([1, 2, 3], null) = "123" 4047 * </pre> 4048 * 4049 * @param array 4050 * the array of values to join together, may be null 4051 * @param delimiter 4052 * the separator character to use 4053 * @param startIndex 4054 * the first index to start joining from. It is an error to pass in a start index past the end of the 4055 * array 4056 * @param endIndex 4057 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4058 * the array 4059 * @return the joined String, {@code null} if null array input 4060 * @since 3.2 4061 */ 4062 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4063 if (array == null) { 4064 return null; 4065 } 4066 if (endIndex - startIndex <= 0) { 4067 return EMPTY; 4068 } 4069 final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1); 4070 for (int i = startIndex; i < endIndex; i++) { 4071 stringBuilder 4072 .append(array[i]) 4073 .append(delimiter); 4074 } 4075 return stringBuilder.substring(0, stringBuilder.length() - 1); 4076 } 4077 4078 /** 4079 * Joins the elements of the provided array into a single String containing the provided list of elements. 4080 * 4081 * <p> 4082 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4083 * by empty strings. 4084 * </p> 4085 * 4086 * <pre> 4087 * StringUtils.join(null, *) = null 4088 * StringUtils.join([], *) = "" 4089 * StringUtils.join([null], *) = "" 4090 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4091 * StringUtils.join([1, 2, 3], null) = "123" 4092 * </pre> 4093 * 4094 * @param array 4095 * the array of values to join together, may be null 4096 * @param delimiter 4097 * the separator character to use 4098 * @return the joined String, {@code null} if null array input 4099 * @since 3.2 4100 */ 4101 public static String join(final double[] array, final char delimiter) { 4102 if (array == null) { 4103 return null; 4104 } 4105 return join(array, delimiter, 0, array.length); 4106 } 4107 4108 /** 4109 * Joins the elements of the provided array into a single String containing the provided list of elements. 4110 * 4111 * <p> 4112 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4113 * by empty strings. 4114 * </p> 4115 * 4116 * <pre> 4117 * StringUtils.join(null, *) = null 4118 * StringUtils.join([], *) = "" 4119 * StringUtils.join([null], *) = "" 4120 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4121 * StringUtils.join([1, 2, 3], null) = "123" 4122 * </pre> 4123 * 4124 * @param array 4125 * the array of values to join together, may be null 4126 * @param delimiter 4127 * the separator character to use 4128 * @param startIndex 4129 * the first index to start joining from. It is an error to pass in a start index past the end of the 4130 * array 4131 * @param endIndex 4132 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4133 * the array 4134 * @return the joined String, {@code null} if null array input 4135 * @since 3.2 4136 */ 4137 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4138 if (array == null) { 4139 return null; 4140 } 4141 if (endIndex - startIndex <= 0) { 4142 return EMPTY; 4143 } 4144 final StringBuilder stringBuilder = new StringBuilder(); 4145 for (int i = startIndex; i < endIndex; i++) { 4146 stringBuilder 4147 .append(array[i]) 4148 .append(delimiter); 4149 } 4150 return stringBuilder.substring(0, stringBuilder.length() - 1); 4151 } 4152 4153 /** 4154 * Joins the elements of the provided array into a single String containing the provided list of elements. 4155 * 4156 * <p> 4157 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4158 * by empty strings. 4159 * </p> 4160 * 4161 * <pre> 4162 * StringUtils.join(null, *) = null 4163 * StringUtils.join([], *) = "" 4164 * StringUtils.join([null], *) = "" 4165 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4166 * StringUtils.join([1, 2, 3], null) = "123" 4167 * </pre> 4168 * 4169 * @param array 4170 * the array of values to join together, may be null 4171 * @param delimiter 4172 * the separator character to use 4173 * @return the joined String, {@code null} if null array input 4174 * @since 3.2 4175 */ 4176 public static String join(final float[] array, final char delimiter) { 4177 if (array == null) { 4178 return null; 4179 } 4180 return join(array, delimiter, 0, array.length); 4181 } 4182 4183 /** 4184 * Joins the elements of the provided array into a single String containing the provided list of elements. 4185 * 4186 * <p> 4187 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4188 * by empty strings. 4189 * </p> 4190 * 4191 * <pre> 4192 * StringUtils.join(null, *) = null 4193 * StringUtils.join([], *) = "" 4194 * StringUtils.join([null], *) = "" 4195 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4196 * StringUtils.join([1, 2, 3], null) = "123" 4197 * </pre> 4198 * 4199 * @param array 4200 * the array of values to join together, may be null 4201 * @param delimiter 4202 * the separator character to use 4203 * @param startIndex 4204 * the first index to start joining from. It is an error to pass in a start index past the end of the 4205 * array 4206 * @param endIndex 4207 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4208 * the array 4209 * @return the joined String, {@code null} if null array input 4210 * @since 3.2 4211 */ 4212 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4213 if (array == null) { 4214 return null; 4215 } 4216 if (endIndex - startIndex <= 0) { 4217 return EMPTY; 4218 } 4219 final StringBuilder stringBuilder = new StringBuilder(); 4220 for (int i = startIndex; i < endIndex; i++) { 4221 stringBuilder 4222 .append(array[i]) 4223 .append(delimiter); 4224 } 4225 return stringBuilder.substring(0, stringBuilder.length() - 1); 4226 } 4227 4228 /** 4229 * Joins the elements of the provided array into a single String containing the provided list of elements. 4230 * 4231 * <p> 4232 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4233 * by empty strings. 4234 * </p> 4235 * 4236 * <pre> 4237 * StringUtils.join(null, *) = null 4238 * StringUtils.join([], *) = "" 4239 * StringUtils.join([null], *) = "" 4240 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4241 * StringUtils.join([1, 2, 3], null) = "123" 4242 * </pre> 4243 * 4244 * @param array 4245 * the array of values to join together, may be null 4246 * @param separator 4247 * the separator character to use 4248 * @return the joined String, {@code null} if null array input 4249 * @since 3.2 4250 */ 4251 public static String join(final int[] array, final char separator) { 4252 if (array == null) { 4253 return null; 4254 } 4255 return join(array, separator, 0, array.length); 4256 } 4257 4258 /** 4259 * Joins the elements of the provided array into a single String containing the provided list of elements. 4260 * 4261 * <p> 4262 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4263 * by empty strings. 4264 * </p> 4265 * 4266 * <pre> 4267 * StringUtils.join(null, *) = null 4268 * StringUtils.join([], *) = "" 4269 * StringUtils.join([null], *) = "" 4270 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4271 * StringUtils.join([1, 2, 3], null) = "123" 4272 * </pre> 4273 * 4274 * @param array 4275 * the array of values to join together, may be null 4276 * @param delimiter 4277 * the separator character to use 4278 * @param startIndex 4279 * the first index to start joining from. It is an error to pass in a start index past the end of the 4280 * array 4281 * @param endIndex 4282 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4283 * the array 4284 * @return the joined String, {@code null} if null array input 4285 * @since 3.2 4286 */ 4287 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4288 if (array == null) { 4289 return null; 4290 } 4291 if (endIndex - startIndex <= 0) { 4292 return EMPTY; 4293 } 4294 final StringBuilder stringBuilder = new StringBuilder(); 4295 for (int i = startIndex; i < endIndex; i++) { 4296 stringBuilder 4297 .append(array[i]) 4298 .append(delimiter); 4299 } 4300 return stringBuilder.substring(0, stringBuilder.length() - 1); 4301 } 4302 4303 /** 4304 * Joins the elements of the provided {@link Iterable} into 4305 * a single String containing the provided elements. 4306 * 4307 * <p>No delimiter is added before or after the list. Null objects or empty 4308 * strings within the iteration are represented by empty strings.</p> 4309 * 4310 * <p>See the examples here: {@link #join(Object[],char)}.</p> 4311 * 4312 * @param iterable the {@link Iterable} providing the values to join together, may be null 4313 * @param separator the separator character to use 4314 * @return the joined String, {@code null} if null iterator input 4315 * @since 2.3 4316 */ 4317 public static String join(final Iterable<?> iterable, final char separator) { 4318 return iterable != null ? join(iterable.iterator(), separator) : null; 4319 } 4320 4321 /** 4322 * Joins the elements of the provided {@link Iterable} into 4323 * a single String containing the provided elements. 4324 * 4325 * <p>No delimiter is added before or after the list. 4326 * A {@code null} separator is the same as an empty String ("").</p> 4327 * 4328 * <p>See the examples here: {@link #join(Object[],String)}.</p> 4329 * 4330 * @param iterable the {@link Iterable} providing the values to join together, may be null 4331 * @param separator the separator character to use, null treated as "" 4332 * @return the joined String, {@code null} if null iterator input 4333 * @since 2.3 4334 */ 4335 public static String join(final Iterable<?> iterable, final String separator) { 4336 return iterable != null ? join(iterable.iterator(), separator) : null; 4337 } 4338 4339 /** 4340 * Joins the elements of the provided {@link Iterator} into 4341 * a single String containing the provided elements. 4342 * 4343 * <p>No delimiter is added before or after the list. Null objects or empty 4344 * strings within the iteration are represented by empty strings.</p> 4345 * 4346 * <p>See the examples here: {@link #join(Object[],char)}.</p> 4347 * 4348 * @param iterator the {@link Iterator} of values to join together, may be null 4349 * @param separator the separator character to use 4350 * @return the joined String, {@code null} if null iterator input 4351 * @since 2.0 4352 */ 4353 public static String join(final Iterator<?> iterator, final char separator) { 4354 // handle null, zero and one elements before building a buffer 4355 if (iterator == null) { 4356 return null; 4357 } 4358 if (!iterator.hasNext()) { 4359 return EMPTY; 4360 } 4361 return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(String.valueOf(separator)), EMPTY, EMPTY, StringUtils::toStringOrEmpty)); 4362 } 4363 4364 /** 4365 * Joins the elements of the provided {@link Iterator} into 4366 * a single String containing the provided elements. 4367 * 4368 * <p>No delimiter is added before or after the list. 4369 * A {@code null} separator is the same as an empty String ("").</p> 4370 * 4371 * <p>See the examples here: {@link #join(Object[],String)}.</p> 4372 * 4373 * @param iterator the {@link Iterator} of values to join together, may be null 4374 * @param separator the separator character to use, null treated as "" 4375 * @return the joined String, {@code null} if null iterator input 4376 */ 4377 public static String join(final Iterator<?> iterator, final String separator) { 4378 // handle null, zero and one elements before building a buffer 4379 if (iterator == null) { 4380 return null; 4381 } 4382 if (!iterator.hasNext()) { 4383 return EMPTY; 4384 } 4385 return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(separator), EMPTY, EMPTY, StringUtils::toStringOrEmpty)); 4386 } 4387 4388 /** 4389 * Joins the elements of the provided {@link List} into a single String 4390 * containing the provided list of elements. 4391 * 4392 * <p>No delimiter is added before or after the list. 4393 * Null objects or empty strings within the array are represented by 4394 * empty strings.</p> 4395 * 4396 * <pre> 4397 * StringUtils.join(null, *) = null 4398 * StringUtils.join([], *) = "" 4399 * StringUtils.join([null], *) = "" 4400 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4401 * StringUtils.join(["a", "b", "c"], null) = "abc" 4402 * StringUtils.join([null, "", "a"], ';') = ";;a" 4403 * </pre> 4404 * 4405 * @param list the {@link List} of values to join together, may be null 4406 * @param separator the separator character to use 4407 * @param startIndex the first index to start joining from. It is 4408 * an error to pass in a start index past the end of the list 4409 * @param endIndex the index to stop joining from (exclusive). It is 4410 * an error to pass in an end index past the end of the list 4411 * @return the joined String, {@code null} if null list input 4412 * @since 3.8 4413 */ 4414 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4415 if (list == null) { 4416 return null; 4417 } 4418 final int noOfItems = endIndex - startIndex; 4419 if (noOfItems <= 0) { 4420 return EMPTY; 4421 } 4422 final List<?> subList = list.subList(startIndex, endIndex); 4423 return join(subList.iterator(), separator); 4424 } 4425 4426 /** 4427 * Joins the elements of the provided {@link List} into a single String 4428 * containing the provided list of elements. 4429 * 4430 * <p>No delimiter is added before or after the list. 4431 * Null objects or empty strings within the array are represented by 4432 * empty strings.</p> 4433 * 4434 * <pre> 4435 * StringUtils.join(null, *) = null 4436 * StringUtils.join([], *) = "" 4437 * StringUtils.join([null], *) = "" 4438 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4439 * StringUtils.join(["a", "b", "c"], null) = "abc" 4440 * StringUtils.join([null, "", "a"], ';') = ";;a" 4441 * </pre> 4442 * 4443 * @param list the {@link List} of values to join together, may be null 4444 * @param separator the separator character to use 4445 * @param startIndex the first index to start joining from. It is 4446 * an error to pass in a start index past the end of the list 4447 * @param endIndex the index to stop joining from (exclusive). It is 4448 * an error to pass in an end index past the end of the list 4449 * @return the joined String, {@code null} if null list input 4450 * @since 3.8 4451 */ 4452 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4453 if (list == null) { 4454 return null; 4455 } 4456 final int noOfItems = endIndex - startIndex; 4457 if (noOfItems <= 0) { 4458 return EMPTY; 4459 } 4460 final List<?> subList = list.subList(startIndex, endIndex); 4461 return join(subList.iterator(), separator); 4462 } 4463 4464 4465 /** 4466 * Joins the elements of the provided array into a single String containing the provided list of elements. 4467 * 4468 * <p> 4469 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4470 * by empty strings. 4471 * </p> 4472 * 4473 * <pre> 4474 * StringUtils.join(null, *) = null 4475 * StringUtils.join([], *) = "" 4476 * StringUtils.join([null], *) = "" 4477 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4478 * StringUtils.join([1, 2, 3], null) = "123" 4479 * </pre> 4480 * 4481 * @param array 4482 * the array of values to join together, may be null 4483 * @param separator 4484 * the separator character to use 4485 * @return the joined String, {@code null} if null array input 4486 * @since 3.2 4487 */ 4488 public static String join(final long[] array, final char separator) { 4489 if (array == null) { 4490 return null; 4491 } 4492 return join(array, separator, 0, array.length); 4493 } 4494 4495 /** 4496 * Joins the elements of the provided array into a single String containing the provided list of elements. 4497 * 4498 * <p> 4499 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4500 * by empty strings. 4501 * </p> 4502 * 4503 * <pre> 4504 * StringUtils.join(null, *) = null 4505 * StringUtils.join([], *) = "" 4506 * StringUtils.join([null], *) = "" 4507 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4508 * StringUtils.join([1, 2, 3], null) = "123" 4509 * </pre> 4510 * 4511 * @param array 4512 * the array of values to join together, may be null 4513 * @param delimiter 4514 * the separator character to use 4515 * @param startIndex 4516 * the first index to start joining from. It is an error to pass in a start index past the end of the 4517 * array 4518 * @param endIndex 4519 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4520 * the array 4521 * @return the joined String, {@code null} if null array input 4522 * @since 3.2 4523 */ 4524 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4525 if (array == null) { 4526 return null; 4527 } 4528 if (endIndex - startIndex <= 0) { 4529 return EMPTY; 4530 } 4531 final StringBuilder stringBuilder = new StringBuilder(); 4532 for (int i = startIndex; i < endIndex; i++) { 4533 stringBuilder 4534 .append(array[i]) 4535 .append(delimiter); 4536 } 4537 return stringBuilder.substring(0, stringBuilder.length() - 1); 4538 } 4539 4540 /** 4541 * Joins the elements of the provided array into a single String 4542 * containing the provided list of elements. 4543 * 4544 * <p>No delimiter is added before or after the list. 4545 * Null objects or empty strings within the array are represented by 4546 * empty strings.</p> 4547 * 4548 * <pre> 4549 * StringUtils.join(null, *) = null 4550 * StringUtils.join([], *) = "" 4551 * StringUtils.join([null], *) = "" 4552 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4553 * StringUtils.join(["a", "b", "c"], null) = "abc" 4554 * StringUtils.join([null, "", "a"], ';') = ";;a" 4555 * </pre> 4556 * 4557 * @param array the array of values to join together, may be null 4558 * @param delimiter the separator character to use 4559 * @return the joined String, {@code null} if null array input 4560 * @since 2.0 4561 */ 4562 public static String join(final Object[] array, final char delimiter) { 4563 if (array == null) { 4564 return null; 4565 } 4566 return join(array, delimiter, 0, array.length); 4567 } 4568 4569 /** 4570 * Joins the elements of the provided array into a single String 4571 * containing the provided list of elements. 4572 * 4573 * <p>No delimiter is added before or after the list. 4574 * Null objects or empty strings within the array are represented by 4575 * empty strings.</p> 4576 * 4577 * <pre> 4578 * StringUtils.join(null, *) = null 4579 * StringUtils.join([], *) = "" 4580 * StringUtils.join([null], *) = "" 4581 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4582 * StringUtils.join(["a", "b", "c"], null) = "abc" 4583 * StringUtils.join([null, "", "a"], ';') = ";;a" 4584 * </pre> 4585 * 4586 * @param array the array of values to join together, may be null 4587 * @param delimiter the separator character to use 4588 * @param startIndex the first index to start joining from. It is 4589 * an error to pass in a start index past the end of the array 4590 * @param endIndex the index to stop joining from (exclusive). It is 4591 * an error to pass in an end index past the end of the array 4592 * @return the joined String, {@code null} if null array input 4593 * @since 2.0 4594 */ 4595 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4596 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4597 } 4598 4599 /** 4600 * Joins the elements of the provided array into a single String 4601 * containing the provided list of elements. 4602 * 4603 * <p>No delimiter is added before or after the list. 4604 * A {@code null} separator is the same as an empty String (""). 4605 * Null objects or empty strings within the array are represented by 4606 * empty strings.</p> 4607 * 4608 * <pre> 4609 * StringUtils.join(null, *) = null 4610 * StringUtils.join([], *) = "" 4611 * StringUtils.join([null], *) = "" 4612 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4613 * StringUtils.join(["a", "b", "c"], null) = "abc" 4614 * StringUtils.join(["a", "b", "c"], "") = "abc" 4615 * StringUtils.join([null, "", "a"], ',') = ",,a" 4616 * </pre> 4617 * 4618 * @param array the array of values to join together, may be null 4619 * @param delimiter the separator character to use, null treated as "" 4620 * @return the joined String, {@code null} if null array input 4621 */ 4622 public static String join(final Object[] array, final String delimiter) { 4623 return array != null ? join(array, toStringOrEmpty(delimiter), 0, array.length) : null; 4624 } 4625 4626 /** 4627 * Joins the elements of the provided array into a single String 4628 * containing the provided list of elements. 4629 * 4630 * <p>No delimiter is added before or after the list. 4631 * A {@code null} separator is the same as an empty String (""). 4632 * Null objects or empty strings within the array are represented by 4633 * empty strings.</p> 4634 * 4635 * <pre> 4636 * StringUtils.join(null, *, *, *) = null 4637 * StringUtils.join([], *, *, *) = "" 4638 * StringUtils.join([null], *, *, *) = "" 4639 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4640 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4641 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4642 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4643 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4644 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4645 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4646 * </pre> 4647 * 4648 * @param array the array of values to join together, may be null 4649 * @param delimiter the separator character to use, null treated as "" 4650 * @param startIndex the first index to start joining from. 4651 * @param endIndex the index to stop joining from (exclusive). 4652 * @return the joined String, {@code null} if null array input; or the empty string 4653 * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by 4654 * {@code endIndex - startIndex} 4655 * @throws ArrayIndexOutOfBoundsException ife<br> 4656 * {@code startIndex < 0} or <br> 4657 * {@code startIndex >= array.length()} or <br> 4658 * {@code endIndex < 0} or <br> 4659 * {@code endIndex > array.length()} 4660 */ 4661 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4662 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4663 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, StringUtils::toStringOrEmpty)) : null; 4664 } 4665 4666 /** 4667 * Joins the elements of the provided array into a single String containing the provided list of elements. 4668 * 4669 * <p> 4670 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4671 * by empty strings. 4672 * </p> 4673 * 4674 * <pre> 4675 * StringUtils.join(null, *) = null 4676 * StringUtils.join([], *) = "" 4677 * StringUtils.join([null], *) = "" 4678 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4679 * StringUtils.join([1, 2, 3], null) = "123" 4680 * </pre> 4681 * 4682 * @param array 4683 * the array of values to join together, may be null 4684 * @param delimiter 4685 * the separator character to use 4686 * @return the joined String, {@code null} if null array input 4687 * @since 3.2 4688 */ 4689 public static String join(final short[] array, final char delimiter) { 4690 if (array == null) { 4691 return null; 4692 } 4693 return join(array, delimiter, 0, array.length); 4694 } 4695 4696 /** 4697 * Joins the elements of the provided array into a single String containing the provided list of elements. 4698 * 4699 * <p> 4700 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4701 * by empty strings. 4702 * </p> 4703 * 4704 * <pre> 4705 * StringUtils.join(null, *) = null 4706 * StringUtils.join([], *) = "" 4707 * StringUtils.join([null], *) = "" 4708 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4709 * StringUtils.join([1, 2, 3], null) = "123" 4710 * </pre> 4711 * 4712 * @param array 4713 * the array of values to join together, may be null 4714 * @param delimiter 4715 * the separator character to use 4716 * @param startIndex 4717 * the first index to start joining from. It is an error to pass in a start index past the end of the 4718 * array 4719 * @param endIndex 4720 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4721 * the array 4722 * @return the joined String, {@code null} if null array input 4723 * @since 3.2 4724 */ 4725 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4726 if (array == null) { 4727 return null; 4728 } 4729 if (endIndex - startIndex <= 0) { 4730 return EMPTY; 4731 } 4732 final StringBuilder stringBuilder = new StringBuilder(); 4733 for (int i = startIndex; i < endIndex; i++) { 4734 stringBuilder 4735 .append(array[i]) 4736 .append(delimiter); 4737 } 4738 return stringBuilder.substring(0, stringBuilder.length() - 1); 4739 } 4740 4741 /** 4742 * Joins the elements of the provided array into a single String 4743 * containing the provided list of elements. 4744 * 4745 * <p>No separator is added to the joined String. 4746 * Null objects or empty strings within the array are represented by 4747 * empty strings.</p> 4748 * 4749 * <pre> 4750 * StringUtils.join(null) = null 4751 * StringUtils.join([]) = "" 4752 * StringUtils.join([null]) = "" 4753 * StringUtils.join(["a", "b", "c"]) = "abc" 4754 * StringUtils.join([null, "", "a"]) = "a" 4755 * </pre> 4756 * 4757 * @param <T> the specific type of values to join together 4758 * @param elements the values to join together, may be null 4759 * @return the joined String, {@code null} if null array input 4760 * @since 2.0 4761 * @since 3.0 Changed signature to use varargs 4762 */ 4763 @SafeVarargs 4764 public static <T> String join(final T... elements) { 4765 return join(elements, null); 4766 } 4767 4768 /** 4769 * Joins the elements of the provided varargs into a 4770 * single String containing the provided elements. 4771 * 4772 * <p>No delimiter is added before or after the list. 4773 * {@code null} elements and separator are treated as empty Strings ("").</p> 4774 * 4775 * <pre> 4776 * StringUtils.joinWith(",", {"a", "b"}) = "a,b" 4777 * StringUtils.joinWith(",", {"a", "b",""}) = "a,b," 4778 * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b" 4779 * StringUtils.joinWith(null, {"a", "b"}) = "ab" 4780 * </pre> 4781 * 4782 * @param delimiter the separator character to use, null treated as "" 4783 * @param array the varargs providing the values to join together. {@code null} elements are treated as "" 4784 * @return the joined String. 4785 * @throws IllegalArgumentException if a null varargs is provided 4786 * @since 3.5 4787 */ 4788 public static String joinWith(final String delimiter, final Object... array) { 4789 if (array == null) { 4790 throw new IllegalArgumentException("Object varargs must not be null"); 4791 } 4792 return join(array, delimiter); 4793 } 4794 4795 /** 4796 * Finds the last index within a CharSequence, handling {@code null}. 4797 * This method uses {@link String#lastIndexOf(String)} if possible. 4798 * 4799 * <p>A {@code null} CharSequence will return {@code -1}.</p> 4800 * 4801 * <pre> 4802 * StringUtils.lastIndexOf(null, *) = -1 4803 * StringUtils.lastIndexOf(*, null) = -1 4804 * StringUtils.lastIndexOf("", "") = 0 4805 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4806 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4807 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4808 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4809 * </pre> 4810 * 4811 * @param seq the CharSequence to check, may be null 4812 * @param searchSeq the CharSequence to find, may be null 4813 * @return the last index of the search String, 4814 * -1 if no match or {@code null} string input 4815 * @since 2.0 4816 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4817 */ 4818 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4819 if (seq == null) { 4820 return INDEX_NOT_FOUND; 4821 } 4822 return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length()); 4823 } 4824 4825 /** 4826 * Finds the last index within a CharSequence, handling {@code null}. 4827 * This method uses {@link String#lastIndexOf(String, int)} if possible. 4828 * 4829 * <p>A {@code null} CharSequence will return {@code -1}. 4830 * A negative start position returns {@code -1}. 4831 * An empty ("") search CharSequence always matches unless the start position is negative. 4832 * A start position greater than the string length searches the whole string. 4833 * The search starts at the startPos and works backwards; matches starting after the start 4834 * position are ignored. 4835 * </p> 4836 * 4837 * <pre> 4838 * StringUtils.lastIndexOf(null, *, *) = -1 4839 * StringUtils.lastIndexOf(*, null, *) = -1 4840 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4841 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4842 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4843 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4844 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4845 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4846 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4847 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4848 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4849 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4850 * </pre> 4851 * 4852 * @param seq the CharSequence to check, may be null 4853 * @param searchSeq the CharSequence to find, may be null 4854 * @param startPos the start position, negative treated as zero 4855 * @return the last index of the search CharSequence (always ≤ startPos), 4856 * -1 if no match or {@code null} string input 4857 * @since 2.0 4858 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4859 */ 4860 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4861 return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos); 4862 } 4863 4864 /** 4865 * Returns the index within {@code seq} of the last occurrence of 4866 * the specified character. For values of {@code searchChar} in the 4867 * range from 0 to 0xFFFF (inclusive), the index (in Unicode code 4868 * units) returned is the largest value <i>k</i> such that: 4869 * <blockquote><pre> 4870 * this.charAt(<i>k</i>) == searchChar 4871 * </pre></blockquote> 4872 * is true. For other values of {@code searchChar}, it is the 4873 * largest value <i>k</i> such that: 4874 * <blockquote><pre> 4875 * this.codePointAt(<i>k</i>) == searchChar 4876 * </pre></blockquote> 4877 * is true. In either case, if no such character occurs in this 4878 * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4879 * {@link CharSequence} will return {@code -1}. The 4880 * {@code seq} {@link CharSequence} object is searched backwards 4881 * starting at the last character. 4882 * 4883 * <pre> 4884 * StringUtils.lastIndexOf(null, *) = -1 4885 * StringUtils.lastIndexOf("", *) = -1 4886 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4887 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4888 * </pre> 4889 * 4890 * @param seq the {@link CharSequence} to check, may be null 4891 * @param searchChar the character to find 4892 * @return the last index of the search character, 4893 * -1 if no match or {@code null} string input 4894 * @since 2.0 4895 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4896 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4897 */ 4898 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4899 if (isEmpty(seq)) { 4900 return INDEX_NOT_FOUND; 4901 } 4902 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4903 } 4904 4905 /** 4906 * Returns the index within {@code seq} of the last occurrence of 4907 * the specified character, searching backward starting at the 4908 * specified index. For values of {@code searchChar} in the range 4909 * from 0 to 0xFFFF (inclusive), the index returned is the largest 4910 * value <i>k</i> such that: 4911 * <blockquote><pre> 4912 * (this.charAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4913 * </pre></blockquote> 4914 * is true. For other values of {@code searchChar}, it is the 4915 * largest value <i>k</i> such that: 4916 * <blockquote><pre> 4917 * (this.codePointAt(<i>k</i>) == searchChar) && (<i>k</i> <= startPos) 4918 * </pre></blockquote> 4919 * is true. In either case, if no such character occurs in {@code seq} 4920 * at or before position {@code startPos}, then 4921 * {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4922 * {@link CharSequence} will return {@code -1}. A start position greater 4923 * than the string length searches the whole string. 4924 * The search starts at the {@code startPos} and works backwards; 4925 * matches starting after the start position are ignored. 4926 * 4927 * <p>All indices are specified in {@code char} values 4928 * (Unicode code units). 4929 * 4930 * <pre> 4931 * StringUtils.lastIndexOf(null, *, *) = -1 4932 * StringUtils.lastIndexOf("", *, *) = -1 4933 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4934 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4935 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4936 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4937 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4938 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 4939 * </pre> 4940 * 4941 * @param seq the CharSequence to check, may be null 4942 * @param searchChar the character to find 4943 * @param startPos the start position 4944 * @return the last index of the search character (always ≤ startPos), 4945 * -1 if no match or {@code null} string input 4946 * @since 2.0 4947 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 4948 */ 4949 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 4950 if (isEmpty(seq)) { 4951 return INDEX_NOT_FOUND; 4952 } 4953 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 4954 } 4955 4956 /** 4957 * Find the latest index of any substring in a set of potential substrings. 4958 * 4959 * <p>A {@code null} CharSequence will return {@code -1}. 4960 * A {@code null} search array will return {@code -1}. 4961 * A {@code null} or zero length search array entry will be ignored, 4962 * but a search array containing "" will return the length of {@code str} 4963 * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p> 4964 * 4965 * <pre> 4966 * StringUtils.lastIndexOfAny(null, *) = -1 4967 * StringUtils.lastIndexOfAny(*, null) = -1 4968 * StringUtils.lastIndexOfAny(*, []) = -1 4969 * StringUtils.lastIndexOfAny(*, [null]) = -1 4970 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 4971 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 4972 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4973 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4974 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 4975 * </pre> 4976 * 4977 * @param str the CharSequence to check, may be null 4978 * @param searchStrs the CharSequences to search for, may be null 4979 * @return the last index of any of the CharSequences, -1 if no match 4980 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 4981 */ 4982 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 4983 if (str == null || searchStrs == null) { 4984 return INDEX_NOT_FOUND; 4985 } 4986 int ret = INDEX_NOT_FOUND; 4987 int tmp; 4988 for (final CharSequence search : searchStrs) { 4989 if (search == null) { 4990 continue; 4991 } 4992 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 4993 if (tmp > ret) { 4994 ret = tmp; 4995 } 4996 } 4997 return ret; 4998 } 4999 5000 /** 5001 * Case in-sensitive find of the last index within a CharSequence. 5002 * 5003 * <p>A {@code null} CharSequence will return {@code -1}. 5004 * A negative start position returns {@code -1}. 5005 * An empty ("") search CharSequence always matches unless the start position is negative. 5006 * A start position greater than the string length searches the whole string.</p> 5007 * 5008 * <pre> 5009 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5010 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5011 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5012 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5013 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5014 * </pre> 5015 * 5016 * @param str the CharSequence to check, may be null 5017 * @param searchStr the CharSequence to find, may be null 5018 * @return the first index of the search CharSequence, 5019 * -1 if no match or {@code null} string input 5020 * @since 2.5 5021 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5022 */ 5023 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5024 if (str == null || searchStr == null) { 5025 return INDEX_NOT_FOUND; 5026 } 5027 return lastIndexOfIgnoreCase(str, searchStr, str.length()); 5028 } 5029 5030 /** 5031 * Case in-sensitive find of the last index within a CharSequence 5032 * from the specified position. 5033 * 5034 * <p>A {@code null} CharSequence will return {@code -1}. 5035 * A negative start position returns {@code -1}. 5036 * An empty ("") search CharSequence always matches unless the start position is negative. 5037 * A start position greater than the string length searches the whole string. 5038 * The search starts at the startPos and works backwards; matches starting after the start 5039 * position are ignored. 5040 * </p> 5041 * 5042 * <pre> 5043 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5044 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5045 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5046 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5047 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5048 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5049 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5050 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5051 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5052 * </pre> 5053 * 5054 * @param str the CharSequence to check, may be null 5055 * @param searchStr the CharSequence to find, may be null 5056 * @param startPos the start position 5057 * @return the last index of the search CharSequence (always ≤ startPos), 5058 * -1 if no match or {@code null} input 5059 * @since 2.5 5060 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5061 */ 5062 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 5063 if (str == null || searchStr == null) { 5064 return INDEX_NOT_FOUND; 5065 } 5066 final int searchStrLength = searchStr.length(); 5067 final int strLength = str.length(); 5068 if (startPos > strLength - searchStrLength) { 5069 startPos = strLength - searchStrLength; 5070 } 5071 if (startPos < 0) { 5072 return INDEX_NOT_FOUND; 5073 } 5074 if (searchStrLength == 0) { 5075 return startPos; 5076 } 5077 5078 for (int i = startPos; i >= 0; i--) { 5079 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStrLength)) { 5080 return i; 5081 } 5082 } 5083 return INDEX_NOT_FOUND; 5084 } 5085 5086 /** 5087 * Finds the n-th last index within a String, handling {@code null}. 5088 * This method uses {@link String#lastIndexOf(String)}. 5089 * 5090 * <p>A {@code null} String will return {@code -1}.</p> 5091 * 5092 * <pre> 5093 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5094 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5095 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5096 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5097 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5098 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5099 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5100 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5101 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5102 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5103 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5104 * </pre> 5105 * 5106 * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p> 5107 * 5108 * <pre> 5109 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5110 * </pre> 5111 * 5112 * @param str the CharSequence to check, may be null 5113 * @param searchStr the CharSequence to find, may be null 5114 * @param ordinal the n-th last {@code searchStr} to find 5115 * @return the n-th last index of the search CharSequence, 5116 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5117 * @since 2.5 5118 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5119 */ 5120 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5121 return ordinalIndexOf(str, searchStr, ordinal, true); 5122 } 5123 5124 /** 5125 * Gets the leftmost {@code len} characters of a String. 5126 * 5127 * <p>If {@code len} characters are not available, or the 5128 * String is {@code null}, the String will be returned without 5129 * an exception. An empty String is returned if len is negative.</p> 5130 * 5131 * <pre> 5132 * StringUtils.left(null, *) = null 5133 * StringUtils.left(*, -ve) = "" 5134 * StringUtils.left("", *) = "" 5135 * StringUtils.left("abc", 0) = "" 5136 * StringUtils.left("abc", 2) = "ab" 5137 * StringUtils.left("abc", 4) = "abc" 5138 * </pre> 5139 * 5140 * @param str the String to get the leftmost characters from, may be null 5141 * @param len the length of the required String 5142 * @return the leftmost characters, {@code null} if null String input 5143 */ 5144 public static String left(final String str, final int len) { 5145 if (str == null) { 5146 return null; 5147 } 5148 if (len < 0) { 5149 return EMPTY; 5150 } 5151 if (str.length() <= len) { 5152 return str; 5153 } 5154 return str.substring(0, len); 5155 } 5156 5157 /** 5158 * Left pad a String with spaces (' '). 5159 * 5160 * <p>The String is padded to the size of {@code size}.</p> 5161 * 5162 * <pre> 5163 * StringUtils.leftPad(null, *) = null 5164 * StringUtils.leftPad("", 3) = " " 5165 * StringUtils.leftPad("bat", 3) = "bat" 5166 * StringUtils.leftPad("bat", 5) = " bat" 5167 * StringUtils.leftPad("bat", 1) = "bat" 5168 * StringUtils.leftPad("bat", -1) = "bat" 5169 * </pre> 5170 * 5171 * @param str the String to pad out, may be null 5172 * @param size the size to pad to 5173 * @return left padded String or original String if no padding is necessary, 5174 * {@code null} if null String input 5175 */ 5176 public static String leftPad(final String str, final int size) { 5177 return leftPad(str, size, ' '); 5178 } 5179 5180 /** 5181 * Left pad a String with a specified character. 5182 * 5183 * <p>Pad to a size of {@code size}.</p> 5184 * 5185 * <pre> 5186 * StringUtils.leftPad(null, *, *) = null 5187 * StringUtils.leftPad("", 3, 'z') = "zzz" 5188 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5189 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5190 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5191 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5192 * </pre> 5193 * 5194 * @param str the String to pad out, may be null 5195 * @param size the size to pad to 5196 * @param padChar the character to pad with 5197 * @return left padded String or original String if no padding is necessary, 5198 * {@code null} if null String input 5199 * @since 2.0 5200 */ 5201 public static String leftPad(final String str, final int size, final char padChar) { 5202 if (str == null) { 5203 return null; 5204 } 5205 final int pads = size - str.length(); 5206 if (pads <= 0) { 5207 return str; // returns original String when possible 5208 } 5209 if (pads > PAD_LIMIT) { 5210 return leftPad(str, size, String.valueOf(padChar)); 5211 } 5212 return repeat(padChar, pads).concat(str); 5213 } 5214 5215 /** 5216 * Left pad a String with a specified String. 5217 * 5218 * <p>Pad to a size of {@code size}.</p> 5219 * 5220 * <pre> 5221 * StringUtils.leftPad(null, *, *) = null 5222 * StringUtils.leftPad("", 3, "z") = "zzz" 5223 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5224 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5225 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5226 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5227 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5228 * StringUtils.leftPad("bat", 5, null) = " bat" 5229 * StringUtils.leftPad("bat", 5, "") = " bat" 5230 * </pre> 5231 * 5232 * @param str the String to pad out, may be null 5233 * @param size the size to pad to 5234 * @param padStr the String to pad with, null or empty treated as single space 5235 * @return left padded String or original String if no padding is necessary, 5236 * {@code null} if null String input 5237 */ 5238 public static String leftPad(final String str, final int size, String padStr) { 5239 if (str == null) { 5240 return null; 5241 } 5242 if (isEmpty(padStr)) { 5243 padStr = SPACE; 5244 } 5245 final int padLen = padStr.length(); 5246 final int strLen = str.length(); 5247 final int pads = size - strLen; 5248 if (pads <= 0) { 5249 return str; // returns original String when possible 5250 } 5251 if (padLen == 1 && pads <= PAD_LIMIT) { 5252 return leftPad(str, size, padStr.charAt(0)); 5253 } 5254 5255 if (pads == padLen) { 5256 return padStr.concat(str); 5257 } 5258 if (pads < padLen) { 5259 return padStr.substring(0, pads).concat(str); 5260 } 5261 final char[] padding = new char[pads]; 5262 final char[] padChars = padStr.toCharArray(); 5263 for (int i = 0; i < pads; i++) { 5264 padding[i] = padChars[i % padLen]; 5265 } 5266 return new String(padding).concat(str); 5267 } 5268 5269 /** 5270 * Gets a CharSequence length or {@code 0} if the CharSequence is 5271 * {@code null}. 5272 * 5273 * @param cs 5274 * a CharSequence or {@code null} 5275 * @return CharSequence length or {@code 0} if the CharSequence is 5276 * {@code null}. 5277 * @since 2.4 5278 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5279 */ 5280 public static int length(final CharSequence cs) { 5281 return cs == null ? 0 : cs.length(); 5282 } 5283 5284 /** 5285 * Converts a String to lower case as per {@link String#toLowerCase()}. 5286 * 5287 * <p>A {@code null} input String returns {@code null}.</p> 5288 * 5289 * <pre> 5290 * StringUtils.lowerCase(null) = null 5291 * StringUtils.lowerCase("") = "" 5292 * StringUtils.lowerCase("aBc") = "abc" 5293 * </pre> 5294 * 5295 * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, 5296 * the result of this method is affected by the current locale. 5297 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5298 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5299 * 5300 * @param str the String to lower case, may be null 5301 * @return the lower cased String, {@code null} if null String input 5302 */ 5303 public static String lowerCase(final String str) { 5304 if (str == null) { 5305 return null; 5306 } 5307 return str.toLowerCase(); 5308 } 5309 5310 /** 5311 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5312 * 5313 * <p>A {@code null} input String returns {@code null}.</p> 5314 * 5315 * <pre> 5316 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5317 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5318 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5319 * </pre> 5320 * 5321 * @param str the String to lower case, may be null 5322 * @param locale the locale that defines the case transformation rules, must not be null 5323 * @return the lower cased String, {@code null} if null String input 5324 * @since 2.5 5325 */ 5326 public static String lowerCase(final String str, final Locale locale) { 5327 if (str == null) { 5328 return null; 5329 } 5330 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5331 } 5332 5333 private static int[] matches(final CharSequence first, final CharSequence second) { 5334 final CharSequence max; 5335 final CharSequence min; 5336 if (first.length() > second.length()) { 5337 max = first; 5338 min = second; 5339 } else { 5340 max = second; 5341 min = first; 5342 } 5343 final int range = Math.max(max.length() / 2 - 1, 0); 5344 final int[] matchIndexes = new int[min.length()]; 5345 Arrays.fill(matchIndexes, -1); 5346 final boolean[] matchFlags = new boolean[max.length()]; 5347 int matches = 0; 5348 for (int mi = 0; mi < min.length(); mi++) { 5349 final char c1 = min.charAt(mi); 5350 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5351 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5352 matchIndexes[mi] = xi; 5353 matchFlags[xi] = true; 5354 matches++; 5355 break; 5356 } 5357 } 5358 } 5359 final char[] ms1 = new char[matches]; 5360 final char[] ms2 = new char[matches]; 5361 for (int i = 0, si = 0; i < min.length(); i++) { 5362 if (matchIndexes[i] != -1) { 5363 ms1[si] = min.charAt(i); 5364 si++; 5365 } 5366 } 5367 for (int i = 0, si = 0; i < max.length(); i++) { 5368 if (matchFlags[i]) { 5369 ms2[si] = max.charAt(i); 5370 si++; 5371 } 5372 } 5373 int transpositions = 0; 5374 for (int mi = 0; mi < ms1.length; mi++) { 5375 if (ms1[mi] != ms2[mi]) { 5376 transpositions++; 5377 } 5378 } 5379 int prefix = 0; 5380 for (int mi = 0; mi < min.length(); mi++) { 5381 if (first.charAt(mi) != second.charAt(mi)) { 5382 break; 5383 } 5384 prefix++; 5385 } 5386 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5387 } 5388 5389 /** 5390 * Gets {@code len} characters from the middle of a String. 5391 * 5392 * <p>If {@code len} characters are not available, the remainder 5393 * of the String will be returned without an exception. If the 5394 * String is {@code null}, {@code null} will be returned. 5395 * An empty String is returned if len is negative or exceeds the 5396 * length of {@code str}.</p> 5397 * 5398 * <pre> 5399 * StringUtils.mid(null, *, *) = null 5400 * StringUtils.mid(*, *, -ve) = "" 5401 * StringUtils.mid("", 0, *) = "" 5402 * StringUtils.mid("abc", 0, 2) = "ab" 5403 * StringUtils.mid("abc", 0, 4) = "abc" 5404 * StringUtils.mid("abc", 2, 4) = "c" 5405 * StringUtils.mid("abc", 4, 2) = "" 5406 * StringUtils.mid("abc", -2, 2) = "ab" 5407 * </pre> 5408 * 5409 * @param str the String to get the characters from, may be null 5410 * @param pos the position to start from, negative treated as zero 5411 * @param len the length of the required String 5412 * @return the middle characters, {@code null} if null String input 5413 */ 5414 public static String mid(final String str, int pos, final int len) { 5415 if (str == null) { 5416 return null; 5417 } 5418 if (len < 0 || pos > str.length()) { 5419 return EMPTY; 5420 } 5421 if (pos < 0) { 5422 pos = 0; 5423 } 5424 if (str.length() <= pos + len) { 5425 return str.substring(pos); 5426 } 5427 return str.substring(pos, pos + len); 5428 } 5429 5430 /** 5431 * Similar to <a 5432 * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize 5433 * -space</a> 5434 * 5435 * <p> 5436 * The function returns the argument string with whitespace normalized by using 5437 * {@code {@link #trim(String)}} to remove leading and trailing whitespace 5438 * and then replacing sequences of whitespace characters by a single space. 5439 * </p> 5440 * In XML Whitespace characters are the same as those allowed by the <a 5441 * href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+ 5442 * <p> 5443 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5444 * 5445 * <p>For reference:</p> 5446 * <ul> 5447 * <li>\x0B = vertical tab</li> 5448 * <li>\f = #xC = form feed</li> 5449 * <li>#x20 = space</li> 5450 * <li>#x9 = \t</li> 5451 * <li>#xA = \n</li> 5452 * <li>#xD = \r</li> 5453 * </ul> 5454 * 5455 * <p> 5456 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also 5457 * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char <= 32) from both 5458 * ends of this String. 5459 * </p> 5460 * 5461 * @see Pattern 5462 * @see #trim(String) 5463 * @see <a 5464 * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5465 * @param str the source String to normalize whitespaces from, may be null 5466 * @return the modified string with whitespace normalized, {@code null} if null String input 5467 * 5468 * @since 3.0 5469 */ 5470 public static String normalizeSpace(final String str) { 5471 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5472 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5473 if (isEmpty(str)) { 5474 return str; 5475 } 5476 final int size = str.length(); 5477 final char[] newChars = new char[size]; 5478 int count = 0; 5479 int whitespacesCount = 0; 5480 boolean startWhitespaces = true; 5481 for (int i = 0; i < size; i++) { 5482 final char actualChar = str.charAt(i); 5483 final boolean isWhitespace = Character.isWhitespace(actualChar); 5484 if (isWhitespace) { 5485 if (whitespacesCount == 0 && !startWhitespaces) { 5486 newChars[count++] = SPACE.charAt(0); 5487 } 5488 whitespacesCount++; 5489 } else { 5490 startWhitespaces = false; 5491 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5492 whitespacesCount = 0; 5493 } 5494 } 5495 if (startWhitespaces) { 5496 return EMPTY; 5497 } 5498 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5499 } 5500 5501 /** 5502 * Finds the n-th index within a CharSequence, handling {@code null}. 5503 * This method uses {@link String#indexOf(String)} if possible. 5504 * <p><b>Note:</b> The code starts looking for a match at the start of the target, 5505 * incrementing the starting index by one after each successful match 5506 * (unless {@code searchStr} is an empty string in which case the position 5507 * is never incremented and {@code 0} is returned immediately). 5508 * This means that matches may overlap.</p> 5509 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5510 * 5511 * <pre> 5512 * StringUtils.ordinalIndexOf(null, *, *) = -1 5513 * StringUtils.ordinalIndexOf(*, null, *) = -1 5514 * StringUtils.ordinalIndexOf("", "", *) = 0 5515 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5516 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5517 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5518 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5519 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5520 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5521 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5522 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5523 * </pre> 5524 * 5525 * <p>Matches may overlap:</p> 5526 * <pre> 5527 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5528 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5529 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5530 * 5531 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5532 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5533 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5534 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5535 * </pre> 5536 * 5537 * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p> 5538 * 5539 * <pre> 5540 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5541 * </pre> 5542 * 5543 * @param str the CharSequence to check, may be null 5544 * @param searchStr the CharSequence to find, may be null 5545 * @param ordinal the n-th {@code searchStr} to find 5546 * @return the n-th index of the search CharSequence, 5547 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5548 * @since 2.1 5549 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5550 */ 5551 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5552 return ordinalIndexOf(str, searchStr, ordinal, false); 5553 } 5554 5555 /** 5556 * Finds the n-th index within a String, handling {@code null}. 5557 * This method uses {@link String#indexOf(String)} if possible. 5558 * <p>Note that matches may overlap<p> 5559 * 5560 * <p>A {@code null} CharSequence will return {@code -1}.</p> 5561 * 5562 * @param str the CharSequence to check, may be null 5563 * @param searchStr the CharSequence to find, may be null 5564 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5565 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf() 5566 * @return the n-th index of the search CharSequence, 5567 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 5568 */ 5569 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5570 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5571 if (str == null || searchStr == null || ordinal <= 0) { 5572 return INDEX_NOT_FOUND; 5573 } 5574 if (searchStr.length() == 0) { 5575 return lastIndex ? str.length() : 0; 5576 } 5577 int found = 0; 5578 // set the initial index beyond the end of the string 5579 // this is to allow for the initial index decrement/increment 5580 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5581 do { 5582 if (lastIndex) { 5583 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5584 } else { 5585 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5586 } 5587 if (index < 0) { 5588 return index; 5589 } 5590 found++; 5591 } while (found < ordinal); 5592 return index; 5593 } 5594 5595 /** 5596 * Overlays part of a String with another String. 5597 * 5598 * <p>A {@code null} string input returns {@code null}. 5599 * A negative index is treated as zero. 5600 * An index greater than the string length is treated as the string length. 5601 * The start index is always the smaller of the two indices.</p> 5602 * 5603 * <pre> 5604 * StringUtils.overlay(null, *, *, *) = null 5605 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5606 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5607 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5608 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5609 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5610 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5611 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5612 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5613 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5614 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5615 * </pre> 5616 * 5617 * @param str the String to do overlaying in, may be null 5618 * @param overlay the String to overlay, may be null 5619 * @param start the position to start overlaying at 5620 * @param end the position to stop overlaying before 5621 * @return overlayed String, {@code null} if null String input 5622 * @since 2.0 5623 */ 5624 public static String overlay(final String str, String overlay, int start, int end) { 5625 if (str == null) { 5626 return null; 5627 } 5628 if (overlay == null) { 5629 overlay = EMPTY; 5630 } 5631 final int len = str.length(); 5632 if (start < 0) { 5633 start = 0; 5634 } 5635 if (start > len) { 5636 start = len; 5637 } 5638 if (end < 0) { 5639 end = 0; 5640 } 5641 if (end > len) { 5642 end = len; 5643 } 5644 if (start > end) { 5645 final int temp = start; 5646 start = end; 5647 end = temp; 5648 } 5649 return str.substring(0, start) + 5650 overlay + 5651 str.substring(end); 5652 } 5653 5654 /** 5655 * Prepends the prefix to the start of the string if the string does not 5656 * already start with any of the prefixes. 5657 * 5658 * @param str The string. 5659 * @param prefix The prefix to prepend to the start of the string. 5660 * @param ignoreCase Indicates whether the compare should ignore case. 5661 * @param prefixes Additional prefixes that are valid (optional). 5662 * 5663 * @return A new String if prefix was prepended, the same string otherwise. 5664 */ 5665 private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) { 5666 if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) { 5667 return str; 5668 } 5669 if (ArrayUtils.isNotEmpty(prefixes)) { 5670 for (final CharSequence p : prefixes) { 5671 if (startsWith(str, p, ignoreCase)) { 5672 return str; 5673 } 5674 } 5675 } 5676 return prefix.toString() + str; 5677 } 5678 5679 /** 5680 * Prepends the prefix to the start of the string if the string does not 5681 * already start with any of the prefixes. 5682 * 5683 * <pre> 5684 * StringUtils.prependIfMissing(null, null) = null 5685 * StringUtils.prependIfMissing("abc", null) = "abc" 5686 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5687 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5688 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5689 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5690 * </pre> 5691 * <p>With additional prefixes,</p> 5692 * <pre> 5693 * StringUtils.prependIfMissing(null, null, null) = null 5694 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5695 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5696 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5697 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5698 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5699 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5700 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5701 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5702 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5703 * </pre> 5704 * 5705 * @param str The string. 5706 * @param prefix The prefix to prepend to the start of the string. 5707 * @param prefixes Additional prefixes that are valid. 5708 * 5709 * @return A new String if prefix was prepended, the same string otherwise. 5710 * 5711 * @since 3.2 5712 */ 5713 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5714 return prependIfMissing(str, prefix, false, prefixes); 5715 } 5716 5717 /** 5718 * Prepends the prefix to the start of the string if the string does not 5719 * already start, case-insensitive, with any of the prefixes. 5720 * 5721 * <pre> 5722 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5723 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5724 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5725 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5726 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5727 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5728 * </pre> 5729 * <p>With additional prefixes,</p> 5730 * <pre> 5731 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5732 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5733 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5734 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5735 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5736 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5737 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5738 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5739 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5740 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5741 * </pre> 5742 * 5743 * @param str The string. 5744 * @param prefix The prefix to prepend to the start of the string. 5745 * @param prefixes Additional prefixes that are valid (optional). 5746 * 5747 * @return A new String if prefix was prepended, the same string otherwise. 5748 * 5749 * @since 3.2 5750 */ 5751 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5752 return prependIfMissing(str, prefix, true, prefixes); 5753 } 5754 5755 /** 5756 * Removes all occurrences of a character from within the source string. 5757 * 5758 * <p>A {@code null} source string will return {@code null}. 5759 * An empty ("") source string will return the empty string.</p> 5760 * 5761 * <pre> 5762 * StringUtils.remove(null, *) = null 5763 * StringUtils.remove("", *) = "" 5764 * StringUtils.remove("queued", 'u') = "qeed" 5765 * StringUtils.remove("queued", 'z') = "queued" 5766 * </pre> 5767 * 5768 * @param str the source String to search, may be null 5769 * @param remove the char to search for and remove, may be null 5770 * @return the substring with the char removed if found, 5771 * {@code null} if null String input 5772 * @since 2.1 5773 */ 5774 public static String remove(final String str, final char remove) { 5775 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5776 return str; 5777 } 5778 final char[] chars = str.toCharArray(); 5779 int pos = 0; 5780 for (int i = 0; i < chars.length; i++) { 5781 if (chars[i] != remove) { 5782 chars[pos++] = chars[i]; 5783 } 5784 } 5785 return new String(chars, 0, pos); 5786 } 5787 5788 /** 5789 * Removes all occurrences of a substring from within the source string. 5790 * 5791 * <p>A {@code null} source string will return {@code null}. 5792 * An empty ("") source string will return the empty string. 5793 * A {@code null} remove string will return the source string. 5794 * An empty ("") remove string will return the source string.</p> 5795 * 5796 * <pre> 5797 * StringUtils.remove(null, *) = null 5798 * StringUtils.remove("", *) = "" 5799 * StringUtils.remove(*, null) = * 5800 * StringUtils.remove(*, "") = * 5801 * StringUtils.remove("queued", "ue") = "qd" 5802 * StringUtils.remove("queued", "zz") = "queued" 5803 * </pre> 5804 * 5805 * @param str the source String to search, may be null 5806 * @param remove the String to search for and remove, may be null 5807 * @return the substring with the string removed if found, 5808 * {@code null} if null String input 5809 * @since 2.1 5810 */ 5811 public static String remove(final String str, final String remove) { 5812 if (isEmpty(str) || isEmpty(remove)) { 5813 return str; 5814 } 5815 return replace(str, remove, EMPTY, -1); 5816 } 5817 5818 /** 5819 * Removes each substring of the text String that matches the given regular expression. 5820 * 5821 * This method is a {@code null} safe equivalent to: 5822 * <ul> 5823 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5824 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5825 * </ul> 5826 * 5827 * <p>A {@code null} reference passed to this method is a no-op.</p> 5828 * 5829 * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option 5830 * is NOT automatically added. 5831 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5832 * DOTALL is also known as single-line mode in Perl.</p> 5833 * 5834 * <pre> 5835 * StringUtils.removeAll(null, *) = null 5836 * StringUtils.removeAll("any", (String) null) = "any" 5837 * StringUtils.removeAll("any", "") = "any" 5838 * StringUtils.removeAll("any", ".*") = "" 5839 * StringUtils.removeAll("any", ".+") = "" 5840 * StringUtils.removeAll("abc", ".?") = "" 5841 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5842 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5843 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5844 * </pre> 5845 * 5846 * @param text text to remove from, may be null 5847 * @param regex the regular expression to which this string is to be matched 5848 * @return the text with any removes processed, 5849 * {@code null} if null String input 5850 * 5851 * @throws java.util.regex.PatternSyntaxException 5852 * if the regular expression's syntax is invalid 5853 * 5854 * @see #replaceAll(String, String, String) 5855 * @see #removePattern(String, String) 5856 * @see String#replaceAll(String, String) 5857 * @see java.util.regex.Pattern 5858 * @see java.util.regex.Pattern#DOTALL 5859 * @since 3.5 5860 * 5861 * @deprecated Moved to RegExUtils. 5862 */ 5863 @Deprecated 5864 public static String removeAll(final String text, final String regex) { 5865 return RegExUtils.removeAll(text, regex); 5866 } 5867 5868 /** 5869 * Removes a substring only if it is at the end of a source string, 5870 * otherwise returns the source string. 5871 * 5872 * <p>A {@code null} source string will return {@code null}. 5873 * An empty ("") source string will return the empty string. 5874 * A {@code null} search string will return the source string.</p> 5875 * 5876 * <pre> 5877 * StringUtils.removeEnd(null, *) = null 5878 * StringUtils.removeEnd("", *) = "" 5879 * StringUtils.removeEnd(*, null) = * 5880 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5881 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5882 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5883 * StringUtils.removeEnd("abc", "") = "abc" 5884 * </pre> 5885 * 5886 * @param str the source String to search, may be null 5887 * @param remove the String to search for and remove, may be null 5888 * @return the substring with the string removed if found, 5889 * {@code null} if null String input 5890 * @since 2.1 5891 */ 5892 public static String removeEnd(final String str, final String remove) { 5893 if (isEmpty(str) || isEmpty(remove)) { 5894 return str; 5895 } 5896 if (str.endsWith(remove)) { 5897 return str.substring(0, str.length() - remove.length()); 5898 } 5899 return str; 5900 } 5901 5902 /** 5903 * Case insensitive removal of a substring if it is at the end of a source string, 5904 * otherwise returns the source string. 5905 * 5906 * <p>A {@code null} source string will return {@code null}. 5907 * An empty ("") source string will return the empty string. 5908 * A {@code null} search string will return the source string.</p> 5909 * 5910 * <pre> 5911 * StringUtils.removeEndIgnoreCase(null, *) = null 5912 * StringUtils.removeEndIgnoreCase("", *) = "" 5913 * StringUtils.removeEndIgnoreCase(*, null) = * 5914 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5915 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5916 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5917 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5918 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 5919 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 5920 * </pre> 5921 * 5922 * @param str the source String to search, may be null 5923 * @param remove the String to search for (case-insensitive) and remove, may be null 5924 * @return the substring with the string removed if found, 5925 * {@code null} if null String input 5926 * @since 2.4 5927 */ 5928 public static String removeEndIgnoreCase(final String str, final String remove) { 5929 if (isEmpty(str) || isEmpty(remove)) { 5930 return str; 5931 } 5932 if (endsWithIgnoreCase(str, remove)) { 5933 return str.substring(0, str.length() - remove.length()); 5934 } 5935 return str; 5936 } 5937 5938 /** 5939 * Removes the first substring of the text string that matches the given regular expression. 5940 * 5941 * This method is a {@code null} safe equivalent to: 5942 * <ul> 5943 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 5944 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 5945 * </ul> 5946 * 5947 * <p>A {@code null} reference passed to this method is a no-op.</p> 5948 * 5949 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 5950 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 5951 * DOTALL is also known as single-line mode in Perl.</p> 5952 * 5953 * <pre> 5954 * StringUtils.removeFirst(null, *) = null 5955 * StringUtils.removeFirst("any", (String) null) = "any" 5956 * StringUtils.removeFirst("any", "") = "any" 5957 * StringUtils.removeFirst("any", ".*") = "" 5958 * StringUtils.removeFirst("any", ".+") = "" 5959 * StringUtils.removeFirst("abc", ".?") = "bc" 5960 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5961 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5962 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5963 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5964 * </pre> 5965 * 5966 * @param text text to remove from, may be null 5967 * @param regex the regular expression to which this string is to be matched 5968 * @return the text with the first replacement processed, 5969 * {@code null} if null String input 5970 * 5971 * @throws java.util.regex.PatternSyntaxException 5972 * if the regular expression's syntax is invalid 5973 * 5974 * @see #replaceFirst(String, String, String) 5975 * @see String#replaceFirst(String, String) 5976 * @see java.util.regex.Pattern 5977 * @see java.util.regex.Pattern#DOTALL 5978 * @since 3.5 5979 * 5980 * @deprecated Moved to RegExUtils. 5981 */ 5982 @Deprecated 5983 public static String removeFirst(final String text, final String regex) { 5984 return replaceFirst(text, regex, EMPTY); 5985 } 5986 5987 /** 5988 * Case insensitive removal of all occurrences of a substring from within 5989 * the source string. 5990 * 5991 * <p> 5992 * A {@code null} source string will return {@code null}. An empty ("") 5993 * source string will return the empty string. A {@code null} remove string 5994 * will return the source string. An empty ("") remove string will return 5995 * the source string. 5996 * </p> 5997 * 5998 * <pre> 5999 * StringUtils.removeIgnoreCase(null, *) = null 6000 * StringUtils.removeIgnoreCase("", *) = "" 6001 * StringUtils.removeIgnoreCase(*, null) = * 6002 * StringUtils.removeIgnoreCase(*, "") = * 6003 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 6004 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 6005 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 6006 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 6007 * </pre> 6008 * 6009 * @param str 6010 * the source String to search, may be null 6011 * @param remove 6012 * the String to search for (case-insensitive) and remove, may be 6013 * null 6014 * @return the substring with the string removed if found, {@code null} if 6015 * null String input 6016 * @since 3.5 6017 */ 6018 public static String removeIgnoreCase(final String str, final String remove) { 6019 return replaceIgnoreCase(str, remove, EMPTY, -1); 6020 } 6021 6022 /** 6023 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6024 * 6025 * This call is a {@code null} safe equivalent to: 6026 * <ul> 6027 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6028 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6029 * </ul> 6030 * 6031 * <p>A {@code null} reference passed to this method is a no-op.</p> 6032 * 6033 * <pre> 6034 * StringUtils.removePattern(null, *) = null 6035 * StringUtils.removePattern("any", (String) null) = "any" 6036 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 6037 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 6038 * </pre> 6039 * 6040 * @param source 6041 * the source string 6042 * @param regex 6043 * the regular expression to which this string is to be matched 6044 * @return The resulting {@link String} 6045 * @see #replacePattern(String, String, String) 6046 * @see String#replaceAll(String, String) 6047 * @see Pattern#DOTALL 6048 * @since 3.2 6049 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6050 * 6051 * @deprecated Moved to RegExUtils. 6052 */ 6053 @Deprecated 6054 public static String removePattern(final String source, final String regex) { 6055 return RegExUtils.removePattern(source, regex); 6056 } 6057 6058 /** 6059 * Removes a char only if it is at the beginning of a source string, 6060 * otherwise returns the source string. 6061 * 6062 * <p>A {@code null} source string will return {@code null}. 6063 * An empty ("") source string will return the empty string. 6064 * A {@code null} search char will return the source string.</p> 6065 * 6066 * <pre> 6067 * StringUtils.removeStart(null, *) = null 6068 * StringUtils.removeStart("", *) = "" 6069 * StringUtils.removeStart(*, null) = * 6070 * StringUtils.removeStart("/path", '/') = "path" 6071 * StringUtils.removeStart("path", '/') = "path" 6072 * StringUtils.removeStart("path", 0) = "path" 6073 * </pre> 6074 * 6075 * @param str the source String to search, may be null. 6076 * @param remove the char to search for and remove. 6077 * @return the substring with the char removed if found, 6078 * {@code null} if null String input. 6079 * @since 3.13.0 6080 */ 6081 public static String removeStart(final String str, final char remove) { 6082 if (isEmpty(str)) { 6083 return str; 6084 } 6085 return str.charAt(0) == remove ? str.substring(1) : str; 6086 } 6087 6088 /** 6089 * Removes a substring only if it is at the beginning of a source string, 6090 * otherwise returns the source string. 6091 * 6092 * <p>A {@code null} source string will return {@code null}. 6093 * An empty ("") source string will return the empty string. 6094 * A {@code null} search string will return the source string.</p> 6095 * 6096 * <pre> 6097 * StringUtils.removeStart(null, *) = null 6098 * StringUtils.removeStart("", *) = "" 6099 * StringUtils.removeStart(*, null) = * 6100 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6101 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6102 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6103 * StringUtils.removeStart("abc", "") = "abc" 6104 * </pre> 6105 * 6106 * @param str the source String to search, may be null 6107 * @param remove the String to search for and remove, may be null 6108 * @return the substring with the string removed if found, 6109 * {@code null} if null String input 6110 * @since 2.1 6111 */ 6112 public static String removeStart(final String str, final String remove) { 6113 if (isEmpty(str) || isEmpty(remove)) { 6114 return str; 6115 } 6116 if (str.startsWith(remove)) { 6117 return str.substring(remove.length()); 6118 } 6119 return str; 6120 } 6121 6122 /** 6123 * Case insensitive removal of a substring if it is at the beginning of a source string, 6124 * otherwise returns the source string. 6125 * 6126 * <p>A {@code null} source string will return {@code null}. 6127 * An empty ("") source string will return the empty string. 6128 * A {@code null} search string will return the source string.</p> 6129 * 6130 * <pre> 6131 * StringUtils.removeStartIgnoreCase(null, *) = null 6132 * StringUtils.removeStartIgnoreCase("", *) = "" 6133 * StringUtils.removeStartIgnoreCase(*, null) = * 6134 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6135 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6136 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6137 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6138 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6139 * </pre> 6140 * 6141 * @param str the source String to search, may be null 6142 * @param remove the String to search for (case-insensitive) and remove, may be null 6143 * @return the substring with the string removed if found, 6144 * {@code null} if null String input 6145 * @since 2.4 6146 */ 6147 public static String removeStartIgnoreCase(final String str, final String remove) { 6148 if (str != null && startsWithIgnoreCase(str, remove)) { 6149 return str.substring(length(remove)); 6150 } 6151 return str; 6152 } 6153 6154 /** 6155 * Returns padding using the specified delimiter repeated 6156 * to a given length. 6157 * 6158 * <pre> 6159 * StringUtils.repeat('e', 0) = "" 6160 * StringUtils.repeat('e', 3) = "eee" 6161 * StringUtils.repeat('e', -2) = "" 6162 * </pre> 6163 * 6164 * <p>Note: this method does not support padding with 6165 * <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6166 * as they require a pair of {@code char}s to be represented. 6167 * If you are needing to support full I18N of your applications 6168 * consider using {@link #repeat(String, int)} instead. 6169 * </p> 6170 * 6171 * @param ch character to repeat 6172 * @param repeat number of times to repeat char, negative treated as zero 6173 * @return String with repeated character 6174 * @see #repeat(String, int) 6175 */ 6176 public static String repeat(final char ch, final int repeat) { 6177 if (repeat <= 0) { 6178 return EMPTY; 6179 } 6180 final char[] buf = new char[repeat]; 6181 Arrays.fill(buf, ch); 6182 return new String(buf); 6183 } 6184 6185 /** 6186 * Repeat a String {@code repeat} times to form a 6187 * new String. 6188 * 6189 * <pre> 6190 * StringUtils.repeat(null, 2) = null 6191 * StringUtils.repeat("", 0) = "" 6192 * StringUtils.repeat("", 2) = "" 6193 * StringUtils.repeat("a", 3) = "aaa" 6194 * StringUtils.repeat("ab", 2) = "abab" 6195 * StringUtils.repeat("a", -2) = "" 6196 * </pre> 6197 * 6198 * @param str the String to repeat, may be null 6199 * @param repeat number of times to repeat str, negative treated as zero 6200 * @return a new String consisting of the original String repeated, 6201 * {@code null} if null String input 6202 */ 6203 public static String repeat(final String str, final int repeat) { 6204 // Performance tuned for 2.0 (JDK1.4) 6205 if (str == null) { 6206 return null; 6207 } 6208 if (repeat <= 0) { 6209 return EMPTY; 6210 } 6211 final int inputLength = str.length(); 6212 if (repeat == 1 || inputLength == 0) { 6213 return str; 6214 } 6215 if (inputLength == 1 && repeat <= PAD_LIMIT) { 6216 return repeat(str.charAt(0), repeat); 6217 } 6218 6219 final int outputLength = inputLength * repeat; 6220 switch (inputLength) { 6221 case 1 : 6222 return repeat(str.charAt(0), repeat); 6223 case 2 : 6224 final char ch0 = str.charAt(0); 6225 final char ch1 = str.charAt(1); 6226 final char[] output2 = new char[outputLength]; 6227 for (int i = repeat * 2 - 2; i >= 0; i--, i--) { 6228 output2[i] = ch0; 6229 output2[i + 1] = ch1; 6230 } 6231 return new String(output2); 6232 default : 6233 final StringBuilder buf = new StringBuilder(outputLength); 6234 for (int i = 0; i < repeat; i++) { 6235 buf.append(str); 6236 } 6237 return buf.toString(); 6238 } 6239 } 6240 6241 /** 6242 * Repeat a String {@code repeat} times to form a 6243 * new String, with a String separator injected each time. 6244 * 6245 * <pre> 6246 * StringUtils.repeat(null, null, 2) = null 6247 * StringUtils.repeat(null, "x", 2) = null 6248 * StringUtils.repeat("", null, 0) = "" 6249 * StringUtils.repeat("", "", 2) = "" 6250 * StringUtils.repeat("", "x", 3) = "xx" 6251 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6252 * </pre> 6253 * 6254 * @param str the String to repeat, may be null 6255 * @param separator the String to inject, may be null 6256 * @param repeat number of times to repeat str, negative treated as zero 6257 * @return a new String consisting of the original String repeated, 6258 * {@code null} if null String input 6259 * @since 2.5 6260 */ 6261 public static String repeat(final String str, final String separator, final int repeat) { 6262 if (str == null || separator == null) { 6263 return repeat(str, repeat); 6264 } 6265 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6266 final String result = repeat(str + separator, repeat); 6267 return removeEnd(result, separator); 6268 } 6269 6270 /** 6271 * Replaces all occurrences of a String within another String. 6272 * 6273 * <p>A {@code null} reference passed to this method is a no-op.</p> 6274 * 6275 * <pre> 6276 * StringUtils.replace(null, *, *) = null 6277 * StringUtils.replace("", *, *) = "" 6278 * StringUtils.replace("any", null, *) = "any" 6279 * StringUtils.replace("any", *, null) = "any" 6280 * StringUtils.replace("any", "", *) = "any" 6281 * StringUtils.replace("aba", "a", null) = "aba" 6282 * StringUtils.replace("aba", "a", "") = "b" 6283 * StringUtils.replace("aba", "a", "z") = "zbz" 6284 * </pre> 6285 * 6286 * @see #replace(String text, String searchString, String replacement, int max) 6287 * @param text text to search and replace in, may be null 6288 * @param searchString the String to search for, may be null 6289 * @param replacement the String to replace it with, may be null 6290 * @return the text with any replacements processed, 6291 * {@code null} if null String input 6292 */ 6293 public static String replace(final String text, final String searchString, final String replacement) { 6294 return replace(text, searchString, replacement, -1); 6295 } 6296 6297 /** 6298 * Replaces a String with another String inside a larger String, 6299 * for the first {@code max} values of the search String. 6300 * 6301 * <p>A {@code null} reference passed to this method is a no-op.</p> 6302 * 6303 * <pre> 6304 * StringUtils.replace(null, *, *, *) = null 6305 * StringUtils.replace("", *, *, *) = "" 6306 * StringUtils.replace("any", null, *, *) = "any" 6307 * StringUtils.replace("any", *, null, *) = "any" 6308 * StringUtils.replace("any", "", *, *) = "any" 6309 * StringUtils.replace("any", *, *, 0) = "any" 6310 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6311 * StringUtils.replace("abaa", "a", "", -1) = "b" 6312 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6313 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6314 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6315 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6316 * </pre> 6317 * 6318 * @param text text to search and replace in, may be null 6319 * @param searchString the String to search for, may be null 6320 * @param replacement the String to replace it with, may be null 6321 * @param max maximum number of values to replace, or {@code -1} if no maximum 6322 * @return the text with any replacements processed, 6323 * {@code null} if null String input 6324 */ 6325 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6326 return replace(text, searchString, replacement, max, false); 6327 } 6328 6329 /** 6330 * Replaces a String with another String inside a larger String, 6331 * for the first {@code max} values of the search String, 6332 * case-sensitively/insensitively based on {@code ignoreCase} value. 6333 * 6334 * <p>A {@code null} reference passed to this method is a no-op.</p> 6335 * 6336 * <pre> 6337 * StringUtils.replace(null, *, *, *, false) = null 6338 * StringUtils.replace("", *, *, *, false) = "" 6339 * StringUtils.replace("any", null, *, *, false) = "any" 6340 * StringUtils.replace("any", *, null, *, false) = "any" 6341 * StringUtils.replace("any", "", *, *, false) = "any" 6342 * StringUtils.replace("any", *, *, 0, false) = "any" 6343 * StringUtils.replace("abaa", "a", null, -1, false) = "abaa" 6344 * StringUtils.replace("abaa", "a", "", -1, false) = "b" 6345 * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa" 6346 * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa" 6347 * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa" 6348 * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza" 6349 * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz" 6350 * </pre> 6351 * 6352 * @param text text to search and replace in, may be null 6353 * @param searchString the String to search for (case-insensitive), may be null 6354 * @param replacement the String to replace it with, may be null 6355 * @param max maximum number of values to replace, or {@code -1} if no maximum 6356 * @param ignoreCase if true replace is case-insensitive, otherwise case-sensitive 6357 * @return the text with any replacements processed, 6358 * {@code null} if null String input 6359 */ 6360 private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) { 6361 if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 6362 return text; 6363 } 6364 if (ignoreCase) { 6365 searchString = searchString.toLowerCase(); 6366 } 6367 int start = 0; 6368 int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6369 if (end == INDEX_NOT_FOUND) { 6370 return text; 6371 } 6372 final int replLength = searchString.length(); 6373 int increase = Math.max(replacement.length() - replLength, 0); 6374 increase *= max < 0 ? 16 : Math.min(max, 64); 6375 final StringBuilder buf = new StringBuilder(text.length() + increase); 6376 while (end != INDEX_NOT_FOUND) { 6377 buf.append(text, start, end).append(replacement); 6378 start = end + replLength; 6379 if (--max == 0) { 6380 break; 6381 } 6382 end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start); 6383 } 6384 buf.append(text, start, text.length()); 6385 return buf.toString(); 6386 } 6387 6388 /** 6389 * Replaces each substring of the text String that matches the given regular expression 6390 * with the given replacement. 6391 * 6392 * This method is a {@code null} safe equivalent to: 6393 * <ul> 6394 * <li>{@code text.replaceAll(regex, replacement)}</li> 6395 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6396 * </ul> 6397 * 6398 * <p>A {@code null} reference passed to this method is a no-op.</p> 6399 * 6400 * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option 6401 * is NOT automatically added. 6402 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6403 * DOTALL is also known as single-line mode in Perl.</p> 6404 * 6405 * <pre> 6406 * StringUtils.replaceAll(null, *, *) = null 6407 * StringUtils.replaceAll("any", (String) null, *) = "any" 6408 * StringUtils.replaceAll("any", *, null) = "any" 6409 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6410 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6411 * StringUtils.replaceAll("", ".+", "zzz") = "" 6412 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6413 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6414 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6415 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6416 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6417 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6418 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6419 * </pre> 6420 * 6421 * @param text text to search and replace in, may be null 6422 * @param regex the regular expression to which this string is to be matched 6423 * @param replacement the string to be substituted for each match 6424 * @return the text with any replacements processed, 6425 * {@code null} if null String input 6426 * 6427 * @throws java.util.regex.PatternSyntaxException 6428 * if the regular expression's syntax is invalid 6429 * 6430 * @see #replacePattern(String, String, String) 6431 * @see String#replaceAll(String, String) 6432 * @see java.util.regex.Pattern 6433 * @see java.util.regex.Pattern#DOTALL 6434 * @since 3.5 6435 * 6436 * @deprecated Moved to RegExUtils. 6437 */ 6438 @Deprecated 6439 public static String replaceAll(final String text, final String regex, final String replacement) { 6440 return RegExUtils.replaceAll(text, regex, replacement); 6441 } 6442 6443 /** 6444 * Replaces all occurrences of a character in a String with another. 6445 * This is a null-safe version of {@link String#replace(char, char)}. 6446 * 6447 * <p>A {@code null} string input returns {@code null}. 6448 * An empty ("") string input returns an empty string.</p> 6449 * 6450 * <pre> 6451 * StringUtils.replaceChars(null, *, *) = null 6452 * StringUtils.replaceChars("", *, *) = "" 6453 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6454 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6455 * </pre> 6456 * 6457 * @param str String to replace characters in, may be null 6458 * @param searchChar the character to search for, may be null 6459 * @param replaceChar the character to replace, may be null 6460 * @return modified String, {@code null} if null string input 6461 * @since 2.0 6462 */ 6463 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6464 if (str == null) { 6465 return null; 6466 } 6467 return str.replace(searchChar, replaceChar); 6468 } 6469 6470 /** 6471 * Replaces multiple characters in a String in one go. 6472 * This method can also be used to delete characters. 6473 * 6474 * <p>For example:<br> 6475 * {@code replaceChars("hello", "ho", "jy") = jelly}.</p> 6476 * 6477 * <p>A {@code null} string input returns {@code null}. 6478 * An empty ("") string input returns an empty string. 6479 * A null or empty set of search characters returns the input string.</p> 6480 * 6481 * <p>The length of the search characters should normally equal the length 6482 * of the replace characters. 6483 * If the search characters is longer, then the extra search characters 6484 * are deleted. 6485 * If the search characters is shorter, then the extra replace characters 6486 * are ignored.</p> 6487 * 6488 * <pre> 6489 * StringUtils.replaceChars(null, *, *) = null 6490 * StringUtils.replaceChars("", *, *) = "" 6491 * StringUtils.replaceChars("abc", null, *) = "abc" 6492 * StringUtils.replaceChars("abc", "", *) = "abc" 6493 * StringUtils.replaceChars("abc", "b", null) = "ac" 6494 * StringUtils.replaceChars("abc", "b", "") = "ac" 6495 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6496 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6497 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6498 * </pre> 6499 * 6500 * @param str String to replace characters in, may be null 6501 * @param searchChars a set of characters to search for, may be null 6502 * @param replaceChars a set of characters to replace, may be null 6503 * @return modified String, {@code null} if null string input 6504 * @since 2.0 6505 */ 6506 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6507 if (isEmpty(str) || isEmpty(searchChars)) { 6508 return str; 6509 } 6510 if (replaceChars == null) { 6511 replaceChars = EMPTY; 6512 } 6513 boolean modified = false; 6514 final int replaceCharsLength = replaceChars.length(); 6515 final int strLength = str.length(); 6516 final StringBuilder buf = new StringBuilder(strLength); 6517 for (int i = 0; i < strLength; i++) { 6518 final char ch = str.charAt(i); 6519 final int index = searchChars.indexOf(ch); 6520 if (index >= 0) { 6521 modified = true; 6522 if (index < replaceCharsLength) { 6523 buf.append(replaceChars.charAt(index)); 6524 } 6525 } else { 6526 buf.append(ch); 6527 } 6528 } 6529 if (modified) { 6530 return buf.toString(); 6531 } 6532 return str; 6533 } 6534 6535 /** 6536 * Replaces all occurrences of Strings within another String. 6537 * 6538 * <p> 6539 * A {@code null} reference passed to this method is a no-op, or if 6540 * any "search string" or "string to replace" is null, that replace will be 6541 * ignored. This will not repeat. For repeating replaces, call the 6542 * overloaded method. 6543 * </p> 6544 * 6545 * <pre> 6546 * StringUtils.replaceEach(null, *, *) = null 6547 * StringUtils.replaceEach("", *, *) = "" 6548 * StringUtils.replaceEach("aba", null, null) = "aba" 6549 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6550 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6551 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6552 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6553 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6554 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6555 * (example of how it does not repeat) 6556 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6557 * </pre> 6558 * 6559 * @param text 6560 * text to search and replace in, no-op if null 6561 * @param searchList 6562 * the Strings to search for, no-op if null 6563 * @param replacementList 6564 * the Strings to replace them with, no-op if null 6565 * @return the text with any replacements processed, {@code null} if 6566 * null String input 6567 * @throws IllegalArgumentException 6568 * if the lengths of the arrays are not the same (null is ok, 6569 * and/or size 0) 6570 * @since 2.4 6571 */ 6572 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6573 return replaceEach(text, searchList, replacementList, false, 0); 6574 } 6575 6576 /** 6577 * Replace all occurrences of Strings within another String. 6578 * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and 6579 * {@link #replaceEach(String, String[], String[])} 6580 * 6581 * <p> 6582 * A {@code null} reference passed to this method is a no-op, or if 6583 * any "search string" or "string to replace" is null, that replace will be 6584 * ignored. 6585 * </p> 6586 * 6587 * <pre> 6588 * StringUtils.replaceEach(null, *, *, *, *) = null 6589 * StringUtils.replaceEach("", *, *, *, *) = "" 6590 * StringUtils.replaceEach("aba", null, null, *, *) = "aba" 6591 * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba" 6592 * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba" 6593 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba" 6594 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b" 6595 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba" 6596 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte" 6597 * (example of how it repeats) 6598 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte" 6599 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte" 6600 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException 6601 * </pre> 6602 * 6603 * @param text 6604 * text to search and replace in, no-op if null 6605 * @param searchList 6606 * the Strings to search for, no-op if null 6607 * @param replacementList 6608 * the Strings to replace them with, no-op if null 6609 * @param repeat if true, then replace repeatedly 6610 * until there are no more possible replacements or timeToLive < 0 6611 * @param timeToLive 6612 * if less than 0 then there is a circular reference and endless 6613 * loop 6614 * @return the text with any replacements processed, {@code null} if 6615 * null String input 6616 * @throws IllegalStateException 6617 * if the search is repeating and there is an endless loop due 6618 * to outputs of one being inputs to another 6619 * @throws IllegalArgumentException 6620 * if the lengths of the arrays are not the same (null is ok, 6621 * and/or size 0) 6622 * @since 2.4 6623 */ 6624 private static String replaceEach( 6625 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 6626 6627 // mchyzer Performance note: This creates very few new objects (one major goal) 6628 // let me know if there are performance requests, we can create a harness to measure 6629 6630 // if recursing, this shouldn't be less than 0 6631 if (timeToLive < 0) { 6632 final Set<String> searchSet = new HashSet<>(Arrays.asList(searchList)); 6633 final Set<String> replacementSet = new HashSet<>(Arrays.asList(replacementList)); 6634 searchSet.retainAll(replacementSet); 6635 if (!searchSet.isEmpty()) { 6636 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6637 "output of one loop is the input of another"); 6638 } 6639 } 6640 6641 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList) || ArrayUtils.isNotEmpty(searchList) && timeToLive == -1) { 6642 return text; 6643 } 6644 6645 final int searchLength = searchList.length; 6646 final int replacementLength = replacementList.length; 6647 6648 // make sure lengths are ok, these need to be equal 6649 if (searchLength != replacementLength) { 6650 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6651 + searchLength 6652 + " vs " 6653 + replacementLength); 6654 } 6655 6656 // keep track of which still have matches 6657 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6658 6659 // index on index that the match was found 6660 int textIndex = -1; 6661 int replaceIndex = -1; 6662 int tempIndex; 6663 6664 // index of replace array that will replace the search string found 6665 // NOTE: logic duplicated below START 6666 for (int i = 0; i < searchLength; i++) { 6667 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6668 continue; 6669 } 6670 tempIndex = text.indexOf(searchList[i]); 6671 6672 // see if we need to keep searching for this 6673 if (tempIndex == -1) { 6674 noMoreMatchesForReplIndex[i] = true; 6675 } else if (textIndex == -1 || tempIndex < textIndex) { 6676 textIndex = tempIndex; 6677 replaceIndex = i; 6678 } 6679 } 6680 // NOTE: logic mostly below END 6681 6682 // no search strings found, we are done 6683 if (textIndex == -1) { 6684 return text; 6685 } 6686 6687 int start = 0; 6688 6689 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6690 int increase = 0; 6691 6692 // count the replacement text elements that are larger than their corresponding text being replaced 6693 for (int i = 0; i < searchList.length; i++) { 6694 if (searchList[i] == null || replacementList[i] == null) { 6695 continue; 6696 } 6697 final int greater = replacementList[i].length() - searchList[i].length(); 6698 if (greater > 0) { 6699 increase += 3 * greater; // assume 3 matches 6700 } 6701 } 6702 // have upper-bound at 20% increase, then let Java take over 6703 increase = Math.min(increase, text.length() / 5); 6704 6705 final StringBuilder buf = new StringBuilder(text.length() + increase); 6706 6707 while (textIndex != -1) { 6708 6709 for (int i = start; i < textIndex; i++) { 6710 buf.append(text.charAt(i)); 6711 } 6712 buf.append(replacementList[replaceIndex]); 6713 6714 start = textIndex + searchList[replaceIndex].length(); 6715 6716 textIndex = -1; 6717 replaceIndex = -1; 6718 // find the next earliest match 6719 // NOTE: logic mostly duplicated above START 6720 for (int i = 0; i < searchLength; i++) { 6721 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6722 continue; 6723 } 6724 tempIndex = text.indexOf(searchList[i], start); 6725 6726 // see if we need to keep searching for this 6727 if (tempIndex == -1) { 6728 noMoreMatchesForReplIndex[i] = true; 6729 } else if (textIndex == -1 || tempIndex < textIndex) { 6730 textIndex = tempIndex; 6731 replaceIndex = i; 6732 } 6733 } 6734 // NOTE: logic duplicated above END 6735 6736 } 6737 final int textLength = text.length(); 6738 for (int i = start; i < textLength; i++) { 6739 buf.append(text.charAt(i)); 6740 } 6741 final String result = buf.toString(); 6742 if (!repeat) { 6743 return result; 6744 } 6745 6746 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6747 } 6748 6749 /** 6750 * Replaces all occurrences of Strings within another String. 6751 * 6752 * <p> 6753 * A {@code null} reference passed to this method is a no-op, or if 6754 * any "search string" or "string to replace" is null, that replace will be 6755 * ignored. 6756 * </p> 6757 * 6758 * <pre> 6759 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6760 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6761 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6762 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6763 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6764 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6765 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6766 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6767 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6768 * (example of how it repeats) 6769 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6770 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException 6771 * </pre> 6772 * 6773 * @param text 6774 * text to search and replace in, no-op if null 6775 * @param searchList 6776 * the Strings to search for, no-op if null 6777 * @param replacementList 6778 * the Strings to replace them with, no-op if null 6779 * @return the text with any replacements processed, {@code null} if 6780 * null String input 6781 * @throws IllegalStateException 6782 * if the search is repeating and there is an endless loop due 6783 * to outputs of one being inputs to another 6784 * @throws IllegalArgumentException 6785 * if the lengths of the arrays are not the same (null is ok, 6786 * and/or size 0) 6787 * @since 2.4 6788 */ 6789 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6790 return replaceEach(text, searchList, replacementList, true, ArrayUtils.getLength(searchList)); 6791 } 6792 6793 /** 6794 * Replaces the first substring of the text string that matches the given regular expression 6795 * with the given replacement. 6796 * 6797 * This method is a {@code null} safe equivalent to: 6798 * <ul> 6799 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6800 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6801 * </ul> 6802 * 6803 * <p>A {@code null} reference passed to this method is a no-op.</p> 6804 * 6805 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 6806 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 6807 * DOTALL is also known as single-line mode in Perl.</p> 6808 * 6809 * <pre> 6810 * StringUtils.replaceFirst(null, *, *) = null 6811 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6812 * StringUtils.replaceFirst("any", *, null) = "any" 6813 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6814 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6815 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6816 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6817 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6818 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6819 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6820 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6821 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6822 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6823 * </pre> 6824 * 6825 * @param text text to search and replace in, may be null 6826 * @param regex the regular expression to which this string is to be matched 6827 * @param replacement the string to be substituted for the first match 6828 * @return the text with the first replacement processed, 6829 * {@code null} if null String input 6830 * 6831 * @throws java.util.regex.PatternSyntaxException 6832 * if the regular expression's syntax is invalid 6833 * 6834 * @see String#replaceFirst(String, String) 6835 * @see java.util.regex.Pattern 6836 * @see java.util.regex.Pattern#DOTALL 6837 * @since 3.5 6838 * 6839 * @deprecated Moved to RegExUtils. 6840 */ 6841 @Deprecated 6842 public static String replaceFirst(final String text, final String regex, final String replacement) { 6843 return RegExUtils.replaceFirst(text, regex, replacement); 6844 } 6845 6846 /** 6847 * Case insensitively replaces all occurrences of a String within another String. 6848 * 6849 * <p>A {@code null} reference passed to this method is a no-op.</p> 6850 * 6851 * <pre> 6852 * StringUtils.replaceIgnoreCase(null, *, *) = null 6853 * StringUtils.replaceIgnoreCase("", *, *) = "" 6854 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6855 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6856 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6857 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6858 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6859 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6860 * </pre> 6861 * 6862 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6863 * @param text text to search and replace in, may be null 6864 * @param searchString the String to search for (case-insensitive), may be null 6865 * @param replacement the String to replace it with, may be null 6866 * @return the text with any replacements processed, 6867 * {@code null} if null String input 6868 * @since 3.5 6869 */ 6870 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6871 return replaceIgnoreCase(text, searchString, replacement, -1); 6872 } 6873 6874 /** 6875 * Case insensitively replaces a String with another String inside a larger String, 6876 * for the first {@code max} values of the search String. 6877 * 6878 * <p>A {@code null} reference passed to this method is a no-op.</p> 6879 * 6880 * <pre> 6881 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6882 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6883 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6884 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6885 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6886 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6887 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6888 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6889 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6890 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6891 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6892 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6893 * </pre> 6894 * 6895 * @param text text to search and replace in, may be null 6896 * @param searchString the String to search for (case-insensitive), may be null 6897 * @param replacement the String to replace it with, may be null 6898 * @param max maximum number of values to replace, or {@code -1} if no maximum 6899 * @return the text with any replacements processed, 6900 * {@code null} if null String input 6901 * @since 3.5 6902 */ 6903 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6904 return replace(text, searchString, replacement, max, true); 6905 } 6906 6907 /** 6908 * Replaces a String with another String inside a larger String, once. 6909 * 6910 * <p>A {@code null} reference passed to this method is a no-op.</p> 6911 * 6912 * <pre> 6913 * StringUtils.replaceOnce(null, *, *) = null 6914 * StringUtils.replaceOnce("", *, *) = "" 6915 * StringUtils.replaceOnce("any", null, *) = "any" 6916 * StringUtils.replaceOnce("any", *, null) = "any" 6917 * StringUtils.replaceOnce("any", "", *) = "any" 6918 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6919 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6920 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6921 * </pre> 6922 * 6923 * @see #replace(String text, String searchString, String replacement, int max) 6924 * @param text text to search and replace in, may be null 6925 * @param searchString the String to search for, may be null 6926 * @param replacement the String to replace with, may be null 6927 * @return the text with any replacements processed, 6928 * {@code null} if null String input 6929 */ 6930 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6931 return replace(text, searchString, replacement, 1); 6932 } 6933 6934 /** 6935 * Case insensitively replaces a String with another String inside a larger String, once. 6936 * 6937 * <p>A {@code null} reference passed to this method is a no-op.</p> 6938 * 6939 * <pre> 6940 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6941 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6942 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6943 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6944 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6945 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6946 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6947 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6948 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6949 * </pre> 6950 * 6951 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6952 * @param text text to search and replace in, may be null 6953 * @param searchString the String to search for (case-insensitive), may be null 6954 * @param replacement the String to replace with, may be null 6955 * @return the text with any replacements processed, 6956 * {@code null} if null String input 6957 * @since 3.5 6958 */ 6959 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6960 return replaceIgnoreCase(text, searchString, replacement, 1); 6961 } 6962 6963 /** 6964 * Replaces each substring of the source String that matches the given regular expression with the given 6965 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl. 6966 * 6967 * This call is a {@code null} safe equivalent to: 6968 * <ul> 6969 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6970 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6971 * </ul> 6972 * 6973 * <p>A {@code null} reference passed to this method is a no-op.</p> 6974 * 6975 * <pre> 6976 * StringUtils.replacePattern(null, *, *) = null 6977 * StringUtils.replacePattern("any", (String) null, *) = "any" 6978 * StringUtils.replacePattern("any", *, null) = "any" 6979 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6980 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6981 * StringUtils.replacePattern("", ".+", "zzz") = "" 6982 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6983 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6984 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6985 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6986 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6987 * </pre> 6988 * 6989 * @param source 6990 * the source string 6991 * @param regex 6992 * the regular expression to which this string is to be matched 6993 * @param replacement 6994 * the string to be substituted for each match 6995 * @return The resulting {@link String} 6996 * @see #replaceAll(String, String, String) 6997 * @see String#replaceAll(String, String) 6998 * @see Pattern#DOTALL 6999 * @since 3.2 7000 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 7001 * 7002 * @deprecated Moved to RegExUtils. 7003 */ 7004 @Deprecated 7005 public static String replacePattern(final String source, final String regex, final String replacement) { 7006 return RegExUtils.replacePattern(source, regex, replacement); 7007 } 7008 7009 /** 7010 * Reverses a String as per {@link StringBuilder#reverse()}. 7011 * 7012 * <p>A {@code null} String returns {@code null}.</p> 7013 * 7014 * <pre> 7015 * StringUtils.reverse(null) = null 7016 * StringUtils.reverse("") = "" 7017 * StringUtils.reverse("bat") = "tab" 7018 * </pre> 7019 * 7020 * @param str the String to reverse, may be null 7021 * @return the reversed String, {@code null} if null String input 7022 */ 7023 public static String reverse(final String str) { 7024 if (str == null) { 7025 return null; 7026 } 7027 return new StringBuilder(str).reverse().toString(); 7028 } 7029 7030 /** 7031 * Reverses a String that is delimited by a specific character. 7032 * 7033 * <p>The Strings between the delimiters are not reversed. 7034 * Thus java.lang.String becomes String.lang.java (if the delimiter 7035 * is {@code '.'}).</p> 7036 * 7037 * <pre> 7038 * StringUtils.reverseDelimited(null, *) = null 7039 * StringUtils.reverseDelimited("", *) = "" 7040 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 7041 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 7042 * </pre> 7043 * 7044 * @param str the String to reverse, may be null 7045 * @param separatorChar the separator character to use 7046 * @return the reversed String, {@code null} if null String input 7047 * @since 2.0 7048 */ 7049 public static String reverseDelimited(final String str, final char separatorChar) { 7050 if (str == null) { 7051 return null; 7052 } 7053 // could implement manually, but simple way is to reuse other, 7054 // probably slower, methods. 7055 final String[] strs = split(str, separatorChar); 7056 ArrayUtils.reverse(strs); 7057 return join(strs, separatorChar); 7058 } 7059 7060 /** 7061 * Gets the rightmost {@code len} characters of a String. 7062 * 7063 * <p>If {@code len} characters are not available, or the String 7064 * is {@code null}, the String will be returned without an 7065 * an exception. An empty String is returned if len is negative.</p> 7066 * 7067 * <pre> 7068 * StringUtils.right(null, *) = null 7069 * StringUtils.right(*, -ve) = "" 7070 * StringUtils.right("", *) = "" 7071 * StringUtils.right("abc", 0) = "" 7072 * StringUtils.right("abc", 2) = "bc" 7073 * StringUtils.right("abc", 4) = "abc" 7074 * </pre> 7075 * 7076 * @param str the String to get the rightmost characters from, may be null 7077 * @param len the length of the required String 7078 * @return the rightmost characters, {@code null} if null String input 7079 */ 7080 public static String right(final String str, final int len) { 7081 if (str == null) { 7082 return null; 7083 } 7084 if (len < 0) { 7085 return EMPTY; 7086 } 7087 if (str.length() <= len) { 7088 return str; 7089 } 7090 return str.substring(str.length() - len); 7091 } 7092 7093 /** 7094 * Right pad a String with spaces (' '). 7095 * 7096 * <p>The String is padded to the size of {@code size}.</p> 7097 * 7098 * <pre> 7099 * StringUtils.rightPad(null, *) = null 7100 * StringUtils.rightPad("", 3) = " " 7101 * StringUtils.rightPad("bat", 3) = "bat" 7102 * StringUtils.rightPad("bat", 5) = "bat " 7103 * StringUtils.rightPad("bat", 1) = "bat" 7104 * StringUtils.rightPad("bat", -1) = "bat" 7105 * </pre> 7106 * 7107 * @param str the String to pad out, may be null 7108 * @param size the size to pad to 7109 * @return right padded String or original String if no padding is necessary, 7110 * {@code null} if null String input 7111 */ 7112 public static String rightPad(final String str, final int size) { 7113 return rightPad(str, size, ' '); 7114 } 7115 7116 /** 7117 * Right pad a String with a specified character. 7118 * 7119 * <p>The String is padded to the size of {@code size}.</p> 7120 * 7121 * <pre> 7122 * StringUtils.rightPad(null, *, *) = null 7123 * StringUtils.rightPad("", 3, 'z') = "zzz" 7124 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7125 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7126 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7127 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7128 * </pre> 7129 * 7130 * @param str the String to pad out, may be null 7131 * @param size the size to pad to 7132 * @param padChar the character to pad with 7133 * @return right padded String or original String if no padding is necessary, 7134 * {@code null} if null String input 7135 * @since 2.0 7136 */ 7137 public static String rightPad(final String str, final int size, final char padChar) { 7138 if (str == null) { 7139 return null; 7140 } 7141 final int pads = size - str.length(); 7142 if (pads <= 0) { 7143 return str; // returns original String when possible 7144 } 7145 if (pads > PAD_LIMIT) { 7146 return rightPad(str, size, String.valueOf(padChar)); 7147 } 7148 return str.concat(repeat(padChar, pads)); 7149 } 7150 7151 /** 7152 * Right pad a String with a specified String. 7153 * 7154 * <p>The String is padded to the size of {@code size}.</p> 7155 * 7156 * <pre> 7157 * StringUtils.rightPad(null, *, *) = null 7158 * StringUtils.rightPad("", 3, "z") = "zzz" 7159 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7160 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7161 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7162 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7163 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7164 * StringUtils.rightPad("bat", 5, null) = "bat " 7165 * StringUtils.rightPad("bat", 5, "") = "bat " 7166 * </pre> 7167 * 7168 * @param str the String to pad out, may be null 7169 * @param size the size to pad to 7170 * @param padStr the String to pad with, null or empty treated as single space 7171 * @return right padded String or original String if no padding is necessary, 7172 * {@code null} if null String input 7173 */ 7174 public static String rightPad(final String str, final int size, String padStr) { 7175 if (str == null) { 7176 return null; 7177 } 7178 if (isEmpty(padStr)) { 7179 padStr = SPACE; 7180 } 7181 final int padLen = padStr.length(); 7182 final int strLen = str.length(); 7183 final int pads = size - strLen; 7184 if (pads <= 0) { 7185 return str; // returns original String when possible 7186 } 7187 if (padLen == 1 && pads <= PAD_LIMIT) { 7188 return rightPad(str, size, padStr.charAt(0)); 7189 } 7190 7191 if (pads == padLen) { 7192 return str.concat(padStr); 7193 } 7194 if (pads < padLen) { 7195 return str.concat(padStr.substring(0, pads)); 7196 } 7197 final char[] padding = new char[pads]; 7198 final char[] padChars = padStr.toCharArray(); 7199 for (int i = 0; i < pads; i++) { 7200 padding[i] = padChars[i % padLen]; 7201 } 7202 return str.concat(new String(padding)); 7203 } 7204 7205 /** 7206 * Rotate (circular shift) a String of {@code shift} characters. 7207 * <ul> 7208 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7209 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7210 * </ul> 7211 * 7212 * <pre> 7213 * StringUtils.rotate(null, *) = null 7214 * StringUtils.rotate("", *) = "" 7215 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7216 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7217 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7218 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7219 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7220 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7221 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7222 * </pre> 7223 * 7224 * @param str the String to rotate, may be null 7225 * @param shift number of time to shift (positive : right shift, negative : left shift) 7226 * @return the rotated String, 7227 * or the original String if {@code shift == 0}, 7228 * or {@code null} if null String input 7229 * @since 3.5 7230 */ 7231 public static String rotate(final String str, final int shift) { 7232 if (str == null) { 7233 return null; 7234 } 7235 7236 final int strLen = str.length(); 7237 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7238 return str; 7239 } 7240 7241 final StringBuilder builder = new StringBuilder(strLen); 7242 final int offset = - (shift % strLen); 7243 builder.append(substring(str, offset)); 7244 builder.append(substring(str, 0, offset)); 7245 return builder.toString(); 7246 } 7247 7248 /** 7249 * Splits the provided text into an array, using whitespace as the 7250 * separator. 7251 * Whitespace is defined by {@link Character#isWhitespace(char)}. 7252 * 7253 * <p>The separator is not included in the returned String array. 7254 * Adjacent separators are treated as one separator. 7255 * For more control over the split use the StrTokenizer class.</p> 7256 * 7257 * <p>A {@code null} input String returns {@code null}.</p> 7258 * 7259 * <pre> 7260 * StringUtils.split(null) = null 7261 * StringUtils.split("") = [] 7262 * StringUtils.split("abc def") = ["abc", "def"] 7263 * StringUtils.split("abc def") = ["abc", "def"] 7264 * StringUtils.split(" abc ") = ["abc"] 7265 * </pre> 7266 * 7267 * @param str the String to parse, may be null 7268 * @return an array of parsed Strings, {@code null} if null String input 7269 */ 7270 public static String[] split(final String str) { 7271 return split(str, null, -1); 7272 } 7273 7274 /** 7275 * Splits the provided text into an array, separator specified. 7276 * This is an alternative to using StringTokenizer. 7277 * 7278 * <p>The separator is not included in the returned String array. 7279 * Adjacent separators are treated as one separator. 7280 * For more control over the split use the StrTokenizer class.</p> 7281 * 7282 * <p>A {@code null} input String returns {@code null}.</p> 7283 * 7284 * <pre> 7285 * StringUtils.split(null, *) = null 7286 * StringUtils.split("", *) = [] 7287 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7288 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7289 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7290 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7291 * </pre> 7292 * 7293 * @param str the String to parse, may be null 7294 * @param separatorChar the character used as the delimiter 7295 * @return an array of parsed Strings, {@code null} if null String input 7296 * @since 2.0 7297 */ 7298 public static String[] split(final String str, final char separatorChar) { 7299 return splitWorker(str, separatorChar, false); 7300 } 7301 7302 /** 7303 * Splits the provided text into an array, separators specified. 7304 * This is an alternative to using StringTokenizer. 7305 * 7306 * <p>The separator is not included in the returned String array. 7307 * Adjacent separators are treated as one separator. 7308 * For more control over the split use the StrTokenizer class.</p> 7309 * 7310 * <p>A {@code null} input String returns {@code null}. 7311 * A {@code null} separatorChars splits on whitespace.</p> 7312 * 7313 * <pre> 7314 * StringUtils.split(null, *) = null 7315 * StringUtils.split("", *) = [] 7316 * StringUtils.split("abc def", null) = ["abc", "def"] 7317 * StringUtils.split("abc def", " ") = ["abc", "def"] 7318 * StringUtils.split("abc def", " ") = ["abc", "def"] 7319 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7320 * </pre> 7321 * 7322 * @param str the String to parse, may be null 7323 * @param separatorChars the characters used as the delimiters, 7324 * {@code null} splits on whitespace 7325 * @return an array of parsed Strings, {@code null} if null String input 7326 */ 7327 public static String[] split(final String str, final String separatorChars) { 7328 return splitWorker(str, separatorChars, -1, false); 7329 } 7330 7331 /** 7332 * Splits the provided text into an array with a maximum length, 7333 * separators specified. 7334 * 7335 * <p>The separator is not included in the returned String array. 7336 * Adjacent separators are treated as one separator.</p> 7337 * 7338 * <p>A {@code null} input String returns {@code null}. 7339 * A {@code null} separatorChars splits on whitespace.</p> 7340 * 7341 * <p>If more than {@code max} delimited substrings are found, the last 7342 * returned string includes all characters after the first {@code max - 1} 7343 * returned strings (including separator characters).</p> 7344 * 7345 * <pre> 7346 * StringUtils.split(null, *, *) = null 7347 * StringUtils.split("", *, *) = [] 7348 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7349 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7350 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7351 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7352 * </pre> 7353 * 7354 * @param str the String to parse, may be null 7355 * @param separatorChars the characters used as the delimiters, 7356 * {@code null} splits on whitespace 7357 * @param max the maximum number of elements to include in the 7358 * array. A zero or negative value implies no limit 7359 * @return an array of parsed Strings, {@code null} if null String input 7360 */ 7361 public static String[] split(final String str, final String separatorChars, final int max) { 7362 return splitWorker(str, separatorChars, max, false); 7363 } 7364 7365 /** 7366 * Splits a String by Character type as returned by 7367 * {@code java.lang.Character.getType(char)}. Groups of contiguous 7368 * characters of the same type are returned as complete tokens. 7369 * <pre> 7370 * StringUtils.splitByCharacterType(null) = null 7371 * StringUtils.splitByCharacterType("") = [] 7372 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7373 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7374 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7375 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7376 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7377 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200"