1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.lang3; 18 19 import java.io.UnsupportedEncodingException; 20 import java.nio.CharBuffer; 21 import java.nio.charset.Charset; 22 import java.text.Normalizer; 23 import java.util.ArrayList; 24 import java.util.Arrays; 25 import java.util.Iterator; 26 import java.util.List; 27 import java.util.Locale; 28 import java.util.Objects; 29 import java.util.Set; 30 import java.util.function.Supplier; 31 import java.util.regex.Pattern; 32 import java.util.stream.Collectors; 33 34 import org.apache.commons.lang3.function.Suppliers; 35 import org.apache.commons.lang3.stream.LangCollectors; 36 import org.apache.commons.lang3.stream.Streams; 37 38 /** 39 * Operations on {@link String} that are 40 * {@code null} safe. 41 * 42 * <ul> 43 * <li><strong>IsEmpty/IsBlank</strong> 44 * - checks if a String contains text</li> 45 * <li><strong>Trim/Strip</strong> 46 * - removes leading and trailing whitespace</li> 47 * <li><strong>Equals/Compare</strong> 48 * - compares two strings in a null-safe manner</li> 49 * <li><strong>startsWith</strong> 50 * - check if a String starts with a prefix in a null-safe manner</li> 51 * <li><strong>endsWith</strong> 52 * - check if a String ends with a suffix in a null-safe manner</li> 53 * <li><strong>IndexOf/LastIndexOf/Contains</strong> 54 * - null-safe index-of checks 55 * <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong> 56 * - index-of any of a set of Strings</li> 57 * <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong> 58 * - checks if String contains only/none/any of these characters</li> 59 * <li><strong>Substring/Left/Right/Mid</strong> 60 * - null-safe substring extractions</li> 61 * <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong> 62 * - substring extraction relative to other strings</li> 63 * <li><strong>Split/Join</strong> 64 * - splits a String into an array of substrings and vice versa</li> 65 * <li><strong>Remove/Delete</strong> 66 * - removes part of a String</li> 67 * <li><strong>Replace/Overlay</strong> 68 * - Searches a String and replaces one String with another</li> 69 * <li><strong>Chomp/Chop</strong> 70 * - removes the last part of a String</li> 71 * <li><strong>AppendIfMissing</strong> 72 * - appends a suffix to the end of the String if not present</li> 73 * <li><strong>PrependIfMissing</strong> 74 * - prepends a prefix to the start of the String if not present</li> 75 * <li><strong>LeftPad/RightPad/Center/Repeat</strong> 76 * - pads a String</li> 77 * <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong> 78 * - changes the case of a String</li> 79 * <li><strong>CountMatches</strong> 80 * - counts the number of occurrences of one String in another</li> 81 * <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong> 82 * - checks the characters in a String</li> 83 * <li><strong>DefaultString</strong> 84 * - protects against a null input String</li> 85 * <li><strong>Rotate</strong> 86 * - rotate (circular shift) a String</li> 87 * <li><strong>Reverse/ReverseDelimited</strong> 88 * - reverses a String</li> 89 * <li><strong>Abbreviate</strong> 90 * - abbreviates a string using ellipses or another given String</li> 91 * <li><strong>Difference</strong> 92 * - compares Strings and reports on their differences</li> 93 * <li><strong>LevenshteinDistance</strong> 94 * - the number of changes needed to change one String into another</li> 95 * </ul> 96 * 97 * <p>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 * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 ⦠this isn't it. 145 */ 146 private static final String ELLIPSIS3 = "..."; 147 148 /** 149 * A String for a space character. 150 * 151 * @since 3.2 152 */ 153 public static final String SPACE = " "; 154 155 /** 156 * The empty String {@code ""}. 157 * @since 2.0 158 */ 159 public static final String EMPTY = ""; 160 161 /** 162 * The null String {@code null}. Package-private only. 163 */ 164 static final String NULL = null; 165 166 /** 167 * A String for linefeed LF ("\n"). 168 * 169 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 170 * for Character and String Literals</a> 171 * @since 3.2 172 */ 173 public static final String LF = "\n"; 174 175 /** 176 * A String for carriage return CR ("\r"). 177 * 178 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 179 * for Character and String Literals</a> 180 * @since 3.2 181 */ 182 public static final String CR = "\r"; 183 184 /** 185 * Represents a failed index search. 186 * @since 2.1 187 */ 188 public static final int INDEX_NOT_FOUND = -1; 189 190 /** 191 * The maximum size to which the padding constant(s) can expand. 192 */ 193 private static final int PAD_LIMIT = 8192; 194 195 /** 196 * The default maximum depth at which recursive replacement will continue until no further search replacements are possible. 197 */ 198 private static final int DEFAULT_TTL = 5; 199 200 /** 201 * Pattern used in {@link #stripAccents(String)}. 202 */ 203 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 204 205 /** 206 * Abbreviates a String using ellipses. This will turn 207 * "Now is the time for all good men" into "Now is the time for..." 208 * 209 * <p>Specifically:</p> 210 * <ul> 211 * <li>If the number of characters in {@code str} is less than or equal to 212 * {@code maxWidth}, return {@code str}.</li> 213 * <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li> 214 * <li>If {@code maxWidth} is less than {@code 4}, throw an 215 * {@link IllegalArgumentException}.</li> 216 * <li>In no case will it return a String of length greater than 217 * {@code maxWidth}.</li> 218 * </ul> 219 * 220 * <pre> 221 * StringUtils.abbreviate(null, *) = null 222 * StringUtils.abbreviate("", 4) = "" 223 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 224 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 225 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 226 * StringUtils.abbreviate("abcdefg", 4) = "a..." 227 * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException 228 * </pre> 229 * 230 * @param str the String to check, may be null. 231 * @param maxWidth maximum length of result String, must be at least 4. 232 * @return abbreviated String, {@code null} if null String input. 233 * @throws IllegalArgumentException if the width is too small. 234 * @since 2.0 235 */ 236 public static String abbreviate(final String str, final int maxWidth) { 237 return abbreviate(str, ELLIPSIS3, 0, maxWidth); 238 } 239 240 /** 241 * Abbreviates a String using ellipses. This will turn "Now is the time for all good men" into "...is the time for..." 242 * 243 * <p> 244 * Works like {@code abbreviate(String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to be the 245 * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result. 246 * 247 * <p> 248 * In no case will it return a String of length greater than {@code maxWidth}. 249 * </p> 250 * 251 * <pre> 252 * StringUtils.abbreviate(null, *, *) = null 253 * StringUtils.abbreviate("", 0, 4) = "" 254 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 255 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 256 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 257 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 258 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 259 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 260 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 261 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 262 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 263 * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 264 * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 265 * </pre> 266 * 267 * @param str the String to check, may be null. 268 * @param offset left edge of source String. 269 * @param maxWidth maximum length of result String, must be at least 4. 270 * @return abbreviated String, {@code null} if null String input. 271 * @throws IllegalArgumentException if the width is too small. 272 * @since 2.0 273 */ 274 public static String abbreviate(final String str, final int offset, final int maxWidth) { 275 return abbreviate(str, ELLIPSIS3, offset, maxWidth); 276 } 277 278 /** 279 * Abbreviates a String using another given String as replacement marker. This will turn "Now is the time for all good men" into "Now is the time for..." if 280 * "..." was defined as the replacement marker. 281 * 282 * <p> 283 * Specifically: 284 * </p> 285 * <ul> 286 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 287 * <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li> 288 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li> 289 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 290 * </ul> 291 * 292 * <pre> 293 * StringUtils.abbreviate(null, "...", *) = null 294 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 295 * StringUtils.abbreviate("", "...", 4) = "" 296 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 297 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 298 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 299 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 300 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 301 * StringUtils.abbreviate("abcdefg", "..", 2) = IllegalArgumentException 302 * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException 303 * </pre> 304 * 305 * @param str the String to check, may be null. 306 * @param abbrevMarker the String used as replacement marker. 307 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}. 308 * @return abbreviated String, {@code null} if null String input. 309 * @throws IllegalArgumentException if the width is too small. 310 * @since 3.6 311 */ 312 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 313 return abbreviate(str, abbrevMarker, 0, maxWidth); 314 } 315 316 /** 317 * Abbreviates a String using a given replacement marker. This will turn "Now is the time for all good men" into "...is the time for..." if "..." was 318 * defined as the replacement marker. 319 * 320 * <p> 321 * Works like {@code abbreviate(String, String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to 322 * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result. 323 * 324 * <p> 325 * In no case will it return a String of length greater than {@code maxWidth}. 326 * </p> 327 * 328 * <pre> 329 * StringUtils.abbreviate(null, null, *, *) = null 330 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 331 * StringUtils.abbreviate("", "...", 0, 4) = "" 332 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 333 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 334 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 335 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 336 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 337 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 338 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 339 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 340 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 341 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = IllegalArgumentException 342 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = IllegalArgumentException 343 * </pre> 344 * 345 * @param str the String to check, may be null. 346 * @param abbrevMarker the String used as replacement marker. 347 * @param offset left edge of source String. 348 * @param maxWidth maximum length of result String, must be at least 4. 349 * @return abbreviated String, {@code null} if null String input. 350 * @throws IllegalArgumentException if the width is too small. 351 * @since 3.6 352 */ 353 public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) { 354 if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) { 355 return substring(str, 0, maxWidth); 356 } 357 if (isAnyEmpty(str, abbrevMarker)) { 358 return str; 359 } 360 final int abbrevMarkerLength = abbrevMarker.length(); 361 final int minAbbrevWidth = abbrevMarkerLength + 1; 362 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 363 364 if (maxWidth < minAbbrevWidth) { 365 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 366 } 367 final int strLen = str.length(); 368 if (strLen <= maxWidth) { 369 return str; 370 } 371 if (offset > strLen) { 372 offset = strLen; 373 } 374 if (strLen - offset < maxWidth - abbrevMarkerLength) { 375 offset = strLen - (maxWidth - abbrevMarkerLength); 376 } 377 if (offset <= abbrevMarkerLength + 1) { 378 return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker; 379 } 380 if (maxWidth < minAbbrevWidthOffset) { 381 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 382 } 383 if (offset + maxWidth - abbrevMarkerLength < strLen) { 384 return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength); 385 } 386 return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength)); 387 } 388 389 /** 390 * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String. 391 * 392 * <p> 393 * This abbreviation only occurs if the following criteria is met: 394 * </p> 395 * <ul> 396 * <li>Neither the String for abbreviation nor the replacement String are null or empty</li> 397 * <li>The length to truncate to is less than the length of the supplied String</li> 398 * <li>The length to truncate to is greater than 0</li> 399 * <li>The abbreviated String will have enough room for the length supplied replacement String and the first and last characters of the supplied String for 400 * abbreviation</li> 401 * </ul> 402 * <p> 403 * Otherwise, the returned String will be the same as the supplied String for abbreviation. 404 * </p> 405 * 406 * <pre> 407 * StringUtils.abbreviateMiddle(null, null, 0) = null 408 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 409 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 410 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 411 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 412 * </pre> 413 * 414 * @param str the String to abbreviate, may be null. 415 * @param middle the String to replace the middle characters with, may be null. 416 * @param length the length to abbreviate {@code str} to. 417 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 418 * @since 2.5 419 */ 420 public static String abbreviateMiddle(final String str, final String middle, final int length) { 421 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) { 422 return str; 423 } 424 final int targetSting = length - middle.length(); 425 final int startOffset = targetSting / 2 + targetSting % 2; 426 final int endOffset = str.length() - targetSting / 2; 427 return str.substring(0, startOffset) + middle + str.substring(endOffset); 428 } 429 430 /** 431 * Appends the suffix to the end of the string if the string does not already end with any of the suffixes. 432 * 433 * <pre> 434 * StringUtils.appendIfMissing(null, null) = null 435 * StringUtils.appendIfMissing("abc", null) = "abc" 436 * StringUtils.appendIfMissing("", "xyz" = "xyz" 437 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 438 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 439 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 440 * </pre> 441 * <p> 442 * With additional suffixes, 443 * </p> 444 * 445 * <pre> 446 * StringUtils.appendIfMissing(null, null, null) = null 447 * StringUtils.appendIfMissing("abc", null, null) = "abc" 448 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 449 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 450 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 451 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 452 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 453 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 454 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 455 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 456 * </pre> 457 * 458 * @param str The string. 459 * @param suffix The suffix to append to the end of the string. 460 * @param suffixes Additional suffixes that are valid terminators. 461 * @return A new String if suffix was appended, the same string otherwise. 462 * @since 3.2 463 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)} 464 */ 465 @Deprecated 466 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 467 return Strings.CS.appendIfMissing(str, suffix, suffixes); 468 } 469 470 /** 471 * Appends the suffix to the end of the string if the string does not 472 * already end, case-insensitive, with any of the suffixes. 473 * 474 * <pre> 475 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 476 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 477 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 478 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 479 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 480 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 481 * </pre> 482 * <p>With additional suffixes,</p> 483 * <pre> 484 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 485 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 486 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 487 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 488 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 489 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 490 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 491 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 492 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 493 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 494 * </pre> 495 * 496 * @param str The string. 497 * @param suffix The suffix to append to the end of the string. 498 * @param suffixes Additional suffixes that are valid terminators. 499 * @return A new String if suffix was appended, the same string otherwise. 500 * @since 3.2 501 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)} 502 */ 503 @Deprecated 504 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 505 return Strings.CI.appendIfMissing(str, suffix, suffixes); 506 } 507 508 /** 509 * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed. 510 * 511 * <p> 512 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}. 513 * </p> 514 * 515 * <pre> 516 * StringUtils.capitalize(null) = null 517 * StringUtils.capitalize("") = "" 518 * StringUtils.capitalize("cat") = "Cat" 519 * StringUtils.capitalize("cAt") = "CAt" 520 * StringUtils.capitalize("'cat'") = "'cat'" 521 * </pre> 522 * 523 * @param str the String to capitalize, may be null. 524 * @return the capitalized String, {@code null} if null String input. 525 * @see org.apache.commons.text.WordUtils#capitalize(String) 526 * @see #uncapitalize(String) 527 * @since 2.0 528 */ 529 public static String capitalize(final String str) { 530 if (isEmpty(str)) { 531 return str; 532 } 533 final int firstCodepoint = str.codePointAt(0); 534 final int newCodePoint = Character.toTitleCase(firstCodepoint); 535 if (firstCodepoint == newCodePoint) { 536 // already capitalized 537 return str; 538 } 539 final int[] newCodePoints = str.codePoints().toArray(); 540 newCodePoints[0] = newCodePoint; // copy the first code point 541 return new String(newCodePoints, 0, newCodePoints.length); 542 } 543 544 /** 545 * Centers a String in a larger String of size {@code size} using the space character (' '). 546 * 547 * <p> 548 * If the size is less than the String length, the original String is returned. A {@code null} String returns {@code null}. A negative size is treated as 549 * zero. 550 * </p> 551 * 552 * <p> 553 * Equivalent to {@code center(str, size, " ")}. 554 * </p> 555 * 556 * <pre> 557 * StringUtils.center(null, *) = null 558 * StringUtils.center("", 4) = " " 559 * StringUtils.center("ab", -1) = "ab" 560 * StringUtils.center("ab", 4) = " ab " 561 * StringUtils.center("abcd", 2) = "abcd" 562 * StringUtils.center("a", 4) = " a " 563 * </pre> 564 * 565 * @param str the String to center, may be null. 566 * @param size the int size of new String, negative treated as zero. 567 * @return centered String, {@code null} if null String input. 568 */ 569 public static String center(final String str, final int size) { 570 return center(str, size, ' '); 571 } 572 573 /** 574 * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with. 575 * 576 * <p> 577 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero. 578 * </p> 579 * 580 * <pre> 581 * StringUtils.center(null, *, *) = null 582 * StringUtils.center("", 4, ' ') = " " 583 * StringUtils.center("ab", -1, ' ') = "ab" 584 * StringUtils.center("ab", 4, ' ') = " ab " 585 * StringUtils.center("abcd", 2, ' ') = "abcd" 586 * StringUtils.center("a", 4, ' ') = " a " 587 * StringUtils.center("a", 4, 'y') = "yayy" 588 * </pre> 589 * 590 * @param str the String to center, may be null. 591 * @param size the int size of new String, negative treated as zero. 592 * @param padChar the character to pad the new String with. 593 * @return centered String, {@code null} if null String input. 594 * @since 2.0 595 */ 596 public static String center(String str, final int size, final char padChar) { 597 if (str == null || size <= 0) { 598 return str; 599 } 600 final int strLen = str.length(); 601 final int pads = size - strLen; 602 if (pads <= 0) { 603 return str; 604 } 605 str = leftPad(str, strLen + pads / 2, padChar); 606 return rightPad(str, size, padChar); 607 } 608 609 /** 610 * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with. 611 * 612 * <p> 613 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero. 614 * </p> 615 * 616 * <pre> 617 * StringUtils.center(null, *, *) = null 618 * StringUtils.center("", 4, " ") = " " 619 * StringUtils.center("ab", -1, " ") = "ab" 620 * StringUtils.center("ab", 4, " ") = " ab " 621 * StringUtils.center("abcd", 2, " ") = "abcd" 622 * StringUtils.center("a", 4, " ") = " a " 623 * StringUtils.center("a", 4, "yz") = "yayz" 624 * StringUtils.center("abc", 7, null) = " abc " 625 * StringUtils.center("abc", 7, "") = " abc " 626 * </pre> 627 * 628 * @param str the String to center, may be null. 629 * @param size the int size of new String, negative treated as zero. 630 * @param padStr the String to pad the new String with, must not be null or empty. 631 * @return centered String, {@code null} if null String input. 632 * @throws IllegalArgumentException if padStr is {@code null} or empty. 633 */ 634 public static String center(String str, final int size, String padStr) { 635 if (str == null || size <= 0) { 636 return str; 637 } 638 if (isEmpty(padStr)) { 639 padStr = SPACE; 640 } 641 final int strLen = str.length(); 642 final int pads = size - strLen; 643 if (pads <= 0) { 644 return str; 645 } 646 str = leftPad(str, strLen + pads / 2, padStr); 647 return rightPad(str, size, padStr); 648 } 649 650 /** 651 * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is "{@code \n}", "{@code \r}", or 652 * "{@code \r\n}". 653 * 654 * <p> 655 * NOTE: This method changed in 2.0. It now more closely matches Perl chomp. 656 * </p> 657 * 658 * <pre> 659 * StringUtils.chomp(null) = null 660 * StringUtils.chomp("") = "" 661 * StringUtils.chomp("abc \r") = "abc " 662 * StringUtils.chomp("abc\n") = "abc" 663 * StringUtils.chomp("abc\r\n") = "abc" 664 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 665 * StringUtils.chomp("abc\n\r") = "abc\n" 666 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 667 * StringUtils.chomp("\r") = "" 668 * StringUtils.chomp("\n") = "" 669 * StringUtils.chomp("\r\n") = "" 670 * </pre> 671 * 672 * @param str the String to chomp a newline from, may be null. 673 * @return String without newline, {@code null} if null String input. 674 */ 675 public static String chomp(final String str) { 676 if (isEmpty(str)) { 677 return str; 678 } 679 if (str.length() == 1) { 680 final char ch = str.charAt(0); 681 if (ch == CharUtils.CR || ch == CharUtils.LF) { 682 return EMPTY; 683 } 684 return str; 685 } 686 int lastIdx = str.length() - 1; 687 final char last = str.charAt(lastIdx); 688 if (last == CharUtils.LF) { 689 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 690 lastIdx--; 691 } 692 } else if (last != CharUtils.CR) { 693 lastIdx++; 694 } 695 return str.substring(0, lastIdx); 696 } 697 698 /** 699 * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone. 700 * 701 * <p> 702 * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use 703 * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}. 704 * </p> 705 * 706 * <pre> 707 * StringUtils.chomp(null, *) = null 708 * StringUtils.chomp("", *) = "" 709 * StringUtils.chomp("foobar", "bar") = "foo" 710 * StringUtils.chomp("foobar", "baz") = "foobar" 711 * StringUtils.chomp("foo", "foo") = "" 712 * StringUtils.chomp("foo ", "foo") = "foo " 713 * StringUtils.chomp(" foo", "foo") = " " 714 * StringUtils.chomp("foo", "foooo") = "foo" 715 * StringUtils.chomp("foo", "") = "foo" 716 * StringUtils.chomp("foo", null) = "foo" 717 * </pre> 718 * 719 * @param str the String to chomp from, may be null. 720 * @param separator separator String, may be null. 721 * @return String without trailing separator, {@code null} if null String input. 722 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead. 723 */ 724 @Deprecated 725 public static String chomp(final String str, final String separator) { 726 return Strings.CS.removeEnd(str, separator); 727 } 728 729 /** 730 * Removes the last character from a String. 731 * 732 * <p> 733 * If the String ends in {@code \r\n}, then remove both of them. 734 * </p> 735 * 736 * <pre> 737 * StringUtils.chop(null) = null 738 * StringUtils.chop("") = "" 739 * StringUtils.chop("abc \r") = "abc " 740 * StringUtils.chop("abc\n") = "abc" 741 * StringUtils.chop("abc\r\n") = "abc" 742 * StringUtils.chop("abc") = "ab" 743 * StringUtils.chop("abc\nabc") = "abc\nab" 744 * StringUtils.chop("a") = "" 745 * StringUtils.chop("\r") = "" 746 * StringUtils.chop("\n") = "" 747 * StringUtils.chop("\r\n") = "" 748 * </pre> 749 * 750 * @param str the String to chop last character from, may be null. 751 * @return String without last character, {@code null} if null String input. 752 */ 753 public static String chop(final String str) { 754 if (str == null) { 755 return null; 756 } 757 final int strLen = str.length(); 758 if (strLen < 2) { 759 return EMPTY; 760 } 761 final int lastIdx = strLen - 1; 762 final String ret = str.substring(0, lastIdx); 763 final char last = str.charAt(lastIdx); 764 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 765 return ret.substring(0, lastIdx - 1); 766 } 767 return ret; 768 } 769 770 /** 771 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 772 * <ul> 773 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 774 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 775 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 776 * </ul> 777 * 778 * <p> 779 * This is a {@code null} safe version of: 780 * </p> 781 * 782 * <pre> 783 * str1.compareTo(str2) 784 * </pre> 785 * 786 * <p> 787 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. 788 * </p> 789 * 790 * <pre>{@code 791 * StringUtils.compare(null, null) = 0 792 * StringUtils.compare(null , "a") < 0 793 * StringUtils.compare("a", null) > 0 794 * StringUtils.compare("abc", "abc") = 0 795 * StringUtils.compare("a", "b") < 0 796 * StringUtils.compare("b", "a") > 0 797 * StringUtils.compare("a", "B") > 0 798 * StringUtils.compare("ab", "abc") < 0 799 * }</pre> 800 * 801 * @param str1 the String to compare from. 802 * @param str2 the String to compare to 803 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2} 804 * @see #compare(String, String, boolean) 805 * @see String#compareTo(String) 806 * @since 3.5 807 * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)} 808 */ 809 @Deprecated 810 public static int compare(final String str1, final String str2) { 811 return Strings.CS.compare(str1, str2); 812 } 813 814 /** 815 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 816 * <ul> 817 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 818 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 819 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 820 * </ul> 821 * 822 * <p> 823 * This is a {@code null} safe version of : 824 * </p> 825 * 826 * <pre> 827 * str1.compareTo(str2) 828 * </pre> 829 * 830 * <p> 831 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. 832 * </p> 833 * 834 * <pre>{@code 835 * StringUtils.compare(null, null, *) = 0 836 * StringUtils.compare(null , "a", true) < 0 837 * StringUtils.compare(null , "a", false) > 0 838 * StringUtils.compare("a", null, true) > 0 839 * StringUtils.compare("a", null, false) < 0 840 * StringUtils.compare("abc", "abc", *) = 0 841 * StringUtils.compare("a", "b", *) < 0 842 * StringUtils.compare("b", "a", *) > 0 843 * StringUtils.compare("a", "B", *) > 0 844 * StringUtils.compare("ab", "abc", *) < 0 845 * }</pre> 846 * 847 * @param str1 the String to compare from. 848 * @param str2 the String to compare to. 849 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 850 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}. 851 * @see String#compareTo(String) 852 * @since 3.5 853 */ 854 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 855 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 856 return 0; 857 } 858 if (str1 == null) { 859 return nullIsLess ? -1 : 1; 860 } 861 if (str2 == null) { 862 return nullIsLess ? 1 : -1; 863 } 864 return str1.compareTo(str2); 865 } 866 867 /** 868 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 869 * <ul> 870 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 871 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 872 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 873 * </ul> 874 * 875 * <p> 876 * This is a {@code null} safe version of: 877 * </p> 878 * 879 * <pre> 880 * str1.compareToIgnoreCase(str2) 881 * </pre> 882 * 883 * <p> 884 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive. 885 * </p> 886 * 887 * <pre>{@code 888 * StringUtils.compareIgnoreCase(null, null) = 0 889 * StringUtils.compareIgnoreCase(null , "a") < 0 890 * StringUtils.compareIgnoreCase("a", null) > 0 891 * StringUtils.compareIgnoreCase("abc", "abc") = 0 892 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 893 * StringUtils.compareIgnoreCase("a", "b") < 0 894 * StringUtils.compareIgnoreCase("b", "a") > 0 895 * StringUtils.compareIgnoreCase("a", "B") < 0 896 * StringUtils.compareIgnoreCase("A", "b") < 0 897 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 898 * }</pre> 899 * 900 * @param str1 the String to compare from. 901 * @param str2 the String to compare to. 902 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 903 * @see #compareIgnoreCase(String, String, boolean) 904 * @see String#compareToIgnoreCase(String) 905 * @since 3.5 906 * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)} 907 */ 908 @Deprecated 909 public static int compareIgnoreCase(final String str1, final String str2) { 910 return Strings.CI.compare(str1, str2); 911 } 912 913 /** 914 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 915 * <ul> 916 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 917 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 918 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 919 * </ul> 920 * 921 * <p> 922 * This is a {@code null} safe version of : 923 * </p> 924 * <pre> 925 * str1.compareToIgnoreCase(str2) 926 * </pre> 927 * 928 * <p> 929 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case 930 * insensitive. 931 * </p> 932 * 933 * <pre>{@code 934 * StringUtils.compareIgnoreCase(null, null, *) = 0 935 * StringUtils.compareIgnoreCase(null , "a", true) < 0 936 * StringUtils.compareIgnoreCase(null , "a", false) > 0 937 * StringUtils.compareIgnoreCase("a", null, true) > 0 938 * StringUtils.compareIgnoreCase("a", null, false) < 0 939 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 940 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 941 * StringUtils.compareIgnoreCase("a", "b", *) < 0 942 * StringUtils.compareIgnoreCase("b", "a", *) > 0 943 * StringUtils.compareIgnoreCase("a", "B", *) < 0 944 * StringUtils.compareIgnoreCase("A", "b", *) < 0 945 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 946 * }</pre> 947 * 948 * @param str1 the String to compare from. 949 * @param str2 the String to compare to. 950 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 951 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 952 * @see String#compareToIgnoreCase(String) 953 * @since 3.5 954 */ 955 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 956 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 957 return 0; 958 } 959 if (str1 == null) { 960 return nullIsLess ? -1 : 1; 961 } 962 if (str2 == null) { 963 return nullIsLess ? 1 : -1; 964 } 965 return str1.compareToIgnoreCase(str2); 966 } 967 968 /** 969 * Tests if CharSequence contains a search CharSequence, handling {@code null}. 970 * This method uses {@link String#indexOf(String)} if possible. 971 * 972 * <p>A {@code null} CharSequence will return {@code false}.</p> 973 * 974 * <pre> 975 * StringUtils.contains(null, *) = false 976 * StringUtils.contains(*, null) = false 977 * StringUtils.contains("", "") = true 978 * StringUtils.contains("abc", "") = true 979 * StringUtils.contains("abc", "a") = true 980 * StringUtils.contains("abc", "z") = false 981 * </pre> 982 * 983 * @param seq the CharSequence to check, may be null 984 * @param searchSeq the CharSequence to find, may be null 985 * @return true if the CharSequence contains the search CharSequence, 986 * false if not or {@code null} string input 987 * @since 2.0 988 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 989 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)} 990 */ 991 @Deprecated 992 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 993 return Strings.CS.contains(seq, searchSeq); 994 } 995 996 /** 997 * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible. 998 * 999 * <p> 1000 * A {@code null} or empty ("") CharSequence will return {@code false}. 1001 * </p> 1002 * 1003 * <pre> 1004 * StringUtils.contains(null, *) = false 1005 * StringUtils.contains("", *) = false 1006 * StringUtils.contains("abc", 'a') = true 1007 * StringUtils.contains("abc", 'z') = false 1008 * </pre> 1009 * 1010 * @param seq the CharSequence to check, may be null 1011 * @param searchChar the character to find 1012 * @return true if the CharSequence contains the search character, false if not or {@code null} string input 1013 * @since 2.0 1014 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1015 */ 1016 public static boolean contains(final CharSequence seq, final int searchChar) { 1017 if (isEmpty(seq)) { 1018 return false; 1019 } 1020 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1021 } 1022 1023 /** 1024 * Tests if the CharSequence contains any character in the given set of characters. 1025 * 1026 * <p> 1027 * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}. 1028 * </p> 1029 * 1030 * <pre> 1031 * StringUtils.containsAny(null, *) = false 1032 * StringUtils.containsAny("", *) = false 1033 * StringUtils.containsAny(*, null) = false 1034 * StringUtils.containsAny(*, []) = false 1035 * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true 1036 * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true 1037 * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true 1038 * StringUtils.containsAny("aba", ['z']) = false 1039 * </pre> 1040 * 1041 * @param cs the CharSequence to check, may be null. 1042 * @param searchChars the chars to search for, may be null. 1043 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input. 1044 * @since 2.4 1045 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1046 */ 1047 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1048 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1049 return false; 1050 } 1051 final int csLength = cs.length(); 1052 final int searchLength = searchChars.length; 1053 final int csLast = csLength - 1; 1054 final int searchLast = searchLength - 1; 1055 for (int i = 0; i < csLength; i++) { 1056 final char ch = cs.charAt(i); 1057 for (int j = 0; j < searchLength; j++) { 1058 if (searchChars[j] == ch) { 1059 if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1060 return true; 1061 } 1062 } 1063 } 1064 } 1065 return false; 1066 } 1067 1068 /** 1069 * Tests if the CharSequence contains any character in the given set of characters. 1070 * 1071 * <p> 1072 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}. 1073 * </p> 1074 * 1075 * <pre> 1076 * StringUtils.containsAny(null, *) = false 1077 * StringUtils.containsAny("", *) = false 1078 * StringUtils.containsAny(*, null) = false 1079 * StringUtils.containsAny(*, "") = false 1080 * StringUtils.containsAny("zzabyycdxx", "za") = true 1081 * StringUtils.containsAny("zzabyycdxx", "by") = true 1082 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1083 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1084 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1085 * StringUtils.containsAny("aba", "z") = false 1086 * </pre> 1087 * 1088 * @param cs the CharSequence to check, may be null. 1089 * @param searchChars the chars to search for, may be null. 1090 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input. 1091 * @since 2.4 1092 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1093 */ 1094 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1095 if (searchChars == null) { 1096 return false; 1097 } 1098 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1099 } 1100 1101 /** 1102 * Tests if the CharSequence contains any of the CharSequences in the given array. 1103 * 1104 * <p> 1105 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1106 * return {@code false}. 1107 * </p> 1108 * 1109 * <pre> 1110 * StringUtils.containsAny(null, *) = false 1111 * StringUtils.containsAny("", *) = false 1112 * StringUtils.containsAny(*, null) = false 1113 * StringUtils.containsAny(*, []) = false 1114 * StringUtils.containsAny("abcd", "ab", null) = true 1115 * StringUtils.containsAny("abcd", "ab", "cd") = true 1116 * StringUtils.containsAny("abc", "d", "abc") = true 1117 * </pre> 1118 * 1119 * @param cs The CharSequence to check, may be null. 1120 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1121 * null as well. 1122 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise. 1123 * @since 3.4 1124 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)} 1125 */ 1126 @Deprecated 1127 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1128 return Strings.CS.containsAny(cs, searchCharSequences); 1129 } 1130 1131 /** 1132 * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case. 1133 * 1134 * <p> 1135 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1136 * return {@code false}. 1137 * </p> 1138 * 1139 * <pre> 1140 * StringUtils.containsAny(null, *) = false 1141 * StringUtils.containsAny("", *) = false 1142 * StringUtils.containsAny(*, null) = false 1143 * StringUtils.containsAny(*, []) = false 1144 * StringUtils.containsAny("abcd", "ab", null) = true 1145 * StringUtils.containsAny("abcd", "ab", "cd") = true 1146 * StringUtils.containsAny("abc", "d", "abc") = true 1147 * StringUtils.containsAny("abc", "D", "ABC") = true 1148 * StringUtils.containsAny("ABC", "d", "abc") = true 1149 * </pre> 1150 * 1151 * @param cs The CharSequence to check, may be null. 1152 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1153 * null as well. 1154 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1155 * @since 3.12.0 1156 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)} 1157 */ 1158 @Deprecated 1159 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) { 1160 return Strings.CI.containsAny(cs, searchCharSequences); 1161 } 1162 1163 /** 1164 * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by 1165 * {@link String#equalsIgnoreCase(String)}. 1166 * 1167 * <p> 1168 * A {@code null} CharSequence will return {@code false}. 1169 * 1170 * <pre> 1171 * StringUtils.containsIgnoreCase(null, *) = false 1172 * StringUtils.containsIgnoreCase(*, null) = false 1173 * StringUtils.containsIgnoreCase("", "") = true 1174 * StringUtils.containsIgnoreCase("abc", "") = true 1175 * StringUtils.containsIgnoreCase("abc", "a") = true 1176 * StringUtils.containsIgnoreCase("abc", "z") = false 1177 * StringUtils.containsIgnoreCase("abc", "A") = true 1178 * StringUtils.containsIgnoreCase("abc", "Z") = false 1179 * </pre> 1180 * 1181 * @param str the CharSequence to check, may be null. 1182 * @param searchStr the CharSequence to find, may be null. 1183 * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input. 1184 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence). 1185 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)} 1186 */ 1187 @Deprecated 1188 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1189 return Strings.CI.contains(str, searchStr); 1190 } 1191 1192 /** 1193 * Tests that the CharSequence does not contain certain characters. 1194 * 1195 * <p> 1196 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0) 1197 * always returns true. 1198 * </p> 1199 * 1200 * <pre> 1201 * StringUtils.containsNone(null, *) = true 1202 * StringUtils.containsNone(*, null) = true 1203 * StringUtils.containsNone("", *) = true 1204 * StringUtils.containsNone("ab", '') = true 1205 * StringUtils.containsNone("abab", 'xyz') = true 1206 * StringUtils.containsNone("ab1", 'xyz') = true 1207 * StringUtils.containsNone("abz", 'xyz') = false 1208 * </pre> 1209 * 1210 * @param cs the CharSequence to check, may be null. 1211 * @param searchChars an array of invalid chars, may be null. 1212 * @return true if it contains none of the invalid chars, or is null. 1213 * @since 2.0 1214 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1215 */ 1216 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1217 if (cs == null || searchChars == null) { 1218 return true; 1219 } 1220 final int csLen = cs.length(); 1221 final int csLast = csLen - 1; 1222 final int searchLen = searchChars.length; 1223 final int searchLast = searchLen - 1; 1224 for (int i = 0; i < csLen; i++) { 1225 final char ch = cs.charAt(i); 1226 for (int j = 0; j < searchLen; j++) { 1227 if (searchChars[j] == ch) { 1228 if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1229 return false; 1230 } 1231 } 1232 } 1233 } 1234 return true; 1235 } 1236 1237 /** 1238 * Tests that the CharSequence does not contain certain characters. 1239 * 1240 * <p> 1241 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always 1242 * returns true. 1243 * </p> 1244 * 1245 * <pre> 1246 * StringUtils.containsNone(null, *) = true 1247 * StringUtils.containsNone(*, null) = true 1248 * StringUtils.containsNone("", *) = true 1249 * StringUtils.containsNone("ab", "") = true 1250 * StringUtils.containsNone("abab", "xyz") = true 1251 * StringUtils.containsNone("ab1", "xyz") = true 1252 * StringUtils.containsNone("abz", "xyz") = false 1253 * </pre> 1254 * 1255 * @param cs the CharSequence to check, may be null. 1256 * @param invalidChars a String of invalid chars, may be null. 1257 * @return true if it contains none of the invalid chars, or is null. 1258 * @since 2.0 1259 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1260 */ 1261 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1262 if (invalidChars == null) { 1263 return true; 1264 } 1265 return containsNone(cs, invalidChars.toCharArray()); 1266 } 1267 1268 /** 1269 * Tests if the CharSequence contains only certain characters. 1270 * 1271 * <p> 1272 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0) 1273 * always returns {@code true}. 1274 * </p> 1275 * 1276 * <pre> 1277 * StringUtils.containsOnly(null, *) = false 1278 * StringUtils.containsOnly(*, null) = false 1279 * StringUtils.containsOnly("", *) = true 1280 * StringUtils.containsOnly("ab", '') = false 1281 * StringUtils.containsOnly("abab", 'abc') = true 1282 * StringUtils.containsOnly("ab1", 'abc') = false 1283 * StringUtils.containsOnly("abz", 'abc') = false 1284 * </pre> 1285 * 1286 * @param cs the String to check, may be null. 1287 * @param valid an array of valid chars, may be null. 1288 * @return true if it only contains valid chars and is non-null. 1289 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1290 */ 1291 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1292 // All these pre-checks are to maintain API with an older version 1293 if (valid == null || cs == null) { 1294 return false; 1295 } 1296 if (cs.length() == 0) { 1297 return true; 1298 } 1299 if (valid.length == 0) { 1300 return false; 1301 } 1302 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1303 } 1304 1305 /** 1306 * Tests if the CharSequence contains only certain characters. 1307 * 1308 * <p> 1309 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0) 1310 * always returns {@code true}. 1311 * </p> 1312 * 1313 * <pre> 1314 * StringUtils.containsOnly(null, *) = false 1315 * StringUtils.containsOnly(*, null) = false 1316 * StringUtils.containsOnly("", *) = true 1317 * StringUtils.containsOnly("ab", "") = false 1318 * StringUtils.containsOnly("abab", "abc") = true 1319 * StringUtils.containsOnly("ab1", "abc") = false 1320 * StringUtils.containsOnly("abz", "abc") = false 1321 * </pre> 1322 * 1323 * @param cs the CharSequence to check, may be null. 1324 * @param validChars a String of valid chars, may be null. 1325 * @return true if it only contains valid chars and is non-null. 1326 * @since 2.0 1327 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1328 */ 1329 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1330 if (cs == null || validChars == null) { 1331 return false; 1332 } 1333 return containsOnly(cs, validChars.toCharArray()); 1334 } 1335 1336 /** 1337 * Tests whether the given CharSequence contains any whitespace characters. 1338 * 1339 * <p> 1340 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1341 * </p> 1342 * 1343 * <pre> 1344 * StringUtils.containsWhitespace(null) = false 1345 * StringUtils.containsWhitespace("") = false 1346 * StringUtils.containsWhitespace("ab") = false 1347 * StringUtils.containsWhitespace(" ab") = true 1348 * StringUtils.containsWhitespace("a b") = true 1349 * StringUtils.containsWhitespace("ab ") = true 1350 * </pre> 1351 * 1352 * @param seq the CharSequence to check (may be {@code null}). 1353 * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character. 1354 * @since 3.0 1355 */ 1356 public static boolean containsWhitespace(final CharSequence seq) { 1357 if (isEmpty(seq)) { 1358 return false; 1359 } 1360 final int strLen = seq.length(); 1361 for (int i = 0; i < strLen; i++) { 1362 if (Character.isWhitespace(seq.charAt(i))) { 1363 return true; 1364 } 1365 } 1366 return false; 1367 } 1368 1369 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1370 for (int i = 0; i < decomposed.length(); i++) { 1371 final char charAt = decomposed.charAt(i); 1372 switch (charAt) { 1373 case '\u0141': 1374 decomposed.setCharAt(i, 'L'); 1375 break; 1376 case '\u0142': 1377 decomposed.setCharAt(i, 'l'); 1378 break; 1379 // D with stroke 1380 case '\u0110': 1381 // LATIN CAPITAL LETTER D WITH STROKE 1382 decomposed.setCharAt(i, 'D'); 1383 break; 1384 case '\u0111': 1385 // LATIN SMALL LETTER D WITH STROKE 1386 decomposed.setCharAt(i, 'd'); 1387 break; 1388 // I with bar 1389 case '\u0197': 1390 decomposed.setCharAt(i, 'I'); 1391 break; 1392 case '\u0268': 1393 decomposed.setCharAt(i, 'i'); 1394 break; 1395 case '\u1D7B': 1396 decomposed.setCharAt(i, 'I'); 1397 break; 1398 case '\u1DA4': 1399 decomposed.setCharAt(i, 'i'); 1400 break; 1401 case '\u1DA7': 1402 decomposed.setCharAt(i, 'I'); 1403 break; 1404 // U with bar 1405 case '\u0244': 1406 // LATIN CAPITAL LETTER U BAR 1407 decomposed.setCharAt(i, 'U'); 1408 break; 1409 case '\u0289': 1410 // LATIN SMALL LETTER U BAR 1411 decomposed.setCharAt(i, 'u'); 1412 break; 1413 case '\u1D7E': 1414 // LATIN SMALL CAPITAL LETTER U WITH STROKE 1415 decomposed.setCharAt(i, 'U'); 1416 break; 1417 case '\u1DB6': 1418 // MODIFIER LETTER SMALL U BAR 1419 decomposed.setCharAt(i, 'u'); 1420 break; 1421 // T with stroke 1422 case '\u0166': 1423 // LATIN CAPITAL LETTER T WITH STROKE 1424 decomposed.setCharAt(i, 'T'); 1425 break; 1426 case '\u0167': 1427 // LATIN SMALL LETTER T WITH STROKE 1428 decomposed.setCharAt(i, 't'); 1429 break; 1430 default: 1431 break; 1432 } 1433 } 1434 } 1435 1436 /** 1437 * Counts how many times the char appears in the given string. 1438 * 1439 * <p> 1440 * A {@code null} or empty ("") String input returns {@code 0}. 1441 * </p> 1442 * 1443 * <pre> 1444 * StringUtils.countMatches(null, *) = 0 1445 * StringUtils.countMatches("", *) = 0 1446 * StringUtils.countMatches("abba", 0) = 0 1447 * StringUtils.countMatches("abba", 'a') = 2 1448 * StringUtils.countMatches("abba", 'b') = 2 1449 * StringUtils.countMatches("abba", 'x') = 0 1450 * </pre> 1451 * 1452 * @param str the CharSequence to check, may be null. 1453 * @param ch the char to count. 1454 * @return the number of occurrences, 0 if the CharSequence is {@code null}. 1455 * @since 3.4 1456 */ 1457 public static int countMatches(final CharSequence str, final char ch) { 1458 if (isEmpty(str)) { 1459 return 0; 1460 } 1461 int count = 0; 1462 // We could also call str.toCharArray() for faster lookups but that would generate more garbage. 1463 for (int i = 0; i < str.length(); i++) { 1464 if (ch == str.charAt(i)) { 1465 count++; 1466 } 1467 } 1468 return count; 1469 } 1470 1471 /** 1472 * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches. 1473 * 1474 * <p> 1475 * A {@code null} or empty ("") String input returns {@code 0}. 1476 * </p> 1477 * 1478 * <pre> 1479 * StringUtils.countMatches(null, *) = 0 1480 * StringUtils.countMatches("", *) = 0 1481 * StringUtils.countMatches("abba", null) = 0 1482 * StringUtils.countMatches("abba", "") = 0 1483 * StringUtils.countMatches("abba", "a") = 2 1484 * StringUtils.countMatches("abba", "ab") = 1 1485 * StringUtils.countMatches("abba", "xxx") = 0 1486 * StringUtils.countMatches("ababa", "aba") = 1 1487 * </pre> 1488 * 1489 * @param str the CharSequence to check, may be null. 1490 * @param sub the substring to count, may be null. 1491 * @return the number of occurrences, 0 if either CharSequence is {@code null}. 1492 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1493 */ 1494 public static int countMatches(final CharSequence str, final CharSequence sub) { 1495 if (isEmpty(str) || isEmpty(sub)) { 1496 return 0; 1497 } 1498 int count = 0; 1499 int idx = 0; 1500 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1501 count++; 1502 idx += sub.length(); 1503 } 1504 return count; 1505 } 1506 1507 /** 1508 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or 1509 * {@code null}), the value of {@code defaultStr}. 1510 * 1511 * <p> 1512 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1513 * </p> 1514 * 1515 * <pre> 1516 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1517 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1518 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1519 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1520 * StringUtils.defaultIfBlank("", null) = null 1521 * </pre> 1522 * 1523 * @param <T> the specific kind of CharSequence. 1524 * @param str the CharSequence to check, may be null. 1525 * @param defaultStr the default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code""}) or 1526 * {@code null}); may be null. 1527 * @return the passed in CharSequence, or the default. 1528 * @see StringUtils#defaultString(String, String) 1529 * @see #isBlank(CharSequence) 1530 */ 1531 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1532 return isBlank(str) ? defaultStr : str; 1533 } 1534 1535 /** 1536 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}. 1537 * 1538 * <pre> 1539 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1540 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1541 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1542 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1543 * StringUtils.defaultIfEmpty("", null) = null 1544 * </pre> 1545 * 1546 * @param <T> the specific kind of CharSequence. 1547 * @param str the CharSequence to check, may be null. 1548 * @param defaultStr the default CharSequence to return if the input is empty ("") or {@code null}, may be null. 1549 * @return the passed in CharSequence, or the default. 1550 * @see StringUtils#defaultString(String, String) 1551 */ 1552 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1553 return isEmpty(str) ? defaultStr : str; 1554 } 1555 1556 /** 1557 * Returns either the passed in String, or if the String is {@code null}, an empty String (""). 1558 * 1559 * <pre> 1560 * StringUtils.defaultString(null) = "" 1561 * StringUtils.defaultString("") = "" 1562 * StringUtils.defaultString("bat") = "bat" 1563 * </pre> 1564 * 1565 * @param str the String to check, may be null. 1566 * @return the passed in String, or the empty String if it was {@code null}. 1567 * @see Objects#toString(Object, String) 1568 * @see String#valueOf(Object) 1569 */ 1570 public static String defaultString(final String str) { 1571 return Objects.toString(str, EMPTY); 1572 } 1573 1574 /** 1575 * Returns either the given String, or if the String is {@code null}, {@code nullDefault}. 1576 * 1577 * <pre> 1578 * StringUtils.defaultString(null, "NULL") = "NULL" 1579 * StringUtils.defaultString("", "NULL") = "" 1580 * StringUtils.defaultString("bat", "NULL") = "bat" 1581 * </pre> 1582 * <p> 1583 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}: 1584 * </p> 1585 * 1586 * <pre> 1587 * Objects.toString(null, "NULL") = "NULL" 1588 * Objects.toString("", "NULL") = "" 1589 * Objects.toString("bat", "NULL") = "bat" 1590 * </pre> 1591 * 1592 * @param str the String to check, may be null. 1593 * @param nullDefault the default String to return if the input is {@code null}, may be null. 1594 * @return the passed in String, or the default if it was {@code null}. 1595 * @see Objects#toString(Object, String) 1596 * @see String#valueOf(Object) 1597 * @deprecated Use {@link Objects#toString(Object, String)} 1598 */ 1599 @Deprecated 1600 public static String defaultString(final String str, final String nullDefault) { 1601 return Objects.toString(str, nullDefault); 1602 } 1603 1604 /** 1605 * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}. 1606 * 1607 * <pre> 1608 * StringUtils.deleteWhitespace(null) = null 1609 * StringUtils.deleteWhitespace("") = "" 1610 * StringUtils.deleteWhitespace("abc") = "abc" 1611 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1612 * </pre> 1613 * 1614 * @param str the String to delete whitespace from, may be null. 1615 * @return the String without whitespaces, {@code null} if null String input. 1616 */ 1617 public static String deleteWhitespace(final String str) { 1618 if (isEmpty(str)) { 1619 return str; 1620 } 1621 final int sz = str.length(); 1622 final char[] chs = new char[sz]; 1623 int count = 0; 1624 for (int i = 0; i < sz; i++) { 1625 if (!Character.isWhitespace(str.charAt(i))) { 1626 chs[count++] = str.charAt(i); 1627 } 1628 } 1629 if (count == sz) { 1630 return str; 1631 } 1632 if (count == 0) { 1633 return EMPTY; 1634 } 1635 return new String(chs, 0, count); 1636 } 1637 1638 /** 1639 * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's 1640 * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c". 1641 * 1642 * <p> 1643 * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}. 1644 * </p> 1645 * 1646 * <pre> 1647 * StringUtils.difference(null, null) = null 1648 * StringUtils.difference("", "") = "" 1649 * StringUtils.difference("", "abc") = "abc" 1650 * StringUtils.difference("abc", "") = "" 1651 * StringUtils.difference("abc", "abc") = "" 1652 * StringUtils.difference("abc", "ab") = "" 1653 * StringUtils.difference("ab", "abxyz") = "xyz" 1654 * StringUtils.difference("abcde", "abxyz") = "xyz" 1655 * StringUtils.difference("abcde", "xyz") = "xyz" 1656 * </pre> 1657 * 1658 * @param str1 the first String, may be null. 1659 * @param str2 the second String, may be null. 1660 * @return the portion of str2 where it differs from str1; returns the empty String if they are equal. 1661 * @see #indexOfDifference(CharSequence,CharSequence) 1662 * @since 2.0 1663 */ 1664 public static String difference(final String str1, final String str2) { 1665 if (str1 == null) { 1666 return str2; 1667 } 1668 if (str2 == null) { 1669 return str1; 1670 } 1671 final int at = indexOfDifference(str1, str2); 1672 if (at == INDEX_NOT_FOUND) { 1673 return EMPTY; 1674 } 1675 return str2.substring(at); 1676 } 1677 1678 /** 1679 * Tests if a CharSequence ends with a specified suffix. 1680 * 1681 * <p> 1682 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 1683 * </p> 1684 * 1685 * <pre> 1686 * StringUtils.endsWith(null, null) = true 1687 * StringUtils.endsWith(null, "def") = false 1688 * StringUtils.endsWith("abcdef", null) = false 1689 * StringUtils.endsWith("abcdef", "def") = true 1690 * StringUtils.endsWith("ABCDEF", "def") = false 1691 * StringUtils.endsWith("ABCDEF", "cde") = false 1692 * StringUtils.endsWith("ABCDEF", "") = true 1693 * </pre> 1694 * 1695 * @param str the CharSequence to check, may be null. 1696 * @param suffix the suffix to find, may be null. 1697 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}. 1698 * @see String#endsWith(String) 1699 * @since 2.4 1700 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1701 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)} 1702 */ 1703 @Deprecated 1704 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1705 return Strings.CS.endsWith(str, suffix); 1706 } 1707 1708 /** 1709 * Tests if a CharSequence ends with any of the provided case-sensitive suffixes. 1710 * 1711 * <pre> 1712 * StringUtils.endsWithAny(null, null) = false 1713 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1714 * StringUtils.endsWithAny("abcxyz", null) = false 1715 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1716 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1717 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1718 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1719 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1720 * </pre> 1721 * 1722 * @param sequence the CharSequence to check, may be null. 1723 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}. 1724 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} ends in any 1725 * of the provided case-sensitive {@code searchStrings}. 1726 * @see StringUtils#endsWith(CharSequence, CharSequence) 1727 * @since 3.0 1728 * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)} 1729 */ 1730 @Deprecated 1731 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1732 return Strings.CS.endsWithAny(sequence, searchStrings); 1733 } 1734 1735 /** 1736 * Case-insensitive check if a CharSequence ends with a specified suffix. 1737 * 1738 * <p> 1739 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 1740 * </p> 1741 * 1742 * <pre> 1743 * StringUtils.endsWithIgnoreCase(null, null) = true 1744 * StringUtils.endsWithIgnoreCase(null, "def") = false 1745 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1746 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1747 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1748 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1749 * </pre> 1750 * 1751 * @param str the CharSequence to check, may be null 1752 * @param suffix the suffix to find, may be null 1753 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null} 1754 * @see String#endsWith(String) 1755 * @since 2.4 1756 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1757 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)} 1758 */ 1759 @Deprecated 1760 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1761 return Strings.CI.endsWith(str, suffix); 1762 } 1763 1764 /** 1765 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters. 1766 * 1767 * <p> 1768 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>. 1769 * </p> 1770 * 1771 * <pre> 1772 * StringUtils.equals(null, null) = true 1773 * StringUtils.equals(null, "abc") = false 1774 * StringUtils.equals("abc", null) = false 1775 * StringUtils.equals("abc", "abc") = true 1776 * StringUtils.equals("abc", "ABC") = false 1777 * </pre> 1778 * 1779 * @param cs1 the first CharSequence, may be {@code null}. 1780 * @param cs2 the second CharSequence, may be {@code null}. 1781 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}. 1782 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1783 * @see Object#equals(Object) 1784 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1785 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)} 1786 */ 1787 @Deprecated 1788 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1789 return Strings.CS.equals(cs1, cs2); 1790 } 1791 1792 /** 1793 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the 1794 * {@code searchStrings}. 1795 * 1796 * <pre> 1797 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1798 * StringUtils.equalsAny(null, null, null) = true 1799 * StringUtils.equalsAny(null, "abc", "def") = false 1800 * StringUtils.equalsAny("abc", null, "def") = false 1801 * StringUtils.equalsAny("abc", "abc", "def") = true 1802 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1803 * </pre> 1804 * 1805 * @param string to compare, may be {@code null}. 1806 * @param searchStrings a vararg of strings, may be {@code null}. 1807 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is 1808 * null or contains no matches. 1809 * @since 3.5 1810 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)} 1811 */ 1812 @Deprecated 1813 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1814 return Strings.CS.equalsAny(string, searchStrings); 1815 } 1816 1817 /** 1818 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1819 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1820 * 1821 * <pre> 1822 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1823 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1824 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1825 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1826 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1827 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1828 * </pre> 1829 * 1830 * @param string to compare, may be {@code null}. 1831 * @param searchStrings a vararg of strings, may be {@code null}. 1832 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1833 * {@code false} if {@code searchStrings} is null or contains no matches. 1834 * @since 3.5 1835 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI-.equalsAny(CharSequence, CharSequence...)} 1836 */ 1837 @Deprecated 1838 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) { 1839 return Strings.CI.equalsAny(string, searchStrings); 1840 } 1841 1842 /** 1843 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case. 1844 * 1845 * <p> 1846 * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>. 1847 * </p> 1848 * 1849 * <pre> 1850 * StringUtils.equalsIgnoreCase(null, null) = true 1851 * StringUtils.equalsIgnoreCase(null, "abc") = false 1852 * StringUtils.equalsIgnoreCase("abc", null) = false 1853 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1854 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1855 * </pre> 1856 * 1857 * @param cs1 the first CharSequence, may be {@code null}. 1858 * @param cs2 the second CharSequence, may be {@code null}. 1859 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}. 1860 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1861 * @see #equals(CharSequence, CharSequence) 1862 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)} 1863 */ 1864 @Deprecated 1865 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1866 return Strings.CI.equals(cs1, cs2); 1867 } 1868 1869 /** 1870 * Returns the first value in the array which is not empty (""), {@code null} or whitespace only. 1871 * 1872 * <p> 1873 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1874 * </p> 1875 * 1876 * <p> 1877 * If all values are blank or the array is {@code null} or empty then {@code null} is returned. 1878 * </p> 1879 * 1880 * <pre> 1881 * StringUtils.firstNonBlank(null, null, null) = null 1882 * StringUtils.firstNonBlank(null, "", " ") = null 1883 * StringUtils.firstNonBlank("abc") = "abc" 1884 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1885 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1886 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1887 * StringUtils.firstNonBlank() = null 1888 * </pre> 1889 * 1890 * @param <T> the specific kind of CharSequence. 1891 * @param values the values to test, may be {@code null} or empty. 1892 * @return the first value from {@code values} which is not blank, or {@code null} if there are no non-blank values. 1893 * @since 3.8 1894 */ 1895 @SafeVarargs 1896 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1897 if (values != null) { 1898 for (final T val : values) { 1899 if (isNotBlank(val)) { 1900 return val; 1901 } 1902 } 1903 } 1904 return null; 1905 } 1906 1907 /** 1908 * Returns the first value in the array which is not empty. 1909 * 1910 * <p> 1911 * If all values are empty or the array is {@code null} or empty then {@code null} is returned. 1912 * </p> 1913 * 1914 * <pre> 1915 * StringUtils.firstNonEmpty(null, null, null) = null 1916 * StringUtils.firstNonEmpty(null, null, "") = null 1917 * StringUtils.firstNonEmpty(null, "", " ") = " " 1918 * StringUtils.firstNonEmpty("abc") = "abc" 1919 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1920 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1921 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1922 * StringUtils.firstNonEmpty() = 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 empty, or {@code null} if there are no non-empty values. 1928 * @since 3.8 1929 */ 1930 @SafeVarargs 1931 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1932 if (values != null) { 1933 for (final T val : values) { 1934 if (isNotEmpty(val)) { 1935 return val; 1936 } 1937 } 1938 } 1939 return null; 1940 } 1941 1942 /** 1943 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1944 * 1945 * @param string input string. 1946 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 1947 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1948 * @see String#getBytes(Charset) 1949 * @since 3.10 1950 */ 1951 public static byte[] getBytes(final String string, final Charset charset) { 1952 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1953 } 1954 1955 /** 1956 * Calls {@link String#getBytes(String)} in a null-safe manner. 1957 * 1958 * @param string input string. 1959 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 1960 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 1961 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 1962 * @see String#getBytes(String) 1963 * @since 3.10 1964 */ 1965 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 1966 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 1967 } 1968 1969 /** 1970 * Compares all Strings in an array and returns the initial sequence of characters that is common to all of them. 1971 * 1972 * <p> 1973 * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -> "i am a "} 1974 * </p> 1975 * 1976 * <pre> 1977 * StringUtils.getCommonPrefix(null) = "" 1978 * StringUtils.getCommonPrefix(new String[] {}) = "" 1979 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 1980 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 1981 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 1982 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 1983 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 1984 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 1985 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 1986 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 1987 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 1988 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 1989 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 1990 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 1991 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 1992 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 1993 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 1994 * </pre> 1995 * 1996 * @param strs array of String objects, entries may be null. 1997 * @return the initial sequence of characters that are common to all Strings in the array; empty String if the array is null, the elements are all null or 1998 * if there is no common prefix. 1999 * @since 2.4 2000 */ 2001 public static String getCommonPrefix(final String... strs) { 2002 if (ArrayUtils.isEmpty(strs)) { 2003 return EMPTY; 2004 } 2005 final int smallestIndexOfDiff = indexOfDifference(strs); 2006 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2007 // all strings were identical 2008 if (strs[0] == null) { 2009 return EMPTY; 2010 } 2011 return strs[0]; 2012 } 2013 if (smallestIndexOfDiff == 0) { 2014 // there were no common initial characters 2015 return EMPTY; 2016 } 2017 // we found a common initial character sequence 2018 return strs[0].substring(0, smallestIndexOfDiff); 2019 } 2020 2021 /** 2022 * Checks if a String {@code str} contains Unicode digits, if yes then concatenate all the digits in {@code str} and return it as a String. 2023 * 2024 * <p> 2025 * An empty ("") String will be returned if no digits found in {@code str}. 2026 * </p> 2027 * 2028 * <pre> 2029 * StringUtils.getDigits(null) = null 2030 * StringUtils.getDigits("") = "" 2031 * StringUtils.getDigits("abc") = "" 2032 * StringUtils.getDigits("1000$") = "1000" 2033 * StringUtils.getDigits("1123~45") = "112345" 2034 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2035 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2036 * </pre> 2037 * 2038 * @param str the String to extract digits from, may be null. 2039 * @return String with only digits, or an empty ("") String if no digits found, or {@code null} String if {@code str} is null. 2040 * @since 3.6 2041 */ 2042 public static String getDigits(final String str) { 2043 if (isEmpty(str)) { 2044 return str; 2045 } 2046 final int sz = str.length(); 2047 final StringBuilder strDigits = new StringBuilder(sz); 2048 for (int i = 0; i < sz; i++) { 2049 final char tempChar = str.charAt(i); 2050 if (Character.isDigit(tempChar)) { 2051 strDigits.append(tempChar); 2052 } 2053 } 2054 return strDigits.toString(); 2055 } 2056 2057 /** 2058 * Gets the Fuzzy Distance which indicates the similarity score between two Strings. 2059 * 2060 * <p> 2061 * This string matching algorithm is similar to the algorithms of editors such as Sublime Text, TextMate, Atom and others. One point is given for every 2062 * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity. 2063 * </p> 2064 * 2065 * <pre> 2066 * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException 2067 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2068 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2069 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2070 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2071 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2072 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2073 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2074 * </pre> 2075 * 2076 * @param term a full term that should be matched against, must not be null. 2077 * @param query the query that will be matched against a term, must not be null. 2078 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case. 2079 * @return result score. 2080 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}. 2081 * @since 3.4 2082 * @deprecated As of 3.6, use Apache Commons Text 2083 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2084 * FuzzyScore</a> instead 2085 */ 2086 @Deprecated 2087 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2088 if (term == null || query == null) { 2089 throw new IllegalArgumentException("Strings must not be null"); 2090 } 2091 if (locale == null) { 2092 throw new IllegalArgumentException("Locale must not be null"); 2093 } 2094 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2095 // case right from the start. Turning characters to lower case 2096 // via Character.toLowerCase(char) is unfortunately insufficient 2097 // as it does not accept a locale. 2098 final String termLowerCase = term.toString().toLowerCase(locale); 2099 final String queryLowerCase = query.toString().toLowerCase(locale); 2100 // the resulting score 2101 int score = 0; 2102 // the position in the term which will be scanned next for potential 2103 // query character matches 2104 int termIndex = 0; 2105 // index of the previously matched character in the term 2106 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2107 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2108 final char queryChar = queryLowerCase.charAt(queryIndex); 2109 boolean termCharacterMatchFound = false; 2110 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2111 final char termChar = termLowerCase.charAt(termIndex); 2112 if (queryChar == termChar) { 2113 // simple character matches result in one point 2114 score++; 2115 // subsequent character matches further improve 2116 // the score. 2117 if (previousMatchingCharacterIndex + 1 == termIndex) { 2118 score += 2; 2119 } 2120 previousMatchingCharacterIndex = termIndex; 2121 // we can leave the nested loop. Every character in the 2122 // query can match at most one character in the term. 2123 termCharacterMatchFound = true; 2124 } 2125 } 2126 } 2127 return score; 2128 } 2129 2130 /** 2131 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or 2132 * {@code null}), the value supplied by {@code defaultStrSupplier}. 2133 * 2134 * <p> 2135 * Whitespace is defined by {@link Character#isWhitespace(char)}. 2136 * </p> 2137 * 2138 * <p> 2139 * Caller responsible for thread-safety and exception handling of default value supplier 2140 * </p> 2141 * 2142 * <pre> 2143 * {@code 2144 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2145 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2146 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2147 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2148 * StringUtils.getIfBlank("", () -> null) = null 2149 * StringUtils.getIfBlank("", null) = null 2150 * }</pre> 2151 * 2152 * @param <T> the specific kind of CharSequence. 2153 * @param str the CharSequence to check, may be null. 2154 * @param defaultSupplier the supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty 2155 * ({@code ""}) or {@code null}); may be null. 2156 * @return the passed in CharSequence, or the default 2157 * @see StringUtils#defaultString(String, String) 2158 * @see #isBlank(CharSequence) 2159 * @since 3.10 2160 */ 2161 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2162 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2163 } 2164 2165 /** 2166 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2167 * 2168 * <p> 2169 * Caller responsible for thread-safety and exception handling of default value supplier 2170 * </p> 2171 * 2172 * <pre> 2173 * {@code 2174 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2175 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2176 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2177 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2178 * StringUtils.getIfEmpty("", () -> null) = null 2179 * StringUtils.getIfEmpty("", null) = null 2180 * } 2181 * </pre> 2182 * 2183 * @param <T> the specific kind of CharSequence. 2184 * @param str the CharSequence to check, may be null. 2185 * @param defaultSupplier the supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null. 2186 * @return the passed in CharSequence, or the default. 2187 * @see StringUtils#defaultString(String, String) 2188 * @since 3.10 2189 */ 2190 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2191 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2192 } 2193 2194 /** 2195 * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings. 2196 * 2197 * <p> 2198 * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for 2199 * matching initial characters. 2200 * </p> 2201 * 2202 * <p> 2203 * This implementation is based on the Jaro Winkler similarity algorithm from 2204 * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>. 2205 * </p> 2206 * 2207 * <pre> 2208 * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException 2209 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2210 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2211 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2212 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2213 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2214 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2215 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2216 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2217 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2218 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2219 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2220 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2221 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2222 * </pre> 2223 * 2224 * @param first the first String, must not be null. 2225 * @param second the second String, must not be null. 2226 * @return result distance. 2227 * @throws IllegalArgumentException if either String input {@code null}. 2228 * @since 3.3 2229 * @deprecated As of 3.6, use Apache Commons Text 2230 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2231 * JaroWinklerDistance</a> instead 2232 */ 2233 @Deprecated 2234 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2235 final double DEFAULT_SCALING_FACTOR = 0.1; 2236 2237 if (first == null || second == null) { 2238 throw new IllegalArgumentException("Strings must not be null"); 2239 } 2240 2241 final int[] mtp = matches(first, second); 2242 final double m = mtp[0]; 2243 if (m == 0) { 2244 return 0D; 2245 } 2246 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2247 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2248 return Math.round(jw * 100.0D) / 100.0D; 2249 } 2250 2251 /** 2252 * Gets the Levenshtein distance between two Strings. 2253 * 2254 * <p> 2255 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2256 * substitution). 2257 * </p> 2258 * 2259 * <p> 2260 * The implementation uses a single-dimensional array of length s.length() + 1. See 2261 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2262 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details. 2263 * </p> 2264 * 2265 * <pre> 2266 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 2267 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 2268 * StringUtils.getLevenshteinDistance("", "") = 0 2269 * StringUtils.getLevenshteinDistance("", "a") = 1 2270 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2271 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2272 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2273 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2274 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2275 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2276 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2277 * </pre> 2278 * 2279 * @param s the first String, must not be null. 2280 * @param t the second String, must not be null. 2281 * @return result distance. 2282 * @throws IllegalArgumentException if either String input {@code null}. 2283 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence) 2284 * @deprecated As of 3.6, use Apache Commons Text 2285 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2286 * LevenshteinDistance</a> instead 2287 */ 2288 @Deprecated 2289 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2290 if (s == null || t == null) { 2291 throw new IllegalArgumentException("Strings must not be null"); 2292 } 2293 2294 int n = s.length(); 2295 int m = t.length(); 2296 2297 if (n == 0) { 2298 return m; 2299 } 2300 if (m == 0) { 2301 return n; 2302 } 2303 2304 if (n > m) { 2305 // swap the input strings to consume less memory 2306 final CharSequence tmp = s; 2307 s = t; 2308 t = tmp; 2309 n = m; 2310 m = t.length(); 2311 } 2312 2313 final int[] p = new int[n + 1]; 2314 // indexes into strings s and t 2315 int i; // iterates through s 2316 int j; // iterates through t 2317 int upperleft; 2318 int upper; 2319 2320 char jOfT; // jth character of t 2321 int cost; 2322 2323 for (i = 0; i <= n; i++) { 2324 p[i] = i; 2325 } 2326 2327 for (j = 1; j <= m; j++) { 2328 upperleft = p[0]; 2329 jOfT = t.charAt(j - 1); 2330 p[0] = j; 2331 2332 for (i = 1; i <= n; i++) { 2333 upper = p[i]; 2334 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2335 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2336 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2337 upperleft = upper; 2338 } 2339 } 2340 2341 return p[n]; 2342 } 2343 2344 /** 2345 * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold. 2346 * 2347 * <p> 2348 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2349 * substitution). 2350 * </p> 2351 * 2352 * <p> 2353 * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance 2354 * algorithm from <a href="https://web.archive.org/web/20120212021906/http%3A//www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a> 2355 * </p> 2356 * 2357 * <pre> 2358 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 2359 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 2360 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 2361 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2362 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2363 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2364 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2365 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2366 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2367 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2368 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2369 * </pre> 2370 * 2371 * @param s the first String, must not be null. 2372 * @param t the second String, must not be null. 2373 * @param threshold the target threshold, must not be negative. 2374 * @return result distance, or {@code -1} if the distance would be greater than the threshold. 2375 * @throws IllegalArgumentException if either String input {@code null} or negative threshold. 2376 * @deprecated As of 3.6, use Apache Commons Text 2377 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2378 * LevenshteinDistance</a> instead 2379 */ 2380 @Deprecated 2381 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2382 if (s == null || t == null) { 2383 throw new IllegalArgumentException("Strings must not be null"); 2384 } 2385 if (threshold < 0) { 2386 throw new IllegalArgumentException("Threshold must not be negative"); 2387 } 2388 2389 /* 2390 This implementation only computes the distance if it's less than or equal to the 2391 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2392 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2393 computing a diagonal stripe of width 2k + 1 of the cost table. 2394 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2395 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2396 d is the distance. 2397 2398 One subtlety comes from needing to ignore entries on the border of our stripe 2399 eg. 2400 p[] = |#|#|#|* 2401 d[] = *|#|#|#| 2402 We must ignore the entry to the left of the leftmost member 2403 We must ignore the entry above the rightmost member 2404 2405 Another subtlety comes from our stripe running off the matrix if the strings aren't 2406 of the same size. Since string s is always swapped to be the shorter of the two, 2407 the stripe will always run off to the upper right instead of the lower left of the matrix. 2408 2409 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2410 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2411 2412 1 2 3 4 5 2413 1 |#|#| | | | 2414 2 |#|#|#| | | 2415 3 | |#|#|#| | 2416 4 | | |#|#|#| 2417 5 | | | |#|#| 2418 6 | | | | |#| 2419 7 | | | | | | 2420 2421 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2422 into one of length 7 in edit distance of 1. 2423 2424 Additionally, this implementation decreases memory usage by using two 2425 single-dimensional arrays and swapping them back and forth instead of allocating 2426 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2427 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2428 large values so that entries we don't compute are ignored. 2429 2430 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2431 */ 2432 2433 int n = s.length(); // length of s 2434 int m = t.length(); // length of t 2435 2436 // if one string is empty, the edit distance is necessarily the length of the other 2437 if (n == 0) { 2438 return m <= threshold ? m : -1; 2439 } 2440 if (m == 0) { 2441 return n <= threshold ? n : -1; 2442 } 2443 if (Math.abs(n - m) > threshold) { 2444 // no need to calculate the distance if the length difference is greater than the threshold 2445 return -1; 2446 } 2447 2448 if (n > m) { 2449 // swap the two strings to consume less memory 2450 final CharSequence tmp = s; 2451 s = t; 2452 t = tmp; 2453 n = m; 2454 m = t.length(); 2455 } 2456 2457 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2458 int[] d = new int[n + 1]; // cost array, horizontally 2459 int[] tmp; // placeholder to assist in swapping p and d 2460 2461 // fill in starting table values 2462 final int boundary = Math.min(n, threshold) + 1; 2463 for (int i = 0; i < boundary; i++) { 2464 p[i] = i; 2465 } 2466 // these fills ensure that the value above the rightmost entry of our 2467 // stripe will be ignored in following loop iterations 2468 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2469 Arrays.fill(d, Integer.MAX_VALUE); 2470 2471 // iterates through t 2472 for (int j = 1; j <= m; j++) { 2473 final char jOfT = t.charAt(j - 1); // jth character of t 2474 d[0] = j; 2475 2476 // compute stripe indices, constrain to array size 2477 final int min = Math.max(1, j - threshold); 2478 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2479 2480 // the stripe may lead off of the table if s and t are of different sizes 2481 if (min > max) { 2482 return -1; 2483 } 2484 2485 // ignore entry left of leftmost 2486 if (min > 1) { 2487 d[min - 1] = Integer.MAX_VALUE; 2488 } 2489 2490 // iterates through [min, max] in s 2491 for (int i = min; i <= max; i++) { 2492 if (s.charAt(i - 1) == jOfT) { 2493 // diagonally left and up 2494 d[i] = p[i - 1]; 2495 } else { 2496 // 1 + minimum of cell to the left, to the top, diagonally left and up 2497 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2498 } 2499 } 2500 2501 // copy current distance counts to 'previous row' distance counts 2502 tmp = p; 2503 p = d; 2504 d = tmp; 2505 } 2506 2507 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2508 // distance 2509 if (p[n] <= threshold) { 2510 return p[n]; 2511 } 2512 return -1; 2513 } 2514 2515 /** 2516 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2517 * 2518 * <p> 2519 * A {@code null} CharSequence will return {@code -1}. 2520 * </p> 2521 * 2522 * <pre> 2523 * StringUtils.indexOf(null, *) = -1 2524 * StringUtils.indexOf(*, null) = -1 2525 * StringUtils.indexOf("", "") = 0 2526 * StringUtils.indexOf("", *) = -1 (except when * = "") 2527 * StringUtils.indexOf("aabaabaa", "a") = 0 2528 * StringUtils.indexOf("aabaabaa", "b") = 2 2529 * StringUtils.indexOf("aabaabaa", "ab") = 1 2530 * StringUtils.indexOf("aabaabaa", "") = 0 2531 * </pre> 2532 * 2533 * @param seq the CharSequence to check, may be null. 2534 * @param searchSeq the CharSequence to find, may be null. 2535 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 2536 * @since 2.0 2537 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2538 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)} 2539 */ 2540 @Deprecated 2541 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2542 return Strings.CS.indexOf(seq, searchSeq); 2543 } 2544 2545 /** 2546 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2547 * 2548 * <p> 2549 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 2550 * start position greater than the string length only matches an empty search CharSequence. 2551 * </p> 2552 * 2553 * <pre> 2554 * StringUtils.indexOf(null, *, *) = -1 2555 * StringUtils.indexOf(*, null, *) = -1 2556 * StringUtils.indexOf("", "", 0) = 0 2557 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2558 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2559 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2560 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2561 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2562 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2563 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2564 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2565 * StringUtils.indexOf("abc", "", 9) = 3 2566 * </pre> 2567 * 2568 * @param seq the CharSequence to check, may be null. 2569 * @param searchSeq the CharSequence to find, may be null. 2570 * @param startPos the start position, negative treated as zero. 2571 * @return the first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 2572 * @since 2.0 2573 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2574 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)} 2575 */ 2576 @Deprecated 2577 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2578 return Strings.CS.indexOf(seq, searchSeq, startPos); 2579 } 2580 2581 /** 2582 * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the 2583 * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is 2584 * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that: 2585 * 2586 * <pre> 2587 * this.charAt(<em>k</em>) == searchChar 2588 * </pre> 2589 * 2590 * <p> 2591 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2592 * </p> 2593 * 2594 * <pre> 2595 * this.codePointAt(<em>k</em>) == searchChar 2596 * </pre> 2597 * 2598 * <p> 2599 * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned. 2600 * </p> 2601 * 2602 * <p> 2603 * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}. 2604 * </p> 2605 * 2606 * <pre> 2607 * StringUtils.indexOf(null, *) = -1 2608 * StringUtils.indexOf("", *) = -1 2609 * StringUtils.indexOf("aabaabaa", 'a') = 0 2610 * StringUtils.indexOf("aabaabaa", 'b') = 2 2611 * StringUtils.indexOf("aaaaaaaa", 'Z') = -1 2612 * </pre> 2613 * 2614 * @param seq the CharSequence to check, may be null. 2615 * @param searchChar the character to find. 2616 * @return the first index of the search character, -1 if no match or {@code null} string input. 2617 * @since 2.0 2618 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2619 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2620 */ 2621 public static int indexOf(final CharSequence seq, final int searchChar) { 2622 if (isEmpty(seq)) { 2623 return INDEX_NOT_FOUND; 2624 } 2625 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2626 } 2627 2628 /** 2629 * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index. 2630 * <p> 2631 * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no 2632 * smaller than {@code startPos}, then the index of the first such occurrence is returned. For values of {@code searchChar} in the range from 0 to 0xFFFF 2633 * (inclusive), this is the smallest value <em>k</em> such that: 2634 * </p> 2635 * 2636 * <pre> 2637 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2638 * </pre> 2639 * 2640 * <p> 2641 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2642 * </p> 2643 * 2644 * <pre> 2645 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2646 * </pre> 2647 * 2648 * <p> 2649 * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned. 2650 * </p> 2651 * 2652 * <p> 2653 * There is no restriction on the value of {@code startPos}. If it is negative, it has the same effect as if it were zero: this entire string may be 2654 * searched. If it is greater than the length of this string, it has the same effect as if it were equal to the length of this string: 2655 * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}. 2656 * </p> 2657 * <p> 2658 * All indices are specified in {@code char} values (Unicode code units). 2659 * 2660 * <pre> 2661 * StringUtils.indexOf(null, *, *) = -1 2662 * StringUtils.indexOf("", *, *) = -1 2663 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2664 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2665 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2666 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2667 * </pre> 2668 * 2669 * @param seq the CharSequence to check, may be null. 2670 * @param searchChar the character to find. 2671 * @param startPos the start position, negative treated as zero. 2672 * @return the first index of the search character (always ≥ startPos), -1 if no match or {@code null} string input. 2673 * @since 2.0 2674 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2675 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2676 */ 2677 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2678 if (isEmpty(seq)) { 2679 return INDEX_NOT_FOUND; 2680 } 2681 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2682 } 2683 2684 /** 2685 * Search a CharSequence to find the first index of any character in the given set of characters. 2686 * 2687 * <p> 2688 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2689 * </p> 2690 * 2691 * <pre> 2692 * StringUtils.indexOfAny(null, *) = -1 2693 * StringUtils.indexOfAny("", *) = -1 2694 * StringUtils.indexOfAny(*, null) = -1 2695 * StringUtils.indexOfAny(*, []) = -1 2696 * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0 2697 * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3 2698 * StringUtils.indexOfAny("aba", ['z']) = -1 2699 * </pre> 2700 * 2701 * @param cs the CharSequence to check, may be null. 2702 * @param searchChars the chars to search for, may be null. 2703 * @return the index of any of the chars, -1 if no match or null input. 2704 * @since 2.0 2705 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2706 */ 2707 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2708 return indexOfAny(cs, 0, searchChars); 2709 } 2710 2711 /** 2712 * Find the first index of any of a set of potential substrings. 2713 * 2714 * <p> 2715 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. A {@code null} search array entry 2716 * will be ignored, but a search array containing "" will return {@code 0} if {@code str} is not null. This method uses {@link String#indexOf(String)} if 2717 * possible. 2718 * </p> 2719 * 2720 * <pre> 2721 * StringUtils.indexOfAny(null, *) = -1 2722 * StringUtils.indexOfAny(*, null) = -1 2723 * StringUtils.indexOfAny(*, []) = -1 2724 * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"]) = 2 2725 * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"]) = 2 2726 * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"]) = -1 2727 * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1 2728 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 2729 * StringUtils.indexOfAny("", [""]) = 0 2730 * StringUtils.indexOfAny("", ["a"]) = -1 2731 * </pre> 2732 * 2733 * @param str the CharSequence to check, may be null. 2734 * @param searchStrs the CharSequences to search for, may be null. 2735 * @return the first index of any of the searchStrs in str, -1 if no match. 2736 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2737 */ 2738 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2739 if (str == null || searchStrs == null) { 2740 return INDEX_NOT_FOUND; 2741 } 2742 // String's can't have a MAX_VALUEth index. 2743 int ret = Integer.MAX_VALUE; 2744 int tmp; 2745 for (final CharSequence search : searchStrs) { 2746 if (search == null) { 2747 continue; 2748 } 2749 tmp = CharSequenceUtils.indexOf(str, search, 0); 2750 if (tmp == INDEX_NOT_FOUND) { 2751 continue; 2752 } 2753 if (tmp < ret) { 2754 ret = tmp; 2755 } 2756 } 2757 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2758 } 2759 2760 /** 2761 * Search a CharSequence to find the first index of any character in the given set of characters. 2762 * 2763 * <p> 2764 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2765 * </p> 2766 * <p> 2767 * The following is the same as {@code indexOfAny(cs, 0, searchChars)}. 2768 * </p> 2769 * <pre> 2770 * StringUtils.indexOfAny(null, 0, *) = -1 2771 * StringUtils.indexOfAny("", 0, *) = -1 2772 * StringUtils.indexOfAny(*, 0, null) = -1 2773 * StringUtils.indexOfAny(*, 0, []) = -1 2774 * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0 2775 * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3 2776 * StringUtils.indexOfAny("aba", 0, ['z']) = -1 2777 * </pre> 2778 * 2779 * @param cs the CharSequence to check, may be null. 2780 * @param csStart Start searching the input {@code cs} at this index. 2781 * @param searchChars the chars to search for, may be null. 2782 * @return the index of any of the chars, -1 if no match or null input. 2783 * @since 2.0 2784 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2785 */ 2786 public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) { 2787 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2788 return INDEX_NOT_FOUND; 2789 } 2790 final int csLen = cs.length(); 2791 final int csLast = csLen - 1; 2792 final int searchLen = searchChars.length; 2793 final int searchLast = searchLen - 1; 2794 for (int i = csStart; i < csLen; i++) { 2795 final char ch = cs.charAt(i); 2796 for (int j = 0; j < searchLen; j++) { 2797 if (searchChars[j] == ch) { 2798 // ch is a supplementary character 2799 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch) || searchChars[j + 1] == cs.charAt(i + 1)) { 2800 return i; 2801 } 2802 } 2803 } 2804 } 2805 return INDEX_NOT_FOUND; 2806 } 2807 2808 /** 2809 * Search a CharSequence to find the first index of any character in the given set of characters. 2810 * 2811 * <p> 2812 * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}. 2813 * </p> 2814 * 2815 * <pre> 2816 * StringUtils.indexOfAny(null, *) = -1 2817 * StringUtils.indexOfAny("", *) = -1 2818 * StringUtils.indexOfAny(*, null) = -1 2819 * StringUtils.indexOfAny(*, "") = -1 2820 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2821 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2822 * StringUtils.indexOfAny("aba", "z") = -1 2823 * </pre> 2824 * 2825 * @param cs the CharSequence to check, may be null. 2826 * @param searchChars the chars to search for, may be null. 2827 * @return the index of any of the chars, -1 if no match or null input. 2828 * @since 2.0 2829 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2830 */ 2831 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2832 if (isEmpty(cs) || isEmpty(searchChars)) { 2833 return INDEX_NOT_FOUND; 2834 } 2835 return indexOfAny(cs, searchChars.toCharArray()); 2836 } 2837 2838 /** 2839 * Searches a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in cs such that 2840 * (cs.codePointAt(i) â { x â codepoints(searchChars) }) 2841 * 2842 * <p> 2843 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2844 * </p> 2845 * 2846 * <pre> 2847 * StringUtils.indexOfAnyBut(null, *) = -1 2848 * StringUtils.indexOfAnyBut("", *) = -1 2849 * StringUtils.indexOfAnyBut(*, null) = -1 2850 * StringUtils.indexOfAnyBut(*, []) = -1 2851 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2852 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2853 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2854 * </pre> 2855 * 2856 * @param cs the CharSequence to check, may be null. 2857 * @param searchChars the chars to search for, may be null. 2858 * @return the index of any of the chars, -1 if no match or null input. 2859 * @since 2.0 2860 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2861 */ 2862 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2863 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2864 return INDEX_NOT_FOUND; 2865 } 2866 return indexOfAnyBut(cs, CharBuffer.wrap(searchChars)); 2867 } 2868 2869 /** 2870 * Search a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in seq such that 2871 * (seq.codePointAt(i) â { x â codepoints(searchChars) }) 2872 * 2873 * <p> 2874 * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}. 2875 * </p> 2876 * 2877 * <pre> 2878 * StringUtils.indexOfAnyBut(null, *) = -1 2879 * StringUtils.indexOfAnyBut("", *) = -1 2880 * StringUtils.indexOfAnyBut(*, null) = -1 2881 * StringUtils.indexOfAnyBut(*, "") = -1 2882 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2883 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2884 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2885 * </pre> 2886 * 2887 * @param seq the CharSequence to check, may be null. 2888 * @param searchChars the chars to search for, may be null. 2889 * @return the index of any of the chars, -1 if no match or null input. 2890 * @since 2.0 2891 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2892 */ 2893 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2894 if (isEmpty(seq) || isEmpty(searchChars)) { 2895 return INDEX_NOT_FOUND; 2896 } 2897 final Set<Integer> searchSetCodePoints = searchChars.codePoints() 2898 .boxed().collect(Collectors.toSet()); 2899 // advance character index from one interpreted codepoint to the next 2900 for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) { 2901 final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx); 2902 if (!searchSetCodePoints.contains(curSeqCodePoint)) { 2903 return curSeqCharIdx; 2904 } 2905 curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates 2906 } 2907 return INDEX_NOT_FOUND; 2908 } 2909 2910 /** 2911 * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ. 2912 * 2913 * <p> 2914 * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7} 2915 * </p> 2916 * 2917 * <pre> 2918 * StringUtils.indexOfDifference(null) = -1 2919 * StringUtils.indexOfDifference(new String[] {}) = -1 2920 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2921 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2922 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2923 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2924 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2925 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2926 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2927 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2928 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2929 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2930 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2931 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2932 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2933 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2934 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2935 * </pre> 2936 * 2937 * @param css array of CharSequences, entries may be null. 2938 * @return the index where the strings begin to differ; -1 if they are all equal. 2939 * @since 2.4 2940 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2941 */ 2942 public static int indexOfDifference(final CharSequence... css) { 2943 if (ArrayUtils.getLength(css) <= 1) { 2944 return INDEX_NOT_FOUND; 2945 } 2946 boolean anyStringNull = false; 2947 boolean allStringsNull = true; 2948 final int arrayLen = css.length; 2949 int shortestStrLen = Integer.MAX_VALUE; 2950 int longestStrLen = 0; 2951 // find the min and max string lengths; this avoids checking to make 2952 // sure we are not exceeding the length of the string each time through 2953 // the bottom loop. 2954 for (final CharSequence cs : css) { 2955 if (cs == null) { 2956 anyStringNull = true; 2957 shortestStrLen = 0; 2958 } else { 2959 allStringsNull = false; 2960 shortestStrLen = Math.min(cs.length(), shortestStrLen); 2961 longestStrLen = Math.max(cs.length(), longestStrLen); 2962 } 2963 } 2964 // handle lists containing all nulls or all empty strings 2965 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 2966 return INDEX_NOT_FOUND; 2967 } 2968 // handle lists containing some nulls or some empty strings 2969 if (shortestStrLen == 0) { 2970 return 0; 2971 } 2972 // find the position with the first difference across all strings 2973 int firstDiff = -1; 2974 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 2975 final char comparisonChar = css[0].charAt(stringPos); 2976 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 2977 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 2978 firstDiff = stringPos; 2979 break; 2980 } 2981 } 2982 if (firstDiff != -1) { 2983 break; 2984 } 2985 } 2986 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 2987 // we compared all of the characters up to the length of the 2988 // shortest string and didn't find a match, but the string lengths 2989 // vary, so return the length of the shortest string. 2990 return shortestStrLen; 2991 } 2992 return firstDiff; 2993 } 2994 2995 /** 2996 * Compares two CharSequences, and returns the index at which the CharSequences begin to differ. 2997 * 2998 * <p> 2999 * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7} 3000 * </p> 3001 * 3002 * <pre> 3003 * StringUtils.indexOfDifference(null, null) = -1 3004 * StringUtils.indexOfDifference("", "") = -1 3005 * StringUtils.indexOfDifference("", "abc") = 0 3006 * StringUtils.indexOfDifference("abc", "") = 0 3007 * StringUtils.indexOfDifference("abc", "abc") = -1 3008 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3009 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3010 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3011 * </pre> 3012 * 3013 * @param cs1 the first CharSequence, may be null. 3014 * @param cs2 the second CharSequence, may be null. 3015 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal. 3016 * @since 2.0 3017 * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence) 3018 */ 3019 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3020 if (cs1 == cs2) { 3021 return INDEX_NOT_FOUND; 3022 } 3023 if (cs1 == null || cs2 == null) { 3024 return 0; 3025 } 3026 int i; 3027 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3028 if (cs1.charAt(i) != cs2.charAt(i)) { 3029 break; 3030 } 3031 } 3032 if (i < cs2.length() || i < cs1.length()) { 3033 return i; 3034 } 3035 return INDEX_NOT_FOUND; 3036 } 3037 3038 /** 3039 * Case in-sensitive find of the first index within a CharSequence. 3040 * 3041 * <p> 3042 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3043 * start position greater than the string length only matches an empty search CharSequence. 3044 * </p> 3045 * 3046 * <pre> 3047 * StringUtils.indexOfIgnoreCase(null, *) = -1 3048 * StringUtils.indexOfIgnoreCase(*, null) = -1 3049 * StringUtils.indexOfIgnoreCase("", "") = 0 3050 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3051 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3052 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3053 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3054 * </pre> 3055 * 3056 * @param str the CharSequence to check, may be null. 3057 * @param searchStr the CharSequence to find, may be null. 3058 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 3059 * @since 2.5 3060 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3061 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)} 3062 */ 3063 @Deprecated 3064 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3065 return Strings.CI.indexOf(str, searchStr); 3066 } 3067 3068 /** 3069 * Case in-sensitive find of the first index within a CharSequence from the specified position. 3070 * 3071 * <p> 3072 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3073 * start position greater than the string length only matches an empty search CharSequence. 3074 * </p> 3075 * 3076 * <pre> 3077 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3078 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3079 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3080 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3081 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3082 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3083 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3084 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3085 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3086 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3087 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3088 * </pre> 3089 * 3090 * @param str the CharSequence to check, may be null. 3091 * @param searchStr the CharSequence to find, may be null. 3092 * @param startPos the start position, negative treated as zero. 3093 * @return the first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 3094 * @since 2.5 3095 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3096 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)} 3097 */ 3098 @Deprecated 3099 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 3100 return Strings.CI.indexOf(str, searchStr, startPos); 3101 } 3102 3103 /** 3104 * Tests if all of the CharSequences are empty (""), null or whitespace only. 3105 * 3106 * <p> 3107 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3108 * </p> 3109 * 3110 * <pre> 3111 * StringUtils.isAllBlank(null) = true 3112 * StringUtils.isAllBlank(null, "foo") = false 3113 * StringUtils.isAllBlank(null, null) = true 3114 * StringUtils.isAllBlank("", "bar") = false 3115 * StringUtils.isAllBlank("bob", "") = false 3116 * StringUtils.isAllBlank(" bob ", null) = false 3117 * StringUtils.isAllBlank(" ", "bar") = false 3118 * StringUtils.isAllBlank("foo", "bar") = false 3119 * StringUtils.isAllBlank(new String[] {}) = true 3120 * </pre> 3121 * 3122 * @param css the CharSequences to check, may be null or empty. 3123 * @return {@code true} if all of the CharSequences are empty or null or whitespace only. 3124 * @since 3.6 3125 */ 3126 public static boolean isAllBlank(final CharSequence... css) { 3127 if (ArrayUtils.isEmpty(css)) { 3128 return true; 3129 } 3130 for (final CharSequence cs : css) { 3131 if (isNotBlank(cs)) { 3132 return false; 3133 } 3134 } 3135 return true; 3136 } 3137 3138 /** 3139 * Tests if all of the CharSequences are empty ("") or null. 3140 * 3141 * <pre> 3142 * StringUtils.isAllEmpty(null) = true 3143 * StringUtils.isAllEmpty(null, "") = true 3144 * StringUtils.isAllEmpty(new String[] {}) = true 3145 * StringUtils.isAllEmpty(null, "foo") = false 3146 * StringUtils.isAllEmpty("", "bar") = false 3147 * StringUtils.isAllEmpty("bob", "") = false 3148 * StringUtils.isAllEmpty(" bob ", null) = false 3149 * StringUtils.isAllEmpty(" ", "bar") = false 3150 * StringUtils.isAllEmpty("foo", "bar") = false 3151 * </pre> 3152 * 3153 * @param css the CharSequences to check, may be null or empty. 3154 * @return {@code true} if all of the CharSequences are empty or null. 3155 * @since 3.6 3156 */ 3157 public static boolean isAllEmpty(final CharSequence... css) { 3158 if (ArrayUtils.isEmpty(css)) { 3159 return true; 3160 } 3161 for (final CharSequence cs : css) { 3162 if (isNotEmpty(cs)) { 3163 return false; 3164 } 3165 } 3166 return true; 3167 } 3168 3169 /** 3170 * Tests if the CharSequence contains only lowercase characters. 3171 * 3172 * <p> 3173 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3174 * </p> 3175 * 3176 * <pre> 3177 * StringUtils.isAllLowerCase(null) = false 3178 * StringUtils.isAllLowerCase("") = false 3179 * StringUtils.isAllLowerCase(" ") = false 3180 * StringUtils.isAllLowerCase("abc") = true 3181 * StringUtils.isAllLowerCase("abC") = false 3182 * StringUtils.isAllLowerCase("ab c") = false 3183 * StringUtils.isAllLowerCase("ab1c") = false 3184 * StringUtils.isAllLowerCase("ab/c") = false 3185 * </pre> 3186 * 3187 * @param cs the CharSequence to check, may be null. 3188 * @return {@code true} if only contains lowercase characters, and is non-null. 3189 * @since 2.5 3190 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3191 */ 3192 public static boolean isAllLowerCase(final CharSequence cs) { 3193 if (isEmpty(cs)) { 3194 return false; 3195 } 3196 final int sz = cs.length(); 3197 for (int i = 0; i < sz; i++) { 3198 if (!Character.isLowerCase(cs.charAt(i))) { 3199 return false; 3200 } 3201 } 3202 return true; 3203 } 3204 3205 /** 3206 * Tests if the CharSequence contains only uppercase characters. 3207 * 3208 * <p>{@code null} will return {@code false}. 3209 * An empty String (length()=0) will return {@code false}.</p> 3210 * 3211 * <pre> 3212 * StringUtils.isAllUpperCase(null) = false 3213 * StringUtils.isAllUpperCase("") = false 3214 * StringUtils.isAllUpperCase(" ") = false 3215 * StringUtils.isAllUpperCase("ABC") = true 3216 * StringUtils.isAllUpperCase("aBC") = false 3217 * StringUtils.isAllUpperCase("A C") = false 3218 * StringUtils.isAllUpperCase("A1C") = false 3219 * StringUtils.isAllUpperCase("A/C") = false 3220 * </pre> 3221 * 3222 * @param cs the CharSequence to check, may be null. 3223 * @return {@code true} if only contains uppercase characters, and is non-null. 3224 * @since 2.5 3225 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3226 */ 3227 public static boolean isAllUpperCase(final CharSequence cs) { 3228 if (isEmpty(cs)) { 3229 return false; 3230 } 3231 final int sz = cs.length(); 3232 for (int i = 0; i < sz; i++) { 3233 if (!Character.isUpperCase(cs.charAt(i))) { 3234 return false; 3235 } 3236 } 3237 return true; 3238 } 3239 3240 /** 3241 * Tests if the CharSequence contains only Unicode letters. 3242 * 3243 * <p> 3244 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3245 * </p> 3246 * 3247 * <pre> 3248 * StringUtils.isAlpha(null) = false 3249 * StringUtils.isAlpha("") = false 3250 * StringUtils.isAlpha(" ") = false 3251 * StringUtils.isAlpha("abc") = true 3252 * StringUtils.isAlpha("ab2c") = false 3253 * StringUtils.isAlpha("ab-c") = false 3254 * </pre> 3255 * 3256 * @param cs the CharSequence to check, may be null. 3257 * @return {@code true} if only contains letters, and is non-null. 3258 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3259 * @since 3.0 Changed "" to return false and not true 3260 */ 3261 public static boolean isAlpha(final CharSequence cs) { 3262 if (isEmpty(cs)) { 3263 return false; 3264 } 3265 final int sz = cs.length(); 3266 for (int i = 0; i < sz; i++) { 3267 if (!Character.isLetter(cs.charAt(i))) { 3268 return false; 3269 } 3270 } 3271 return true; 3272 } 3273 3274 /** 3275 * Tests if the CharSequence contains only Unicode letters or digits. 3276 * 3277 * <p> 3278 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3279 * </p> 3280 * 3281 * <pre> 3282 * StringUtils.isAlphanumeric(null) = false 3283 * StringUtils.isAlphanumeric("") = false 3284 * StringUtils.isAlphanumeric(" ") = false 3285 * StringUtils.isAlphanumeric("abc") = true 3286 * StringUtils.isAlphanumeric("ab c") = false 3287 * StringUtils.isAlphanumeric("ab2c") = true 3288 * StringUtils.isAlphanumeric("ab-c") = false 3289 * </pre> 3290 * 3291 * @param cs the CharSequence to check, may be null. 3292 * @return {@code true} if only contains letters or digits, and is non-null. 3293 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3294 * @since 3.0 Changed "" to return false and not true 3295 */ 3296 public static boolean isAlphanumeric(final CharSequence cs) { 3297 if (isEmpty(cs)) { 3298 return false; 3299 } 3300 final int sz = cs.length(); 3301 for (int i = 0; i < sz; i++) { 3302 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3303 return false; 3304 } 3305 } 3306 return true; 3307 } 3308 3309 /** 3310 * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}). 3311 * 3312 * <p> 3313 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3314 * </p> 3315 * 3316 * <pre> 3317 * StringUtils.isAlphanumericSpace(null) = false 3318 * StringUtils.isAlphanumericSpace("") = true 3319 * StringUtils.isAlphanumericSpace(" ") = true 3320 * StringUtils.isAlphanumericSpace("abc") = true 3321 * StringUtils.isAlphanumericSpace("ab c") = true 3322 * StringUtils.isAlphanumericSpace("ab2c") = true 3323 * StringUtils.isAlphanumericSpace("ab-c") = false 3324 * </pre> 3325 * 3326 * @param cs the CharSequence to check, may be null. 3327 * @return {@code true} if only contains letters, digits or space, and is non-null. 3328 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3329 */ 3330 public static boolean isAlphanumericSpace(final CharSequence cs) { 3331 if (cs == null) { 3332 return false; 3333 } 3334 final int sz = cs.length(); 3335 for (int i = 0; i < sz; i++) { 3336 final char nowChar = cs.charAt(i); 3337 if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar)) { 3338 return false; 3339 } 3340 } 3341 return true; 3342 } 3343 3344 /** 3345 * Tests if the CharSequence contains only Unicode letters and space (' '). 3346 * 3347 * <p> 3348 * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}. 3349 * </p> 3350 * 3351 * <pre> 3352 * StringUtils.isAlphaSpace(null) = false 3353 * StringUtils.isAlphaSpace("") = true 3354 * StringUtils.isAlphaSpace(" ") = true 3355 * StringUtils.isAlphaSpace("abc") = true 3356 * StringUtils.isAlphaSpace("ab c") = true 3357 * StringUtils.isAlphaSpace("ab2c") = false 3358 * StringUtils.isAlphaSpace("ab-c") = false 3359 * </pre> 3360 * 3361 * @param cs the CharSequence to check, may be null. 3362 * @return {@code true} if only contains letters and space, and is non-null. 3363 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3364 */ 3365 public static boolean isAlphaSpace(final CharSequence cs) { 3366 if (cs == null) { 3367 return false; 3368 } 3369 final int sz = cs.length(); 3370 for (int i = 0; i < sz; i++) { 3371 final char nowChar = cs.charAt(i); 3372 if (nowChar != ' ' && !Character.isLetter(nowChar)) { 3373 return false; 3374 } 3375 } 3376 return true; 3377 } 3378 3379 /** 3380 * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}). 3381 * 3382 * <p> 3383 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3384 * </p> 3385 * 3386 * <pre> 3387 * StringUtils.isAnyBlank((String) null) = true 3388 * StringUtils.isAnyBlank((String[]) null) = false 3389 * StringUtils.isAnyBlank(null, "foo") = true 3390 * StringUtils.isAnyBlank(null, null) = true 3391 * StringUtils.isAnyBlank("", "bar") = true 3392 * StringUtils.isAnyBlank("bob", "") = true 3393 * StringUtils.isAnyBlank(" bob ", null) = true 3394 * StringUtils.isAnyBlank(" ", "bar") = true 3395 * StringUtils.isAnyBlank(new String[] {}) = false 3396 * StringUtils.isAnyBlank(new String[]{""}) = true 3397 * StringUtils.isAnyBlank("foo", "bar") = false 3398 * </pre> 3399 * 3400 * @param css the CharSequences to check, may be null or empty. 3401 * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}). 3402 * @see #isBlank(CharSequence) 3403 * @since 3.2 3404 */ 3405 public static boolean isAnyBlank(final CharSequence... css) { 3406 if (ArrayUtils.isEmpty(css)) { 3407 return false; 3408 } 3409 for (final CharSequence cs : css) { 3410 if (isBlank(cs)) { 3411 return true; 3412 } 3413 } 3414 return false; 3415 } 3416 3417 /** 3418 * Tests if any of the CharSequences are empty ("") or null. 3419 * 3420 * <pre> 3421 * StringUtils.isAnyEmpty((String) null) = true 3422 * StringUtils.isAnyEmpty((String[]) null) = false 3423 * StringUtils.isAnyEmpty(null, "foo") = true 3424 * StringUtils.isAnyEmpty("", "bar") = true 3425 * StringUtils.isAnyEmpty("bob", "") = true 3426 * StringUtils.isAnyEmpty(" bob ", null) = true 3427 * StringUtils.isAnyEmpty(" ", "bar") = false 3428 * StringUtils.isAnyEmpty("foo", "bar") = false 3429 * StringUtils.isAnyEmpty(new String[]{}) = false 3430 * StringUtils.isAnyEmpty(new String[]{""}) = true 3431 * </pre> 3432 * 3433 * @param css the CharSequences to check, may be null or empty. 3434 * @return {@code true} if any of the CharSequences are empty or null. 3435 * @since 3.2 3436 */ 3437 public static boolean isAnyEmpty(final CharSequence... css) { 3438 if (ArrayUtils.isEmpty(css)) { 3439 return false; 3440 } 3441 for (final CharSequence cs : css) { 3442 if (isEmpty(cs)) { 3443 return true; 3444 } 3445 } 3446 return false; 3447 } 3448 3449 /** 3450 * Tests if the CharSequence contains only ASCII printable characters. 3451 * 3452 * <p> 3453 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3454 * </p> 3455 * 3456 * <pre> 3457 * StringUtils.isAsciiPrintable(null) = false 3458 * StringUtils.isAsciiPrintable("") = true 3459 * StringUtils.isAsciiPrintable(" ") = true 3460 * StringUtils.isAsciiPrintable("Ceki") = true 3461 * StringUtils.isAsciiPrintable("ab2c") = true 3462 * StringUtils.isAsciiPrintable("!ab-c~") = true 3463 * StringUtils.isAsciiPrintable("\u0020") = true 3464 * StringUtils.isAsciiPrintable("\u0021") = true 3465 * StringUtils.isAsciiPrintable("\u007e") = true 3466 * StringUtils.isAsciiPrintable("\u007f") = false 3467 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3468 * </pre> 3469 * 3470 * @param cs the CharSequence to check, may be null. 3471 * @return {@code true} if every character is in the range 32 through 126. 3472 * @since 2.1 3473 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3474 */ 3475 public static boolean isAsciiPrintable(final CharSequence cs) { 3476 if (cs == null) { 3477 return false; 3478 } 3479 final int sz = cs.length(); 3480 for (int i = 0; i < sz; i++) { 3481 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3482 return false; 3483 } 3484 } 3485 return true; 3486 } 3487 3488 /** 3489 * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}. 3490 * 3491 * <pre> 3492 * StringUtils.isBlank(null) = true 3493 * StringUtils.isBlank("") = true 3494 * StringUtils.isBlank(" ") = true 3495 * StringUtils.isBlank("bob") = false 3496 * StringUtils.isBlank(" bob ") = false 3497 * </pre> 3498 * 3499 * @param cs the CharSequence to check, may be null. 3500 * @return {@code true} if the CharSequence is null, empty or whitespace only. 3501 * @since 2.0 3502 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3503 */ 3504 public static boolean isBlank(final CharSequence cs) { 3505 final int strLen = length(cs); 3506 if (strLen == 0) { 3507 return true; 3508 } 3509 for (int i = 0; i < strLen; i++) { 3510 if (!Character.isWhitespace(cs.charAt(i))) { 3511 return false; 3512 } 3513 } 3514 return true; 3515 } 3516 3517 /** 3518 * Tests if a CharSequence is empty ("") or null. 3519 * 3520 * <pre> 3521 * StringUtils.isEmpty(null) = true 3522 * StringUtils.isEmpty("") = true 3523 * StringUtils.isEmpty(" ") = false 3524 * StringUtils.isEmpty("bob") = false 3525 * StringUtils.isEmpty(" bob ") = false 3526 * </pre> 3527 * 3528 * <p> 3529 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank(). 3530 * </p> 3531 * 3532 * @param cs the CharSequence to check, may be null. 3533 * @return {@code true} if the CharSequence is empty or null. 3534 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3535 */ 3536 public static boolean isEmpty(final CharSequence cs) { 3537 return cs == null || cs.length() == 0; 3538 } 3539 3540 /** 3541 * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3542 * 3543 * <p> 3544 * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}. 3545 * </p> 3546 * 3547 * <pre> 3548 * StringUtils.isMixedCase(null) = false 3549 * StringUtils.isMixedCase("") = false 3550 * StringUtils.isMixedCase(" ") = false 3551 * StringUtils.isMixedCase("ABC") = false 3552 * StringUtils.isMixedCase("abc") = false 3553 * StringUtils.isMixedCase("aBc") = true 3554 * StringUtils.isMixedCase("A c") = true 3555 * StringUtils.isMixedCase("A1c") = true 3556 * StringUtils.isMixedCase("a/C") = true 3557 * StringUtils.isMixedCase("aC\t") = true 3558 * </pre> 3559 * 3560 * @param cs the CharSequence to check, may be null. 3561 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters. 3562 * @since 3.5 3563 */ 3564 public static boolean isMixedCase(final CharSequence cs) { 3565 if (isEmpty(cs) || cs.length() == 1) { 3566 return false; 3567 } 3568 boolean containsUppercase = false; 3569 boolean containsLowercase = false; 3570 final int sz = cs.length(); 3571 for (int i = 0; i < sz; i++) { 3572 final char nowChar = cs.charAt(i); 3573 if (Character.isUpperCase(nowChar)) { 3574 containsUppercase = true; 3575 } else if (Character.isLowerCase(nowChar)) { 3576 containsLowercase = true; 3577 } 3578 if (containsUppercase && containsLowercase) { 3579 return true; 3580 } 3581 } 3582 return false; 3583 } 3584 3585 /** 3586 * Tests if none of the CharSequences are empty (""), null or whitespace only. 3587 * 3588 * <p> 3589 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3590 * </p> 3591 * 3592 * <pre> 3593 * StringUtils.isNoneBlank((String) null) = false 3594 * StringUtils.isNoneBlank((String[]) null) = true 3595 * StringUtils.isNoneBlank(null, "foo") = false 3596 * StringUtils.isNoneBlank(null, null) = false 3597 * StringUtils.isNoneBlank("", "bar") = false 3598 * StringUtils.isNoneBlank("bob", "") = false 3599 * StringUtils.isNoneBlank(" bob ", null) = false 3600 * StringUtils.isNoneBlank(" ", "bar") = false 3601 * StringUtils.isNoneBlank(new String[] {}) = true 3602 * StringUtils.isNoneBlank(new String[]{""}) = false 3603 * StringUtils.isNoneBlank("foo", "bar") = true 3604 * </pre> 3605 * 3606 * @param css the CharSequences to check, may be null or empty. 3607 * @return {@code true} if none of the CharSequences are empty or null or whitespace only. 3608 * @since 3.2 3609 */ 3610 public static boolean isNoneBlank(final CharSequence... css) { 3611 return !isAnyBlank(css); 3612 } 3613 3614 /** 3615 * Tests if none of the CharSequences are empty ("") or null. 3616 * 3617 * <pre> 3618 * StringUtils.isNoneEmpty((String) null) = false 3619 * StringUtils.isNoneEmpty((String[]) null) = true 3620 * StringUtils.isNoneEmpty(null, "foo") = false 3621 * StringUtils.isNoneEmpty("", "bar") = false 3622 * StringUtils.isNoneEmpty("bob", "") = false 3623 * StringUtils.isNoneEmpty(" bob ", null) = false 3624 * StringUtils.isNoneEmpty(new String[] {}) = true 3625 * StringUtils.isNoneEmpty(new String[]{""}) = false 3626 * StringUtils.isNoneEmpty(" ", "bar") = true 3627 * StringUtils.isNoneEmpty("foo", "bar") = true 3628 * </pre> 3629 * 3630 * @param css the CharSequences to check, may be null or empty. 3631 * @return {@code true} if none of the CharSequences are empty or null. 3632 * @since 3.2 3633 */ 3634 public static boolean isNoneEmpty(final CharSequence... css) { 3635 return !isAnyEmpty(css); 3636 } 3637 3638 /** 3639 * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}). 3640 * 3641 * <p> 3642 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3643 * </p> 3644 * 3645 * <pre> 3646 * StringUtils.isNotBlank(null) = false 3647 * StringUtils.isNotBlank("") = false 3648 * StringUtils.isNotBlank(" ") = false 3649 * StringUtils.isNotBlank("bob") = true 3650 * StringUtils.isNotBlank(" bob ") = true 3651 * </pre> 3652 * 3653 * @param cs the CharSequence to check, may be null. 3654 * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}) or {@code null}). 3655 * @see #isBlank(CharSequence) 3656 * @since 2.0 3657 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3658 */ 3659 public static boolean isNotBlank(final CharSequence cs) { 3660 return !isBlank(cs); 3661 } 3662 3663 /** 3664 * Tests if a CharSequence is not empty ("") and not null. 3665 * 3666 * <pre> 3667 * StringUtils.isNotEmpty(null) = false 3668 * StringUtils.isNotEmpty("") = false 3669 * StringUtils.isNotEmpty(" ") = true 3670 * StringUtils.isNotEmpty("bob") = true 3671 * StringUtils.isNotEmpty(" bob ") = true 3672 * </pre> 3673 * 3674 * @param cs the CharSequence to check, may be null. 3675 * @return {@code true} if the CharSequence is not empty and not null. 3676 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3677 */ 3678 public static boolean isNotEmpty(final CharSequence cs) { 3679 return !isEmpty(cs); 3680 } 3681 3682 /** 3683 * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false. 3684 * 3685 * <p> 3686 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3687 * </p> 3688 * 3689 * <p> 3690 * Note that the method does not allow for a leading sign, either positive or negative. Also, if a String passes the numeric test, it may still generate a 3691 * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively. 3692 * </p> 3693 * 3694 * <pre> 3695 * StringUtils.isNumeric(null) = false 3696 * StringUtils.isNumeric("") = false 3697 * StringUtils.isNumeric(" ") = false 3698 * StringUtils.isNumeric("123") = true 3699 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3700 * StringUtils.isNumeric("12 3") = false 3701 * StringUtils.isNumeric("ab2c") = false 3702 * StringUtils.isNumeric("12-3") = false 3703 * StringUtils.isNumeric("12.3") = false 3704 * StringUtils.isNumeric("-123") = false 3705 * StringUtils.isNumeric("+123") = false 3706 * </pre> 3707 * 3708 * @param cs the CharSequence to check, may be null. 3709 * @return {@code true} if only contains digits, and is non-null. 3710 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3711 * @since 3.0 Changed "" to return false and not true 3712 */ 3713 public static boolean isNumeric(final CharSequence cs) { 3714 if (isEmpty(cs)) { 3715 return false; 3716 } 3717 final int sz = cs.length(); 3718 for (int i = 0; i < sz; i++) { 3719 if (!Character.isDigit(cs.charAt(i))) { 3720 return false; 3721 } 3722 } 3723 return true; 3724 } 3725 3726 /** 3727 * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false. 3728 * 3729 * <p> 3730 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3731 * </p> 3732 * 3733 * <pre> 3734 * StringUtils.isNumericSpace(null) = false 3735 * StringUtils.isNumericSpace("") = true 3736 * StringUtils.isNumericSpace(" ") = true 3737 * StringUtils.isNumericSpace("123") = true 3738 * StringUtils.isNumericSpace("12 3") = true 3739 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3740 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3741 * StringUtils.isNumericSpace("ab2c") = false 3742 * StringUtils.isNumericSpace("12-3") = false 3743 * StringUtils.isNumericSpace("12.3") = false 3744 * </pre> 3745 * 3746 * @param cs the CharSequence to check, may be null. 3747 * @return {@code true} if only contains digits or space, and is non-null. 3748 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3749 */ 3750 public static boolean isNumericSpace(final CharSequence cs) { 3751 if (cs == null) { 3752 return false; 3753 } 3754 final int sz = cs.length(); 3755 for (int i = 0; i < sz; i++) { 3756 final char nowChar = cs.charAt(i); 3757 if (nowChar != ' ' && !Character.isDigit(nowChar)) { 3758 return false; 3759 } 3760 } 3761 return true; 3762 } 3763 3764 /** 3765 * Tests if the CharSequence contains only whitespace. 3766 * 3767 * <p> 3768 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3769 * </p> 3770 * 3771 * <p> 3772 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3773 * </p> 3774 * 3775 * <pre> 3776 * StringUtils.isWhitespace(null) = false 3777 * StringUtils.isWhitespace("") = true 3778 * StringUtils.isWhitespace(" ") = true 3779 * StringUtils.isWhitespace("abc") = false 3780 * StringUtils.isWhitespace("ab2c") = false 3781 * StringUtils.isWhitespace("ab-c") = false 3782 * </pre> 3783 * 3784 * @param cs the CharSequence to check, may be null. 3785 * @return {@code true} if only contains whitespace, and is non-null. 3786 * @since 2.0 3787 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3788 */ 3789 public static boolean isWhitespace(final CharSequence cs) { 3790 if (cs == null) { 3791 return false; 3792 } 3793 final int sz = cs.length(); 3794 for (int i = 0; i < sz; i++) { 3795 if (!Character.isWhitespace(cs.charAt(i))) { 3796 return false; 3797 } 3798 } 3799 return true; 3800 } 3801 3802 /** 3803 * Joins the elements of the provided array into a single String containing the provided list of elements. 3804 * 3805 * <p> 3806 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 3807 * </p> 3808 * 3809 * <pre> 3810 * StringUtils.join(null, *) = null 3811 * StringUtils.join([], *) = "" 3812 * StringUtils.join([null], *) = "" 3813 * StringUtils.join([false, false], ';') = "false;false" 3814 * </pre> 3815 * 3816 * @param array the array of values to join together, may be null. 3817 * @param delimiter the separator character to use. 3818 * @return the joined String, {@code null} if null array input. 3819 * @since 3.12.0 3820 */ 3821 public static String join(final boolean[] array, final char delimiter) { 3822 if (array == null) { 3823 return null; 3824 } 3825 return join(array, delimiter, 0, array.length); 3826 } 3827 3828 /** 3829 * Joins the elements of the provided array into a single String containing the provided list of elements. 3830 * 3831 * <p> 3832 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3833 * by empty strings. 3834 * </p> 3835 * 3836 * <pre> 3837 * StringUtils.join(null, *) = null 3838 * StringUtils.join([], *) = "" 3839 * StringUtils.join([null], *) = "" 3840 * StringUtils.join([true, false, true], ';') = "true;false;true" 3841 * </pre> 3842 * 3843 * @param array 3844 * the array of values to join together, may be null. 3845 * @param delimiter 3846 * the separator character to use. 3847 * @param startIndex 3848 * the first index to start joining from. It is an error to pass in a start index past the end of the 3849 * array. 3850 * @param endIndex 3851 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3852 * the array. 3853 * @return the joined String, {@code null} if null array input. 3854 * @since 3.12.0 3855 */ 3856 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3857 if (array == null) { 3858 return null; 3859 } 3860 if (endIndex - startIndex <= 0) { 3861 return EMPTY; 3862 } 3863 final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1); 3864 for (int i = startIndex; i < endIndex; i++) { 3865 stringBuilder 3866 .append(array[i]) 3867 .append(delimiter); 3868 } 3869 return stringBuilder.substring(0, stringBuilder.length() - 1); 3870 } 3871 3872 /** 3873 * Joins the elements of the provided array into a single String containing the provided list of elements. 3874 * 3875 * <p> 3876 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3877 * by empty strings. 3878 * </p> 3879 * 3880 * <pre> 3881 * StringUtils.join(null, *) = null 3882 * StringUtils.join([], *) = "" 3883 * StringUtils.join([null], *) = "" 3884 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3885 * StringUtils.join([1, 2, 3], null) = "123" 3886 * </pre> 3887 * 3888 * @param array 3889 * the array of values to join together, may be null. 3890 * @param delimiter 3891 * the separator character to use. 3892 * @return the joined String, {@code null} if null array input. 3893 * @since 3.2 3894 */ 3895 public static String join(final byte[] array, final char delimiter) { 3896 if (array == null) { 3897 return null; 3898 } 3899 return join(array, delimiter, 0, array.length); 3900 } 3901 3902 /** 3903 * Joins the elements of the provided array into a single String containing the provided list of elements. 3904 * 3905 * <p> 3906 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3907 * by empty strings. 3908 * </p> 3909 * 3910 * <pre> 3911 * StringUtils.join(null, *) = null 3912 * StringUtils.join([], *) = "" 3913 * StringUtils.join([null], *) = "" 3914 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3915 * StringUtils.join([1, 2, 3], null) = "123" 3916 * </pre> 3917 * 3918 * @param array 3919 * the array of values to join together, may be null. 3920 * @param delimiter 3921 * the separator character to use. 3922 * @param startIndex 3923 * the first index to start joining from. It is an error to pass in a start index past the end of the 3924 * array. 3925 * @param endIndex 3926 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3927 * the array. 3928 * @return the joined String, {@code null} if null array input. 3929 * @since 3.2 3930 */ 3931 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 3932 if (array == null) { 3933 return null; 3934 } 3935 if (endIndex - startIndex <= 0) { 3936 return EMPTY; 3937 } 3938 final StringBuilder stringBuilder = new StringBuilder(); 3939 for (int i = startIndex; i < endIndex; i++) { 3940 stringBuilder 3941 .append(array[i]) 3942 .append(delimiter); 3943 } 3944 return stringBuilder.substring(0, stringBuilder.length() - 1); 3945 } 3946 3947 /** 3948 * Joins the elements of the provided array into a single String containing the provided list of elements. 3949 * 3950 * <p> 3951 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3952 * by empty strings. 3953 * </p> 3954 * 3955 * <pre> 3956 * StringUtils.join(null, *) = null 3957 * StringUtils.join([], *) = "" 3958 * StringUtils.join([null], *) = "" 3959 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3960 * StringUtils.join([1, 2, 3], null) = "123" 3961 * </pre> 3962 * 3963 * @param array 3964 * the array of values to join together, may be null. 3965 * @param delimiter 3966 * the separator character to use. 3967 * @return the joined String, {@code null} if null array input. 3968 * @since 3.2 3969 */ 3970 public static String join(final char[] array, final char delimiter) { 3971 if (array == null) { 3972 return null; 3973 } 3974 return join(array, delimiter, 0, array.length); 3975 } 3976 3977 /** 3978 * Joins the elements of the provided array into a single String containing the provided list of elements. 3979 * 3980 * <p> 3981 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3982 * by empty strings. 3983 * </p> 3984 * 3985 * <pre> 3986 * StringUtils.join(null, *) = null 3987 * StringUtils.join([], *) = "" 3988 * StringUtils.join([null], *) = "" 3989 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3990 * StringUtils.join([1, 2, 3], null) = "123" 3991 * </pre> 3992 * 3993 * @param array 3994 * the array of values to join together, may be null. 3995 * @param delimiter 3996 * the separator character to use. 3997 * @param startIndex 3998 * the first index to start joining from. It is an error to pass in a start index past the end of the 3999 * array. 4000 * @param endIndex 4001 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4002 * the array. 4003 * @return the joined String, {@code null} if null array input. 4004 * @since 3.2 4005 */ 4006 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4007 if (array == null) { 4008 return null; 4009 } 4010 if (endIndex - startIndex <= 0) { 4011 return EMPTY; 4012 } 4013 final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1); 4014 for (int i = startIndex; i < endIndex; i++) { 4015 stringBuilder 4016 .append(array[i]) 4017 .append(delimiter); 4018 } 4019 return stringBuilder.substring(0, stringBuilder.length() - 1); 4020 } 4021 4022 /** 4023 * Joins the elements of the provided array into a single String containing the provided list of elements. 4024 * 4025 * <p> 4026 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4027 * by empty strings. 4028 * </p> 4029 * 4030 * <pre> 4031 * StringUtils.join(null, *) = null 4032 * StringUtils.join([], *) = "" 4033 * StringUtils.join([null], *) = "" 4034 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4035 * StringUtils.join([1, 2, 3], null) = "123" 4036 * </pre> 4037 * 4038 * @param array 4039 * the array of values to join together, may be null. 4040 * @param delimiter 4041 * the separator character to use. 4042 * @return the joined String, {@code null} if null array input. 4043 * @since 3.2 4044 */ 4045 public static String join(final double[] array, final char delimiter) { 4046 if (array == null) { 4047 return null; 4048 } 4049 return join(array, delimiter, 0, array.length); 4050 } 4051 4052 /** 4053 * Joins the elements of the provided array into a single String containing the provided list of elements. 4054 * 4055 * <p> 4056 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4057 * by empty strings. 4058 * </p> 4059 * 4060 * <pre> 4061 * StringUtils.join(null, *) = null 4062 * StringUtils.join([], *) = "" 4063 * StringUtils.join([null], *) = "" 4064 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4065 * StringUtils.join([1, 2, 3], null) = "123" 4066 * </pre> 4067 * 4068 * @param array 4069 * the array of values to join together, may be null. 4070 * @param delimiter 4071 * the separator character to use. 4072 * @param startIndex 4073 * the first index to start joining from. It is an error to pass in a start index past the end of the 4074 * array. 4075 * @param endIndex 4076 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4077 * the array. 4078 * @return the joined String, {@code null} if null array input. 4079 * @since 3.2 4080 */ 4081 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4082 if (array == null) { 4083 return null; 4084 } 4085 if (endIndex - startIndex <= 0) { 4086 return EMPTY; 4087 } 4088 final StringBuilder stringBuilder = new StringBuilder(); 4089 for (int i = startIndex; i < endIndex; i++) { 4090 stringBuilder 4091 .append(array[i]) 4092 .append(delimiter); 4093 } 4094 return stringBuilder.substring(0, stringBuilder.length() - 1); 4095 } 4096 4097 /** 4098 * Joins the elements of the provided array into a single String containing the provided list of elements. 4099 * 4100 * <p> 4101 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4102 * by empty strings. 4103 * </p> 4104 * 4105 * <pre> 4106 * StringUtils.join(null, *) = null 4107 * StringUtils.join([], *) = "" 4108 * StringUtils.join([null], *) = "" 4109 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4110 * StringUtils.join([1, 2, 3], null) = "123" 4111 * </pre> 4112 * 4113 * @param array 4114 * the array of values to join together, may be null. 4115 * @param delimiter 4116 * the separator character to use. 4117 * @return the joined String, {@code null} if null array input 4118 * @since 3.2 4119 */ 4120 public static String join(final float[] array, final char delimiter) { 4121 if (array == null) { 4122 return null; 4123 } 4124 return join(array, delimiter, 0, array.length); 4125 } 4126 4127 /** 4128 * Joins the elements of the provided array into a single String containing the provided list of elements. 4129 * 4130 * <p> 4131 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4132 * by empty strings. 4133 * </p> 4134 * 4135 * <pre> 4136 * StringUtils.join(null, *) = null 4137 * StringUtils.join([], *) = "" 4138 * StringUtils.join([null], *) = "" 4139 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4140 * StringUtils.join([1, 2, 3], null) = "123" 4141 * </pre> 4142 * 4143 * @param array 4144 * the array of values to join together, may be null. 4145 * @param delimiter 4146 * the separator character to use. 4147 * @param startIndex 4148 * the first index to start joining from. It is an error to pass in a start index past the end of the 4149 * array. 4150 * @param endIndex 4151 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4152 * the array. 4153 * @return the joined String, {@code null} if null array input. 4154 * @since 3.2 4155 */ 4156 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4157 if (array == null) { 4158 return null; 4159 } 4160 if (endIndex - startIndex <= 0) { 4161 return EMPTY; 4162 } 4163 final StringBuilder stringBuilder = new StringBuilder(); 4164 for (int i = startIndex; i < endIndex; i++) { 4165 stringBuilder 4166 .append(array[i]) 4167 .append(delimiter); 4168 } 4169 return stringBuilder.substring(0, stringBuilder.length() - 1); 4170 } 4171 4172 /** 4173 * Joins the elements of the provided array into a single String containing the provided list of elements. 4174 * 4175 * <p> 4176 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4177 * by empty strings. 4178 * </p> 4179 * 4180 * <pre> 4181 * StringUtils.join(null, *) = null 4182 * StringUtils.join([], *) = "" 4183 * StringUtils.join([null], *) = "" 4184 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4185 * StringUtils.join([1, 2, 3], null) = "123" 4186 * </pre> 4187 * 4188 * @param array 4189 * the array of values to join together, may be null. 4190 * @param separator 4191 * the separator character to use. 4192 * @return the joined String, {@code null} if null array input. 4193 * @since 3.2 4194 */ 4195 public static String join(final int[] array, final char separator) { 4196 if (array == null) { 4197 return null; 4198 } 4199 return join(array, separator, 0, array.length); 4200 } 4201 4202 /** 4203 * Joins the elements of the provided array into a single String containing the provided list of elements. 4204 * 4205 * <p> 4206 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4207 * by empty strings. 4208 * </p> 4209 * 4210 * <pre> 4211 * StringUtils.join(null, *) = null 4212 * StringUtils.join([], *) = "" 4213 * StringUtils.join([null], *) = "" 4214 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4215 * StringUtils.join([1, 2, 3], null) = "123" 4216 * </pre> 4217 * 4218 * @param array 4219 * the array of values to join together, may be null. 4220 * @param delimiter 4221 * the separator character to use. 4222 * @param startIndex 4223 * the first index to start joining from. It is an error to pass in a start index past the end of the 4224 * array. 4225 * @param endIndex 4226 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4227 * the array. 4228 * @return the joined String, {@code null} if null array input. 4229 * @since 3.2 4230 */ 4231 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4232 if (array == null) { 4233 return null; 4234 } 4235 if (endIndex - startIndex <= 0) { 4236 return EMPTY; 4237 } 4238 final StringBuilder stringBuilder = new StringBuilder(); 4239 for (int i = startIndex; i < endIndex; i++) { 4240 stringBuilder 4241 .append(array[i]) 4242 .append(delimiter); 4243 } 4244 return stringBuilder.substring(0, stringBuilder.length() - 1); 4245 } 4246 4247 /** 4248 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4249 * 4250 * <p> 4251 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4252 * </p> 4253 * 4254 * <p> 4255 * See the examples here: {@link #join(Object[],char)}. 4256 * </p> 4257 * 4258 * @param iterable the {@link Iterable} providing the values to join together, may be null. 4259 * @param separator the separator character to use. 4260 * @return the joined String, {@code null} if null iterator input. 4261 * @since 2.3 4262 */ 4263 public static String join(final Iterable<?> iterable, final char separator) { 4264 return iterable != null ? join(iterable.iterator(), separator) : null; 4265 } 4266 4267 /** 4268 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4269 * 4270 * <p> 4271 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4272 * </p> 4273 * 4274 * <p> 4275 * See the examples here: {@link #join(Object[],String)}. 4276 * </p> 4277 * 4278 * @param iterable the {@link Iterable} providing the values to join together, may be null. 4279 * @param separator the separator character to use, null treated as "". 4280 * @return the joined String, {@code null} if null iterator input. 4281 * @since 2.3 4282 */ 4283 public static String join(final Iterable<?> iterable, final String separator) { 4284 return iterable != null ? join(iterable.iterator(), separator) : null; 4285 } 4286 4287 /** 4288 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4289 * 4290 * <p> 4291 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4292 * </p> 4293 * 4294 * <p> 4295 * See the examples here: {@link #join(Object[],char)}. 4296 * </p> 4297 * 4298 * @param iterator the {@link Iterator} of values to join together, may be null. 4299 * @param separator the separator character to use. 4300 * @return the joined String, {@code null} if null iterator input. 4301 * @since 2.0 4302 */ 4303 public static String join(final Iterator<?> iterator, final char separator) { 4304 // handle null, zero and one elements before building a buffer 4305 if (iterator == null) { 4306 return null; 4307 } 4308 if (!iterator.hasNext()) { 4309 return EMPTY; 4310 } 4311 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString)); 4312 } 4313 4314 /** 4315 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4316 * 4317 * <p> 4318 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4319 * </p> 4320 * 4321 * <p> 4322 * See the examples here: {@link #join(Object[],String)}. 4323 * </p> 4324 * 4325 * @param iterator the {@link Iterator} of values to join together, may be null. 4326 * @param separator the separator character to use, null treated as "". 4327 * @return the joined String, {@code null} if null iterator input. 4328 */ 4329 public static String join(final Iterator<?> iterator, final String separator) { 4330 // handle null, zero and one elements before building a buffer 4331 if (iterator == null) { 4332 return null; 4333 } 4334 if (!iterator.hasNext()) { 4335 return EMPTY; 4336 } 4337 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString)); 4338 } 4339 4340 /** 4341 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4342 * 4343 * <p> 4344 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4345 * </p> 4346 * 4347 * <pre> 4348 * StringUtils.join(null, *) = null 4349 * StringUtils.join([], *) = "" 4350 * StringUtils.join([null], *) = "" 4351 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4352 * StringUtils.join(["a", "b", "c"], null) = "abc" 4353 * StringUtils.join([null, "", "a"], ';') = ";;a" 4354 * </pre> 4355 * 4356 * @param list the {@link List} of values to join together, may be null. 4357 * @param separator the separator character to use. 4358 * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the list. 4359 * @param endIndex the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list. 4360 * @return the joined String, {@code null} if null list input. 4361 * @since 3.8 4362 */ 4363 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4364 if (list == null) { 4365 return null; 4366 } 4367 final int noOfItems = endIndex - startIndex; 4368 if (noOfItems <= 0) { 4369 return EMPTY; 4370 } 4371 final List<?> subList = list.subList(startIndex, endIndex); 4372 return join(subList.iterator(), separator); 4373 } 4374 4375 /** 4376 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4377 * 4378 * <p> 4379 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4380 * </p> 4381 * 4382 * <pre> 4383 * StringUtils.join(null, *) = null 4384 * StringUtils.join([], *) = "" 4385 * StringUtils.join([null], *) = "" 4386 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4387 * StringUtils.join(["a", "b", "c"], null) = "abc" 4388 * StringUtils.join([null, "", "a"], ';') = ";;a" 4389 * </pre> 4390 * 4391 * @param list the {@link List} of values to join together, may be null. 4392 * @param separator the separator character to use. 4393 * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the list. 4394 * @param endIndex the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list. 4395 * @return the joined String, {@code null} if null list input. 4396 * @since 3.8 4397 */ 4398 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4399 if (list == null) { 4400 return null; 4401 } 4402 final int noOfItems = endIndex - startIndex; 4403 if (noOfItems <= 0) { 4404 return EMPTY; 4405 } 4406 final List<?> subList = list.subList(startIndex, endIndex); 4407 return join(subList.iterator(), separator); 4408 } 4409 4410 /** 4411 * Joins the elements of the provided array into a single String containing the provided list of elements. 4412 * 4413 * <p> 4414 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4415 * by empty strings. 4416 * </p> 4417 * 4418 * <pre> 4419 * StringUtils.join(null, *) = null 4420 * StringUtils.join([], *) = "" 4421 * StringUtils.join([null], *) = "" 4422 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4423 * StringUtils.join([1, 2, 3], null) = "123" 4424 * </pre> 4425 * 4426 * @param array 4427 * the array of values to join together, may be null. 4428 * @param separator 4429 * the separator character to use. 4430 * @return the joined String, {@code null} if null array input. 4431 * @since 3.2 4432 */ 4433 public static String join(final long[] array, final char separator) { 4434 if (array == null) { 4435 return null; 4436 } 4437 return join(array, separator, 0, array.length); 4438 } 4439 4440 /** 4441 * Joins the elements of the provided array into a single String containing the provided list of elements. 4442 * 4443 * <p> 4444 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4445 * by empty strings. 4446 * </p> 4447 * 4448 * <pre> 4449 * StringUtils.join(null, *) = null 4450 * StringUtils.join([], *) = "" 4451 * StringUtils.join([null], *) = "" 4452 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4453 * StringUtils.join([1, 2, 3], null) = "123" 4454 * </pre> 4455 * 4456 * @param array 4457 * the array of values to join together, may be null. 4458 * @param delimiter 4459 * the separator character to use. 4460 * @param startIndex 4461 * the first index to start joining from. It is an error to pass in a start index past the end of the 4462 * array. 4463 * @param endIndex 4464 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4465 * the array. 4466 * @return the joined String, {@code null} if null array input. 4467 * @since 3.2 4468 */ 4469 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4470 if (array == null) { 4471 return null; 4472 } 4473 if (endIndex - startIndex <= 0) { 4474 return EMPTY; 4475 } 4476 final StringBuilder stringBuilder = new StringBuilder(); 4477 for (int i = startIndex; i < endIndex; i++) { 4478 stringBuilder 4479 .append(array[i]) 4480 .append(delimiter); 4481 } 4482 return stringBuilder.substring(0, stringBuilder.length() - 1); 4483 } 4484 4485 /** 4486 * Joins the elements of the provided array into a single String containing the provided list of elements. 4487 * 4488 * <p> 4489 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4490 * </p> 4491 * 4492 * <pre> 4493 * StringUtils.join(null, *) = null 4494 * StringUtils.join([], *) = "" 4495 * StringUtils.join([null], *) = "" 4496 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4497 * StringUtils.join(["a", "b", "c"], null) = "abc" 4498 * StringUtils.join([null, "", "a"], ';') = ";;a" 4499 * </pre> 4500 * 4501 * @param array the array of values to join together, may be null. 4502 * @param delimiter the separator character to use. 4503 * @return the joined String, {@code null} if null array input. 4504 * @since 2.0 4505 */ 4506 public static String join(final Object[] array, final char delimiter) { 4507 if (array == null) { 4508 return null; 4509 } 4510 return join(array, delimiter, 0, array.length); 4511 } 4512 4513 /** 4514 * Joins the elements of the provided array into a single String containing the provided list of elements. 4515 * 4516 * <p> 4517 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4518 * </p> 4519 * 4520 * <pre> 4521 * StringUtils.join(null, *) = null 4522 * StringUtils.join([], *) = "" 4523 * StringUtils.join([null], *) = "" 4524 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4525 * StringUtils.join(["a", "b", "c"], null) = "abc" 4526 * StringUtils.join([null, "", "a"], ';') = ";;a" 4527 * </pre> 4528 * 4529 * @param array the array of values to join together, may be null. 4530 * @param delimiter the separator character to use. 4531 * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the array. 4532 * @param endIndex the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the array. 4533 * @return the joined String, {@code null} if null array input. 4534 * @since 2.0 4535 */ 4536 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4537 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4538 } 4539 4540 /** 4541 * Joins the elements of the provided array into a single String containing the provided list of elements. 4542 * 4543 * <p> 4544 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the 4545 * array are represented by empty strings. 4546 * </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(["a", "b", "c"], "") = "abc" 4555 * StringUtils.join([null, "", "a"], ',') = ",,a" 4556 * </pre> 4557 * 4558 * @param array the array of values to join together, may be null. 4559 * @param delimiter the separator character to use, null treated as "". 4560 * @return the joined String, {@code null} if null array input. 4561 */ 4562 public static String join(final Object[] array, final String delimiter) { 4563 return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null; 4564 } 4565 4566 /** 4567 * Joins the elements of the provided array into a single String containing the provided list of elements. 4568 * 4569 * <p> 4570 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the 4571 * array are represented by empty strings. 4572 * </p> 4573 * 4574 * <pre> 4575 * StringUtils.join(null, *, *, *) = null 4576 * StringUtils.join([], *, *, *) = "" 4577 * StringUtils.join([null], *, *, *) = "" 4578 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4579 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4580 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4581 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4582 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4583 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4584 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4585 * </pre> 4586 * 4587 * @param array the array of values to join together, may be null. 4588 * @param delimiter the separator character to use, null treated as "". 4589 * @param startIndex the first index to start joining from. 4590 * @param endIndex the index to stop joining from (exclusive). 4591 * @return the joined String, {@code null} if null array input; or the empty string if {@code endIndex - startIndex <= 0}. The number of joined entries is 4592 * given by {@code endIndex - startIndex}. 4593 * @throws ArrayIndexOutOfBoundsException ife<br> 4594 * {@code startIndex < 0} or <br> 4595 * {@code startIndex >= array.length()} or <br> 4596 * {@code endIndex < 0} or <br> 4597 * {@code endIndex > array.length()} 4598 */ 4599 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4600 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4601 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null; 4602 } 4603 4604 /** 4605 * Joins the elements of the provided array into a single String containing the provided list of elements. 4606 * 4607 * <p> 4608 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4609 * by empty strings. 4610 * </p> 4611 * 4612 * <pre> 4613 * StringUtils.join(null, *) = null 4614 * StringUtils.join([], *) = "" 4615 * StringUtils.join([null], *) = "" 4616 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4617 * StringUtils.join([1, 2, 3], null) = "123" 4618 * </pre> 4619 * 4620 * @param array 4621 * the array of values to join together, may be null. 4622 * @param delimiter 4623 * the separator character to use. 4624 * @return the joined String, {@code null} if null array input. 4625 * @since 3.2 4626 */ 4627 public static String join(final short[] array, final char delimiter) { 4628 if (array == null) { 4629 return null; 4630 } 4631 return join(array, delimiter, 0, array.length); 4632 } 4633 4634 /** 4635 * Joins the elements of the provided array into a single String containing the provided list of elements. 4636 * 4637 * <p> 4638 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4639 * by empty strings. 4640 * </p> 4641 * 4642 * <pre> 4643 * StringUtils.join(null, *) = null 4644 * StringUtils.join([], *) = "" 4645 * StringUtils.join([null], *) = "" 4646 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4647 * StringUtils.join([1, 2, 3], null) = "123" 4648 * </pre> 4649 * 4650 * @param array 4651 * the array of values to join together, may be null. 4652 * @param delimiter 4653 * the separator character to use. 4654 * @param startIndex 4655 * the first index to start joining from. It is an error to pass in a start index past the end of the 4656 * array. 4657 * @param endIndex 4658 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4659 * the array. 4660 * @return the joined String, {@code null} if null array input. 4661 * @since 3.2 4662 */ 4663 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4664 if (array == null) { 4665 return null; 4666 } 4667 if (endIndex - startIndex <= 0) { 4668 return EMPTY; 4669 } 4670 final StringBuilder stringBuilder = new StringBuilder(); 4671 for (int i = startIndex; i < endIndex; i++) { 4672 stringBuilder 4673 .append(array[i]) 4674 .append(delimiter); 4675 } 4676 return stringBuilder.substring(0, stringBuilder.length() - 1); 4677 } 4678 4679 /** 4680 * Joins the elements of the provided array into a single String containing the provided list of elements. 4681 * 4682 * <p> 4683 * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings. 4684 * </p> 4685 * 4686 * <pre> 4687 * StringUtils.join(null) = null 4688 * StringUtils.join([]) = "" 4689 * StringUtils.join([null]) = "" 4690 * StringUtils.join(["a", "b", "c"]) = "abc" 4691 * StringUtils.join([null, "", "a"]) = "a" 4692 * </pre> 4693 * 4694 * @param <T> the specific type of values to join together. 4695 * @param elements the values to join together, may be null. 4696 * @return the joined String, {@code null} if null array input. 4697 * @since 2.0 4698 * @since 3.0 Changed signature to use varargs 4699 */ 4700 @SafeVarargs 4701 public static <T> String join(final T... elements) { 4702 return join(elements, null); 4703 } 4704 4705 /** 4706 * Joins the elements of the provided varargs into a single String containing the provided elements. 4707 * 4708 * <p> 4709 * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings (""). 4710 * </p> 4711 * 4712 * <pre> 4713 * StringUtils.joinWith(",", {"a", "b"}) = "a,b" 4714 * StringUtils.joinWith(",", {"a", "b",""}) = "a,b," 4715 * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b" 4716 * StringUtils.joinWith(null, {"a", "b"}) = "ab" 4717 * </pre> 4718 * 4719 * @param delimiter the separator character to use, null treated as "". 4720 * @param array the varargs providing the values to join together. {@code null} elements are treated as "". 4721 * @return the joined String. 4722 * @throws IllegalArgumentException if a null varargs is provided. 4723 * @since 3.5 4724 */ 4725 public static String joinWith(final String delimiter, final Object... array) { 4726 if (array == null) { 4727 throw new IllegalArgumentException("Object varargs must not be null"); 4728 } 4729 return join(array, delimiter); 4730 } 4731 4732 /** 4733 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible. 4734 * 4735 * <p> 4736 * A {@code null} CharSequence will return {@code -1}. 4737 * </p> 4738 * 4739 * <pre> 4740 * StringUtils.lastIndexOf(null, *) = -1 4741 * StringUtils.lastIndexOf(*, null) = -1 4742 * StringUtils.lastIndexOf("", "") = 0 4743 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4744 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4745 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4746 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4747 * </pre> 4748 * 4749 * @param seq the CharSequence to check, may be null. 4750 * @param searchSeq the CharSequence to find, may be null. 4751 * @return the last index of the search String, -1 if no match or {@code null} string input. 4752 * @since 2.0 4753 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4754 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)} 4755 */ 4756 @Deprecated 4757 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4758 return Strings.CS.lastIndexOf(seq, searchSeq); 4759 } 4760 4761 /** 4762 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible. 4763 * 4764 * <p> 4765 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4766 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works 4767 * backwards; matches starting after the start position are ignored. 4768 * </p> 4769 * 4770 * <pre> 4771 * StringUtils.lastIndexOf(null, *, *) = -1 4772 * StringUtils.lastIndexOf(*, null, *) = -1 4773 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4774 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4775 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4776 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4777 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4778 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4779 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4780 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4781 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4782 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4783 * </pre> 4784 * 4785 * @param seq the CharSequence to check, may be null. 4786 * @param searchSeq the CharSequence to find, may be null. 4787 * @param startPos the start position, negative treated as zero. 4788 * @return the last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} string input. 4789 * @since 2.0 4790 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4791 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)} 4792 */ 4793 @Deprecated 4794 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4795 return Strings.CS.lastIndexOf(seq, searchSeq, startPos); 4796 } 4797 4798 /** 4799 * Returns the index within {@code seq} of the last occurrence of the specified character. For values of {@code searchChar} in the range from 0 to 0xFFFF 4800 * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that: 4801 * 4802 * <pre> 4803 * this.charAt(<em>k</em>) == searchChar 4804 * </pre> 4805 * 4806 * <p> 4807 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4808 * </p> 4809 * 4810 * <pre> 4811 * this.codePointAt(<em>k</em>) == searchChar 4812 * </pre> 4813 * 4814 * <p> 4815 * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4816 * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character. 4817 * </p> 4818 * 4819 * <pre> 4820 * StringUtils.lastIndexOf(null, *) = -1 4821 * StringUtils.lastIndexOf("", *) = -1 4822 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4823 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4824 * </pre> 4825 * 4826 * @param seq the {@link CharSequence} to check, may be null. 4827 * @param searchChar the character to find. 4828 * @return the last index of the search character, -1 if no match or {@code null} string input. 4829 * @since 2.0 4830 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4831 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4832 */ 4833 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4834 if (isEmpty(seq)) { 4835 return INDEX_NOT_FOUND; 4836 } 4837 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4838 } 4839 4840 /** 4841 * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of 4842 * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that: 4843 * 4844 * <pre> 4845 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4846 * </pre> 4847 * 4848 * <p> 4849 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4850 * </p> 4851 * 4852 * <pre> 4853 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4854 * </pre> 4855 * 4856 * <p> 4857 * is true. In either case, if no such character occurs in {@code seq} at or before position {@code startPos}, then {@code -1} is returned. Furthermore, a 4858 * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The 4859 * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored. 4860 * </p> 4861 * 4862 * <p> 4863 * All indices are specified in {@code char} values (Unicode code units). 4864 * </p> 4865 * 4866 * <pre> 4867 * StringUtils.lastIndexOf(null, *, *) = -1 4868 * StringUtils.lastIndexOf("", *, *) = -1 4869 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4870 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4871 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4872 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4873 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4874 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 4875 * </pre> 4876 * 4877 * @param seq the CharSequence to check, may be null. 4878 * @param searchChar the character to find. 4879 * @param startPos the start position. 4880 * @return the last index of the search character (always ≤ startPos), -1 if no match or {@code null} string input. 4881 * @since 2.0 4882 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 4883 */ 4884 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 4885 if (isEmpty(seq)) { 4886 return INDEX_NOT_FOUND; 4887 } 4888 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 4889 } 4890 4891 /** 4892 * Finds the latest index of any substring in a set of potential substrings. 4893 * 4894 * <p> 4895 * A {@code null} CharSequence will return {@code -1}. A {@code null} search array will return {@code -1}. A {@code null} or zero length search array entry 4896 * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses 4897 * {@link String#indexOf(String)} if possible 4898 * </p> 4899 * 4900 * <pre> 4901 * StringUtils.lastIndexOfAny(null, *) = -1 4902 * StringUtils.lastIndexOfAny(*, null) = -1 4903 * StringUtils.lastIndexOfAny(*, []) = -1 4904 * StringUtils.lastIndexOfAny(*, [null]) = -1 4905 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 4906 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 4907 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4908 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4909 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 4910 * </pre> 4911 * 4912 * @param str the CharSequence to check, may be null. 4913 * @param searchStrs the CharSequences to search for, may be null. 4914 * @return the last index of any of the CharSequences, -1 if no match. 4915 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 4916 */ 4917 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 4918 if (str == null || searchStrs == null) { 4919 return INDEX_NOT_FOUND; 4920 } 4921 int ret = INDEX_NOT_FOUND; 4922 int tmp; 4923 for (final CharSequence search : searchStrs) { 4924 if (search == null) { 4925 continue; 4926 } 4927 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 4928 if (tmp > ret) { 4929 ret = tmp; 4930 } 4931 } 4932 return ret; 4933 } 4934 4935 /** 4936 * Case in-sensitive find of the last index within a CharSequence. 4937 * 4938 * <p> 4939 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4940 * the start position is negative. A start position greater than the string length searches the whole string. 4941 * </p> 4942 * 4943 * <pre> 4944 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 4945 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 4946 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 4947 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 4948 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 4949 * </pre> 4950 * 4951 * @param str the CharSequence to check, may be null. 4952 * @param searchStr the CharSequence to find, may be null. 4953 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 4954 * @since 2.5 4955 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 4956 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)} 4957 */ 4958 @Deprecated 4959 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 4960 return Strings.CI.lastIndexOf(str, searchStr); 4961 } 4962 4963 /** 4964 * Case in-sensitive find of the last index within a CharSequence from the specified position. 4965 * 4966 * <p> 4967 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4968 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works 4969 * backwards; matches starting after the start position are ignored. 4970 * </p> 4971 * 4972 * <pre> 4973 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 4974 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 4975 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 4976 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 4977 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 4978 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 4979 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 4980 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 4981 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 4982 * </pre> 4983 * 4984 * @param str the CharSequence to check, may be null. 4985 * @param searchStr the CharSequence to find, may be null. 4986 * @param startPos the start position. 4987 * @return the last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} input. 4988 * @since 2.5 4989 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 4990 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)} 4991 */ 4992 @Deprecated 4993 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 4994 return Strings.CI.lastIndexOf(str, searchStr, startPos); 4995 } 4996 4997 /** 4998 * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}. 4999 * 5000 * <p> 5001 * A {@code null} String will return {@code -1}. 5002 * </p> 5003 * 5004 * <pre> 5005 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5006 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5007 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5008 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5009 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5010 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5011 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5012 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5013 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5014 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5015 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5016 * </pre> 5017 * 5018 * <p> 5019 * Note that 'tail(CharSequence str, int n)' may be implemented as: 5020 * </p> 5021 * 5022 * <pre> 5023 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5024 * </pre> 5025 * 5026 * @param str the CharSequence to check, may be null. 5027 * @param searchStr the CharSequence to find, may be null. 5028 * @param ordinal the n-th last {@code searchStr} to find. 5029 * @return the n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5030 * @since 2.5 5031 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5032 */ 5033 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5034 return ordinalIndexOf(str, searchStr, ordinal, true); 5035 } 5036 5037 /** 5038 * Gets the leftmost {@code len} characters of a String. 5039 * 5040 * <p> 5041 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is returned 5042 * if len is negative. 5043 * </p> 5044 * 5045 * <pre> 5046 * StringUtils.left(null, *) = null 5047 * StringUtils.left(*, -ve) = "" 5048 * StringUtils.left("", *) = "" 5049 * StringUtils.left("abc", 0) = "" 5050 * StringUtils.left("abc", 2) = "ab" 5051 * StringUtils.left("abc", 4) = "abc" 5052 * </pre> 5053 * 5054 * @param str the String to get the leftmost characters from, may be null. 5055 * @param len the length of the required String. 5056 * @return the leftmost characters, {@code null} if null String input. 5057 */ 5058 public static String left(final String str, final int len) { 5059 if (str == null) { 5060 return null; 5061 } 5062 if (len < 0) { 5063 return EMPTY; 5064 } 5065 if (str.length() <= len) { 5066 return str; 5067 } 5068 return str.substring(0, len); 5069 } 5070 5071 /** 5072 * Left pad a String with spaces (' '). 5073 * 5074 * <p> 5075 * The String is padded to the size of {@code size}. 5076 * </p> 5077 * 5078 * <pre> 5079 * StringUtils.leftPad(null, *) = null 5080 * StringUtils.leftPad("", 3) = " " 5081 * StringUtils.leftPad("bat", 3) = "bat" 5082 * StringUtils.leftPad("bat", 5) = " bat" 5083 * StringUtils.leftPad("bat", 1) = "bat" 5084 * StringUtils.leftPad("bat", -1) = "bat" 5085 * </pre> 5086 * 5087 * @param str the String to pad out, may be null. 5088 * @param size the size to pad to. 5089 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5090 */ 5091 public static String leftPad(final String str, final int size) { 5092 return leftPad(str, size, ' '); 5093 } 5094 5095 /** 5096 * Left pad a String with a specified character. 5097 * 5098 * <p> 5099 * Pad to a size of {@code size}. 5100 * </p> 5101 * 5102 * <pre> 5103 * StringUtils.leftPad(null, *, *) = null 5104 * StringUtils.leftPad("", 3, 'z') = "zzz" 5105 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5106 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5107 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5108 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5109 * </pre> 5110 * 5111 * @param str the String to pad out, may be null. 5112 * @param size the size to pad to. 5113 * @param padChar the character to pad with. 5114 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5115 * @since 2.0 5116 */ 5117 public static String leftPad(final String str, final int size, final char padChar) { 5118 if (str == null) { 5119 return null; 5120 } 5121 final int pads = size - str.length(); 5122 if (pads <= 0) { 5123 return str; // returns original String when possible 5124 } 5125 if (pads > PAD_LIMIT) { 5126 return leftPad(str, size, String.valueOf(padChar)); 5127 } 5128 return repeat(padChar, pads).concat(str); 5129 } 5130 5131 /** 5132 * Left pad a String with a specified String. 5133 * 5134 * <p> 5135 * Pad to a size of {@code size}. 5136 * </p> 5137 * 5138 * <pre> 5139 * StringUtils.leftPad(null, *, *) = null 5140 * StringUtils.leftPad("", 3, "z") = "zzz" 5141 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5142 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5143 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5144 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5145 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5146 * StringUtils.leftPad("bat", 5, null) = " bat" 5147 * StringUtils.leftPad("bat", 5, "") = " bat" 5148 * </pre> 5149 * 5150 * @param str the String to pad out, may be null. 5151 * @param size the size to pad to. 5152 * @param padStr the String to pad with, null or empty treated as single space. 5153 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5154 */ 5155 public static String leftPad(final String str, final int size, String padStr) { 5156 if (str == null) { 5157 return null; 5158 } 5159 if (isEmpty(padStr)) { 5160 padStr = SPACE; 5161 } 5162 final int padLen = padStr.length(); 5163 final int strLen = str.length(); 5164 final int pads = size - strLen; 5165 if (pads <= 0) { 5166 return str; // returns original String when possible 5167 } 5168 if (padLen == 1 && pads <= PAD_LIMIT) { 5169 return leftPad(str, size, padStr.charAt(0)); 5170 } 5171 if (pads == padLen) { 5172 return padStr.concat(str); 5173 } 5174 if (pads < padLen) { 5175 return padStr.substring(0, pads).concat(str); 5176 } 5177 final char[] padding = new char[pads]; 5178 final char[] padChars = padStr.toCharArray(); 5179 for (int i = 0; i < pads; i++) { 5180 padding[i] = padChars[i % padLen]; 5181 } 5182 return new String(padding).concat(str); 5183 } 5184 5185 /** 5186 * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}. 5187 * 5188 * @param cs a CharSequence or {@code null}. 5189 * @return CharSequence length or {@code 0} if the CharSequence is {@code null}. 5190 * @since 2.4 5191 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5192 */ 5193 public static int length(final CharSequence cs) { 5194 return cs == null ? 0 : cs.length(); 5195 } 5196 5197 /** 5198 * Converts a String to lower case as per {@link String#toLowerCase()}. 5199 * 5200 * <p> 5201 * A {@code null} input String returns {@code null}. 5202 * </p> 5203 * 5204 * <pre> 5205 * StringUtils.lowerCase(null) = null 5206 * StringUtils.lowerCase("") = "" 5207 * StringUtils.lowerCase("aBc") = "abc" 5208 * </pre> 5209 * 5210 * <p> 5211 * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale. 5212 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g. 5213 * {@link Locale#ENGLISH}). 5214 * </p> 5215 * 5216 * @param str the String to lower case, may be null. 5217 * @return the lower cased String, {@code null} if null String input. 5218 */ 5219 public static String lowerCase(final String str) { 5220 if (str == null) { 5221 return null; 5222 } 5223 return str.toLowerCase(); 5224 } 5225 5226 /** 5227 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5228 * 5229 * <p> 5230 * A {@code null} input String returns {@code null}. 5231 * </p> 5232 * 5233 * <pre> 5234 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5235 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5236 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5237 * </pre> 5238 * 5239 * @param str the String to lower case, may be null. 5240 * @param locale the locale that defines the case transformation rules, must not be null. 5241 * @return the lower cased String, {@code null} if null String input. 5242 * @since 2.5 5243 */ 5244 public static String lowerCase(final String str, final Locale locale) { 5245 if (str == null) { 5246 return null; 5247 } 5248 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5249 } 5250 5251 private static int[] matches(final CharSequence first, final CharSequence second) { 5252 final CharSequence max; 5253 final CharSequence min; 5254 if (first.length() > second.length()) { 5255 max = first; 5256 min = second; 5257 } else { 5258 max = second; 5259 min = first; 5260 } 5261 final int range = Math.max(max.length() / 2 - 1, 0); 5262 final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1); 5263 final boolean[] matchFlags = new boolean[max.length()]; 5264 int matches = 0; 5265 for (int mi = 0; mi < min.length(); mi++) { 5266 final char c1 = min.charAt(mi); 5267 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5268 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5269 matchIndexes[mi] = xi; 5270 matchFlags[xi] = true; 5271 matches++; 5272 break; 5273 } 5274 } 5275 } 5276 final char[] ms1 = new char[matches]; 5277 final char[] ms2 = new char[matches]; 5278 for (int i = 0, si = 0; i < min.length(); i++) { 5279 if (matchIndexes[i] != -1) { 5280 ms1[si] = min.charAt(i); 5281 si++; 5282 } 5283 } 5284 for (int i = 0, si = 0; i < max.length(); i++) { 5285 if (matchFlags[i]) { 5286 ms2[si] = max.charAt(i); 5287 si++; 5288 } 5289 } 5290 int transpositions = 0; 5291 for (int mi = 0; mi < ms1.length; mi++) { 5292 if (ms1[mi] != ms2[mi]) { 5293 transpositions++; 5294 } 5295 } 5296 int prefix = 0; 5297 for (int mi = 0; mi < min.length(); mi++) { 5298 if (first.charAt(mi) != second.charAt(mi)) { 5299 break; 5300 } 5301 prefix++; 5302 } 5303 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5304 } 5305 5306 /** 5307 * Gets {@code len} characters from the middle of a String. 5308 * 5309 * <p> 5310 * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null}, 5311 * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}. 5312 * </p> 5313 * 5314 * <pre> 5315 * StringUtils.mid(null, *, *) = null 5316 * StringUtils.mid(*, *, -ve) = "" 5317 * StringUtils.mid("", 0, *) = "" 5318 * StringUtils.mid("abc", 0, 2) = "ab" 5319 * StringUtils.mid("abc", 0, 4) = "abc" 5320 * StringUtils.mid("abc", 2, 4) = "c" 5321 * StringUtils.mid("abc", 4, 2) = "" 5322 * StringUtils.mid("abc", -2, 2) = "ab" 5323 * </pre> 5324 * 5325 * @param str the String to get the characters from, may be null. 5326 * @param pos the position to start from, negative treated as zero. 5327 * @param len the length of the required String. 5328 * @return the middle characters, {@code null} if null String input. 5329 */ 5330 public static String mid(final String str, int pos, final int len) { 5331 if (str == null) { 5332 return null; 5333 } 5334 if (len < 0 || pos > str.length()) { 5335 return EMPTY; 5336 } 5337 if (pos < 0) { 5338 pos = 0; 5339 } 5340 if (str.length() <= pos + len) { 5341 return str.substring(pos); 5342 } 5343 return str.substring(pos, pos + len); 5344 } 5345 5346 /** 5347 * Similar to <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize -space</a> 5348 * 5349 * <p> 5350 * The function returns the argument string with whitespace normalized by using {@code {@link #trim(String)}} to remove leading and trailing whitespace and 5351 * then replacing sequences of whitespace characters by a single space. 5352 * </p> 5353 * In XML Whitespace characters are the same as those allowed by the <a href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | 5354 * #x9 | #xD | #xA)+ 5355 * <p> 5356 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5357 * </p> 5358 * <p> 5359 * For reference: 5360 * </p> 5361 * <ul> 5362 * <li>\x0B = vertical tab</li> 5363 * <li>\f = #xC = form feed</li> 5364 * <li>#x20 = space</li> 5365 * <li>#x9 = \t</li> 5366 * <li>#xA = \n</li> 5367 * <li>#xD = \r</li> 5368 * </ul> 5369 * 5370 * <p> 5371 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also normalize. Additionally {@code {@link 5372 * #trim(String)}} removes control characters (char <= 32) from both ends of this String. 5373 * </p> 5374 * 5375 * @param str the source String to normalize whitespaces from, may be null. 5376 * @return the modified string with whitespace normalized, {@code null} if null String input. 5377 * @see Pattern 5378 * @see #trim(String) 5379 * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5380 * @since 3.0 5381 */ 5382 public static String normalizeSpace(final String str) { 5383 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5384 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5385 if (isEmpty(str)) { 5386 return str; 5387 } 5388 final int size = str.length(); 5389 final char[] newChars = new char[size]; 5390 int count = 0; 5391 int whitespacesCount = 0; 5392 boolean startWhitespaces = true; 5393 for (int i = 0; i < size; i++) { 5394 final char actualChar = str.charAt(i); 5395 final boolean isWhitespace = Character.isWhitespace(actualChar); 5396 if (isWhitespace) { 5397 if (whitespacesCount == 0 && !startWhitespaces) { 5398 newChars[count++] = SPACE.charAt(0); 5399 } 5400 whitespacesCount++; 5401 } else { 5402 startWhitespaces = false; 5403 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5404 whitespacesCount = 0; 5405 } 5406 } 5407 if (startWhitespaces) { 5408 return EMPTY; 5409 } 5410 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5411 } 5412 5413 /** 5414 * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5415 * <p> 5416 * <strong>Note:</strong> The code starts looking for a match at the start of the target, incrementing the starting index by one after each successful match 5417 * (unless {@code searchStr} is an empty string in which case the position is never incremented and {@code 0} is returned immediately). This means that 5418 * matches may overlap. 5419 * </p> 5420 * <p> 5421 * A {@code null} CharSequence will return {@code -1}. 5422 * </p> 5423 * 5424 * <pre> 5425 * StringUtils.ordinalIndexOf(null, *, *) = -1 5426 * StringUtils.ordinalIndexOf(*, null, *) = -1 5427 * StringUtils.ordinalIndexOf("", "", *) = 0 5428 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5429 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5430 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5431 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5432 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5433 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5434 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5435 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5436 * </pre> 5437 * 5438 * <p> 5439 * Matches may overlap: 5440 * </p> 5441 * 5442 * <pre> 5443 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5444 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5445 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5446 * 5447 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5448 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5449 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5450 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5451 * </pre> 5452 * 5453 * <p> 5454 * Note that 'head(CharSequence str, int n)' may be implemented as: 5455 * </p> 5456 * 5457 * <pre> 5458 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5459 * </pre> 5460 * 5461 * @param str the CharSequence to check, may be null. 5462 * @param searchStr the CharSequence to find, may be null. 5463 * @param ordinal the n-th {@code searchStr} to find. 5464 * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5465 * @since 2.1 5466 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5467 */ 5468 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5469 return ordinalIndexOf(str, searchStr, ordinal, false); 5470 } 5471 5472 /** 5473 * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5474 * <p> 5475 * Note that matches may overlap 5476 * <p> 5477 * 5478 * <p> 5479 * A {@code null} CharSequence will return {@code -1}. 5480 * </p> 5481 * 5482 * @param str the CharSequence to check, may be null. 5483 * @param searchStr the CharSequence to find, may be null. 5484 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5485 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf(). 5486 * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5487 */ 5488 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5489 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5490 if (str == null || searchStr == null || ordinal <= 0) { 5491 return INDEX_NOT_FOUND; 5492 } 5493 if (searchStr.length() == 0) { 5494 return lastIndex ? str.length() : 0; 5495 } 5496 int found = 0; 5497 // set the initial index beyond the end of the string 5498 // this is to allow for the initial index decrement/increment 5499 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5500 do { 5501 if (lastIndex) { 5502 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5503 } else { 5504 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5505 } 5506 if (index < 0) { 5507 return index; 5508 } 5509 found++; 5510 } while (found < ordinal); 5511 return index; 5512 } 5513 5514 /** 5515 * Overlays part of a String with another String. 5516 * 5517 * <p> 5518 * A {@code null} string input returns {@code null}. A negative index is treated as zero. An index greater than the string length is treated as the string 5519 * length. The start index is always the smaller of the two indices. 5520 * </p> 5521 * 5522 * <pre> 5523 * StringUtils.overlay(null, *, *, *) = null 5524 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5525 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5526 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5527 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5528 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5529 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5530 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5531 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5532 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5533 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5534 * </pre> 5535 * 5536 * @param str the String to do overlaying in, may be null. 5537 * @param overlay the String to overlay, may be null. 5538 * @param start the position to start overlaying at. 5539 * @param end the position to stop overlaying before. 5540 * @return overlayed String, {@code null} if null String input. 5541 * @since 2.0 5542 */ 5543 public static String overlay(final String str, String overlay, int start, int end) { 5544 if (str == null) { 5545 return null; 5546 } 5547 if (overlay == null) { 5548 overlay = EMPTY; 5549 } 5550 final int len = str.length(); 5551 if (start < 0) { 5552 start = 0; 5553 } 5554 if (start > len) { 5555 start = len; 5556 } 5557 if (end < 0) { 5558 end = 0; 5559 } 5560 if (end > len) { 5561 end = len; 5562 } 5563 if (start > end) { 5564 final int temp = start; 5565 start = end; 5566 end = temp; 5567 } 5568 return str.substring(0, start) + overlay + str.substring(end); 5569 } 5570 5571 /** 5572 * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes. 5573 * 5574 * <pre> 5575 * StringUtils.prependIfMissing(null, null) = null 5576 * StringUtils.prependIfMissing("abc", null) = "abc" 5577 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5578 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5579 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5580 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5581 * </pre> 5582 * <p> 5583 * With additional prefixes, 5584 * </p> 5585 * 5586 * <pre> 5587 * StringUtils.prependIfMissing(null, null, null) = null 5588 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5589 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5590 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5591 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5592 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5593 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5594 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5595 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5596 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5597 * </pre> 5598 * 5599 * @param str The string. 5600 * @param prefix The prefix to prepend to the start of the string. 5601 * @param prefixes Additional prefixes that are valid. 5602 * @return A new String if prefix was prepended, the same string otherwise. 5603 * @since 3.2 5604 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence, 5605 * CharSequence...)} 5606 */ 5607 @Deprecated 5608 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5609 return Strings.CS.prependIfMissing(str, prefix, prefixes); 5610 } 5611 5612 /** 5613 * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes. 5614 * 5615 * <pre> 5616 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5617 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5618 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5619 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5620 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5621 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5622 * </pre> 5623 * <p> 5624 * With additional prefixes, 5625 * </p> 5626 * 5627 * <pre> 5628 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5629 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5630 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5631 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5632 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5633 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5634 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5635 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5636 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5637 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5638 * </pre> 5639 * 5640 * @param str The string. 5641 * @param prefix The prefix to prepend to the start of the string. 5642 * @param prefixes Additional prefixes that are valid (optional). 5643 * @return A new String if prefix was prepended, the same string otherwise. 5644 * @since 3.2 5645 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence, 5646 * CharSequence...)} 5647 */ 5648 @Deprecated 5649 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5650 return Strings.CI.prependIfMissing(str, prefix, prefixes); 5651 } 5652 5653 /** 5654 * Removes all occurrences of a character from within the source string. 5655 * 5656 * <p> 5657 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. 5658 * </p> 5659 * 5660 * <pre> 5661 * StringUtils.remove(null, *) = null 5662 * StringUtils.remove("", *) = "" 5663 * StringUtils.remove("queued", 'u') = "qeed" 5664 * StringUtils.remove("queued", 'z') = "queued" 5665 * </pre> 5666 * 5667 * @param str the source String to search, may be null. 5668 * @param remove the char to search for and remove, may be null. 5669 * @return the substring with the char removed if found, {@code null} if null String input. 5670 * @since 2.1 5671 */ 5672 public static String remove(final String str, final char remove) { 5673 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5674 return str; 5675 } 5676 final char[] chars = str.toCharArray(); 5677 int pos = 0; 5678 for (int i = 0; i < chars.length; i++) { 5679 if (chars[i] != remove) { 5680 chars[pos++] = chars[i]; 5681 } 5682 } 5683 return new String(chars, 0, pos); 5684 } 5685 5686 /** 5687 * Removes all occurrences of a substring from within the source string. 5688 * 5689 * <p> 5690 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return 5691 * the source string. An empty ("") remove string will return the source string. 5692 * </p> 5693 * 5694 * <pre> 5695 * StringUtils.remove(null, *) = null 5696 * StringUtils.remove("", *) = "" 5697 * StringUtils.remove(*, null) = * 5698 * StringUtils.remove(*, "") = * 5699 * StringUtils.remove("queued", "ue") = "qd" 5700 * StringUtils.remove("queued", "zz") = "queued" 5701 * </pre> 5702 * 5703 * @param str the source String to search, may be null. 5704 * @param remove the String to search for and remove, may be null. 5705 * @return the substring with the string removed if found, {@code null} if null String input. 5706 * @since 2.1 5707 * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)} 5708 */ 5709 @Deprecated 5710 public static String remove(final String str, final String remove) { 5711 return Strings.CS.remove(str, remove); 5712 } 5713 5714 /** 5715 * Removes each substring of the text String that matches the given regular expression. 5716 * 5717 * This method is a {@code null} safe equivalent to: 5718 * <ul> 5719 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5720 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5721 * </ul> 5722 * 5723 * <p> 5724 * A {@code null} reference passed to this method is a no-op. 5725 * </p> 5726 * 5727 * <p> 5728 * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option 5729 * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 5730 * </p> 5731 * 5732 * <pre>{@code 5733 * StringUtils.removeAll(null, *) = null 5734 * StringUtils.removeAll("any", (String) null) = "any" 5735 * StringUtils.removeAll("any", "") = "any" 5736 * StringUtils.removeAll("any", ".*") = "" 5737 * StringUtils.removeAll("any", ".+") = "" 5738 * StringUtils.removeAll("abc", ".?") = "" 5739 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5740 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5741 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5742 * }</pre> 5743 * 5744 * @param text text to remove from, may be null. 5745 * @param regex the regular expression to which this string is to be matched. 5746 * @return the text with any removes processed, {@code null} if null String input. 5747 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 5748 * @see #replaceAll(String, String, String) 5749 * @see #removePattern(String, String) 5750 * @see String#replaceAll(String, String) 5751 * @see java.util.regex.Pattern 5752 * @see java.util.regex.Pattern#DOTALL 5753 * @since 3.5 5754 * @deprecated Moved to RegExUtils. 5755 */ 5756 @Deprecated 5757 public static String removeAll(final String text, final String regex) { 5758 return RegExUtils.removeAll(text, regex); 5759 } 5760 5761 /** 5762 * Removes a substring only if it is at the end of a source string, otherwise returns the source string. 5763 * 5764 * <p> 5765 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5766 * the source string. 5767 * </p> 5768 * 5769 * <pre> 5770 * StringUtils.removeEnd(null, *) = null 5771 * StringUtils.removeEnd("", *) = "" 5772 * StringUtils.removeEnd(*, null) = * 5773 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5774 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5775 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5776 * StringUtils.removeEnd("abc", "") = "abc" 5777 * </pre> 5778 * 5779 * @param str the source String to search, may be null. 5780 * @param remove the String to search for and remove, may be null. 5781 * @return the substring with the string removed if found, {@code null} if null String input. 5782 * @since 2.1 5783 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)} 5784 */ 5785 @Deprecated 5786 public static String removeEnd(final String str, final String remove) { 5787 return Strings.CS.removeEnd(str, remove); 5788 } 5789 5790 /** 5791 * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string. 5792 * 5793 * <p> 5794 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5795 * the source string. 5796 * </p> 5797 * 5798 * <pre> 5799 * StringUtils.removeEndIgnoreCase(null, *) = null 5800 * StringUtils.removeEndIgnoreCase("", *) = "" 5801 * StringUtils.removeEndIgnoreCase(*, null) = * 5802 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5803 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5804 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5805 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5806 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 5807 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 5808 * </pre> 5809 * 5810 * @param str the source String to search, may be null. 5811 * @param remove the String to search for (case-insensitive) and remove, may be null. 5812 * @return the substring with the string removed if found, {@code null} if null String input. 5813 * @since 2.4 5814 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)} 5815 */ 5816 @Deprecated 5817 public static String removeEndIgnoreCase(final String str, final String remove) { 5818 return Strings.CI.removeEnd(str, remove); 5819 } 5820 5821 /** 5822 * Removes the first substring of the text string that matches the given regular expression. 5823 * 5824 * This method is a {@code null} safe equivalent to: 5825 * <ul> 5826 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 5827 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 5828 * </ul> 5829 * 5830 * <p> 5831 * A {@code null} reference passed to this method is a no-op. 5832 * </p> 5833 * 5834 * <p> 5835 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as 5836 * single-line mode in Perl. 5837 * </p> 5838 * 5839 * <pre>{@code 5840 * StringUtils.removeFirst(null, *) = null 5841 * StringUtils.removeFirst("any", (String) null) = "any" 5842 * StringUtils.removeFirst("any", "") = "any" 5843 * StringUtils.removeFirst("any", ".*") = "" 5844 * StringUtils.removeFirst("any", ".+") = "" 5845 * StringUtils.removeFirst("abc", ".?") = "bc" 5846 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5847 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5848 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5849 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5850 * }</pre> 5851 * 5852 * @param text text to remove from, may be null. 5853 * @param regex the regular expression to which this string is to be matched. 5854 * @return the text with the first replacement processed, {@code null} if null String input. 5855 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 5856 * @see #replaceFirst(String, String, String) 5857 * @see String#replaceFirst(String, String) 5858 * @see java.util.regex.Pattern 5859 * @see java.util.regex.Pattern#DOTALL 5860 * @since 3.5 5861 * @deprecated Moved to RegExUtils. 5862 */ 5863 @Deprecated 5864 public static String removeFirst(final String text, final String regex) { 5865 return replaceFirst(text, regex, EMPTY); 5866 } 5867 5868 /** 5869 * Case-insensitive removal of all occurrences of a substring from within the source string. 5870 * 5871 * <p> 5872 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return 5873 * the source string. An empty ("") remove string will return the source string. 5874 * </p> 5875 * 5876 * <pre> 5877 * StringUtils.removeIgnoreCase(null, *) = null 5878 * StringUtils.removeIgnoreCase("", *) = "" 5879 * StringUtils.removeIgnoreCase(*, null) = * 5880 * StringUtils.removeIgnoreCase(*, "") = * 5881 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 5882 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 5883 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 5884 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 5885 * </pre> 5886 * 5887 * @param str the source String to search, may be null. 5888 * @param remove the String to search for (case-insensitive) and remove, may be null. 5889 * @return the substring with the string removed if found, {@code null} if null String input. 5890 * @since 3.5 5891 * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)} 5892 */ 5893 @Deprecated 5894 public static String removeIgnoreCase(final String str, final String remove) { 5895 return Strings.CI.remove(str, remove); 5896 } 5897 5898 /** 5899 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 5900 * 5901 * This call is a {@code null} safe equivalent to: 5902 * <ul> 5903 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 5904 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 5905 * </ul> 5906 * 5907 * <p> 5908 * A {@code null} reference passed to this method is a no-op. 5909 * </p> 5910 * 5911 * <pre>{@code 5912 * StringUtils.removePattern(null, *) = null 5913 * StringUtils.removePattern("any", (String) null) = "any" 5914 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 5915 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 5916 * }</pre> 5917 * 5918 * @param source the source string. 5919 * @param regex the regular expression to which this string is to be matched. 5920 * @return The resulting {@link String}. 5921 * @see #replacePattern(String, String, String) 5922 * @see String#replaceAll(String, String) 5923 * @see Pattern#DOTALL 5924 * @since 3.2 5925 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 5926 * @deprecated Moved to RegExUtils. 5927 */ 5928 @Deprecated 5929 public static String removePattern(final String source, final String regex) { 5930 return RegExUtils.removePattern(source, regex); 5931 } 5932 5933 /** 5934 * Removes a char only if it is at the beginning of a source string, otherwise returns the source string. 5935 * 5936 * <p> 5937 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search char will return 5938 * the source string. 5939 * </p> 5940 * 5941 * <pre> 5942 * StringUtils.removeStart(null, *) = null 5943 * StringUtils.removeStart("", *) = "" 5944 * StringUtils.removeStart(*, null) = * 5945 * StringUtils.removeStart("/path", '/') = "path" 5946 * StringUtils.removeStart("path", '/') = "path" 5947 * StringUtils.removeStart("path", 0) = "path" 5948 * </pre> 5949 * 5950 * @param str the source String to search, may be null. 5951 * @param remove the char to search for and remove. 5952 * @return the substring with the char removed if found, {@code null} if null String input. 5953 * @since 3.13.0 5954 */ 5955 public static String removeStart(final String str, final char remove) { 5956 if (isEmpty(str)) { 5957 return str; 5958 } 5959 return str.charAt(0) == remove ? str.substring(1) : str; 5960 } 5961 5962 /** 5963 * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string. 5964 * 5965 * <p> 5966 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5967 * the source string. 5968 * </p> 5969 * 5970 * <pre> 5971 * StringUtils.removeStart(null, *) = null 5972 * StringUtils.removeStart("", *) = "" 5973 * StringUtils.removeStart(*, null) = * 5974 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 5975 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 5976 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 5977 * StringUtils.removeStart("abc", "") = "abc" 5978 * </pre> 5979 * 5980 * @param str the source String to search, may be null. 5981 * @param remove the String to search for and remove, may be null. 5982 * @return the substring with the string removed if found, {@code null} if null String input. 5983 * @since 2.1 5984 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)} 5985 */ 5986 @Deprecated 5987 public static String removeStart(final String str, final String remove) { 5988 return Strings.CS.removeStart(str, remove); 5989 } 5990 5991 /** 5992 * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string. 5993 * 5994 * <p> 5995 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5996 * the source string. 5997 * </p> 5998 * 5999 * <pre> 6000 * StringUtils.removeStartIgnoreCase(null, *) = null 6001 * StringUtils.removeStartIgnoreCase("", *) = "" 6002 * StringUtils.removeStartIgnoreCase(*, null) = * 6003 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6004 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6005 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6006 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6007 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6008 * </pre> 6009 * 6010 * @param str the source String to search, may be null. 6011 * @param remove the String to search for (case-insensitive) and remove, may be null. 6012 * @return the substring with the string removed if found, {@code null} if null String input. 6013 * @since 2.4 6014 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)} 6015 */ 6016 @Deprecated 6017 public static String removeStartIgnoreCase(final String str, final String remove) { 6018 return Strings.CI.removeStart(str, remove); 6019 } 6020 6021 /** 6022 * Returns padding using the specified delimiter repeated to a given length. 6023 * 6024 * <pre> 6025 * StringUtils.repeat('e', 0) = "" 6026 * StringUtils.repeat('e', 3) = "eee" 6027 * StringUtils.repeat('e', -2) = "" 6028 * </pre> 6029 * 6030 * <p> 6031 * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6032 * as they require a pair of {@code char}s to be represented. If you are needing to support full I18N of your applications consider using 6033 * {@link #repeat(String, int)} instead. 6034 * </p> 6035 * 6036 * @param repeat character to repeat. 6037 * @param count number of times to repeat char, negative treated as zero. 6038 * @return String with repeated character. 6039 * @see #repeat(String, int) 6040 */ 6041 public static String repeat(final char repeat, final int count) { 6042 if (count <= 0) { 6043 return EMPTY; 6044 } 6045 return new String(ArrayFill.fill(new char[count], repeat)); 6046 } 6047 6048 /** 6049 * Repeats a String {@code repeat} times to form a new String. 6050 * 6051 * <pre> 6052 * StringUtils.repeat(null, 2) = null 6053 * StringUtils.repeat("", 0) = "" 6054 * StringUtils.repeat("", 2) = "" 6055 * StringUtils.repeat("a", 3) = "aaa" 6056 * StringUtils.repeat("ab", 2) = "abab" 6057 * StringUtils.repeat("a", -2) = "" 6058 * </pre> 6059 * 6060 * @param repeat the String to repeat, may be null. 6061 * @param count number of times to repeat str, negative treated as zero. 6062 * @return a new String consisting of the original String repeated, {@code null} if null String input. 6063 */ 6064 public static String repeat(final String repeat, final int count) { 6065 // Performance tuned for 2.0 (JDK1.4) 6066 if (repeat == null) { 6067 return null; 6068 } 6069 if (count <= 0) { 6070 return EMPTY; 6071 } 6072 final int inputLength = repeat.length(); 6073 if (count == 1 || inputLength == 0) { 6074 return repeat; 6075 } 6076 if (inputLength == 1 && count <= PAD_LIMIT) { 6077 return repeat(repeat.charAt(0), count); 6078 } 6079 final int outputLength = inputLength * count; 6080 switch (inputLength) { 6081 case 1: 6082 return repeat(repeat.charAt(0), count); 6083 case 2: 6084 final char ch0 = repeat.charAt(0); 6085 final char ch1 = repeat.charAt(1); 6086 final char[] output2 = new char[outputLength]; 6087 for (int i = count * 2 - 2; i >= 0; i--, i--) { 6088 output2[i] = ch0; 6089 output2[i + 1] = ch1; 6090 } 6091 return new String(output2); 6092 default: 6093 final StringBuilder buf = new StringBuilder(outputLength); 6094 for (int i = 0; i < count; i++) { 6095 buf.append(repeat); 6096 } 6097 return buf.toString(); 6098 } 6099 } 6100 6101 /** 6102 * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time. 6103 * 6104 * <pre> 6105 * StringUtils.repeat(null, null, 2) = null 6106 * StringUtils.repeat(null, "x", 2) = null 6107 * StringUtils.repeat("", null, 0) = "" 6108 * StringUtils.repeat("", "", 2) = "" 6109 * StringUtils.repeat("", "x", 3) = "xx" 6110 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6111 * </pre> 6112 * 6113 * @param repeat the String to repeat, may be null. 6114 * @param separator the String to inject, may be null. 6115 * @param count number of times to repeat str, negative treated as zero. 6116 * @return a new String consisting of the original String repeated, {@code null} if null String input. 6117 * @since 2.5 6118 */ 6119 public static String repeat(final String repeat, final String separator, final int count) { 6120 if (repeat == null || separator == null) { 6121 return repeat(repeat, count); 6122 } 6123 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6124 final String result = repeat(repeat + separator, count); 6125 return Strings.CS.removeEnd(result, separator); 6126 } 6127 6128 /** 6129 * Replaces all occurrences of a String within another String. 6130 * 6131 * <p> 6132 * A {@code null} reference passed to this method is a no-op. 6133 * </p> 6134 * 6135 * <pre> 6136 * StringUtils.replace(null, *, *) = null 6137 * StringUtils.replace("", *, *) = "" 6138 * StringUtils.replace("any", null, *) = "any" 6139 * StringUtils.replace("any", *, null) = "any" 6140 * StringUtils.replace("any", "", *) = "any" 6141 * StringUtils.replace("aba", "a", null) = "aba" 6142 * StringUtils.replace("aba", "a", "") = "b" 6143 * StringUtils.replace("aba", "a", "z") = "zbz" 6144 * </pre> 6145 * 6146 * @param text text to search and replace in, may be null. 6147 * @param searchString the String to search for, may be null. 6148 * @param replacement the String to replace it with, may be null. 6149 * @return the text with any replacements processed, {@code null} if null String input. 6150 * @see #replace(String text, String searchString, String replacement, int max) 6151 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)} 6152 */ 6153 @Deprecated 6154 public static String replace(final String text, final String searchString, final String replacement) { 6155 return Strings.CS.replace(text, searchString, replacement); 6156 } 6157 6158 /** 6159 * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6160 * 6161 * <p> 6162 * A {@code null} reference passed to this method is a no-op. 6163 * </p> 6164 * 6165 * <pre> 6166 * StringUtils.replace(null, *, *, *) = null 6167 * StringUtils.replace("", *, *, *) = "" 6168 * StringUtils.replace("any", null, *, *) = "any" 6169 * StringUtils.replace("any", *, null, *) = "any" 6170 * StringUtils.replace("any", "", *, *) = "any" 6171 * StringUtils.replace("any", *, *, 0) = "any" 6172 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6173 * StringUtils.replace("abaa", "a", "", -1) = "b" 6174 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6175 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6176 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6177 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6178 * </pre> 6179 * 6180 * @param text text to search and replace in, may be null. 6181 * @param searchString the String to search for, may be null. 6182 * @param replacement the String to replace it with, may be null. 6183 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6184 * @return the text with any replacements processed, {@code null} if null String input. 6185 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)} 6186 */ 6187 @Deprecated 6188 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6189 return Strings.CS.replace(text, searchString, replacement, max); 6190 } 6191 6192 /** 6193 * Replaces each substring of the text String that matches the given regular expression with the given replacement. 6194 * 6195 * This method is a {@code null} safe equivalent to: 6196 * <ul> 6197 * <li>{@code text.replaceAll(regex, replacement)}</li> 6198 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6199 * </ul> 6200 * 6201 * <p> 6202 * A {@code null} reference passed to this method is a no-op. 6203 * </p> 6204 * 6205 * <p> 6206 * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL 6207 * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 6208 * </p> 6209 * 6210 * <pre>{@code 6211 * StringUtils.replaceAll(null, *, *) = null 6212 * StringUtils.replaceAll("any", (String) null, *) = "any" 6213 * StringUtils.replaceAll("any", *, null) = "any" 6214 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6215 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6216 * StringUtils.replaceAll("", ".+", "zzz") = "" 6217 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6218 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6219 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6220 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6221 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6222 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6223 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6224 * }</pre> 6225 * 6226 * @param text text to search and replace in, may be null. 6227 * @param regex the regular expression to which this string is to be matched. 6228 * @param replacement the string to be substituted for each match. 6229 * @return the text with any replacements processed, {@code null} if null String input. 6230 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 6231 * @see #replacePattern(String, String, String) 6232 * @see String#replaceAll(String, String) 6233 * @see java.util.regex.Pattern 6234 * @see java.util.regex.Pattern#DOTALL 6235 * @since 3.5 6236 * @deprecated Moved to RegExUtils. 6237 */ 6238 @Deprecated 6239 public static String replaceAll(final String text, final String regex, final String replacement) { 6240 return RegExUtils.replaceAll(text, regex, replacement); 6241 } 6242 6243 /** 6244 * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}. 6245 * 6246 * <p> 6247 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. 6248 * </p> 6249 * 6250 * <pre> 6251 * StringUtils.replaceChars(null, *, *) = null 6252 * StringUtils.replaceChars("", *, *) = "" 6253 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6254 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6255 * </pre> 6256 * 6257 * @param str String to replace characters in, may be null. 6258 * @param searchChar the character to search for, may be null. 6259 * @param replaceChar the character to replace, may be null. 6260 * @return modified String, {@code null} if null string input. 6261 * @since 2.0 6262 */ 6263 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6264 if (str == null) { 6265 return null; 6266 } 6267 return str.replace(searchChar, replaceChar); 6268 } 6269 6270 /** 6271 * Replaces multiple characters in a String in one go. This method can also be used to delete characters. 6272 * 6273 * <p> 6274 * For example:<br> 6275 * {@code replaceChars("hello", "ho", "jy") = jelly}. 6276 * </p> 6277 * 6278 * <p> 6279 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. A null or empty set of search characters returns 6280 * the input string. 6281 * </p> 6282 * 6283 * <p> 6284 * The length of the search characters should normally equal the length of the replace characters. If the search characters is longer, then the extra search 6285 * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored. 6286 * </p> 6287 * 6288 * <pre> 6289 * StringUtils.replaceChars(null, *, *) = null 6290 * StringUtils.replaceChars("", *, *) = "" 6291 * StringUtils.replaceChars("abc", null, *) = "abc" 6292 * StringUtils.replaceChars("abc", "", *) = "abc" 6293 * StringUtils.replaceChars("abc", "b", null) = "ac" 6294 * StringUtils.replaceChars("abc", "b", "") = "ac" 6295 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6296 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6297 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6298 * </pre> 6299 * 6300 * @param str String to replace characters in, may be null. 6301 * @param searchChars a set of characters to search for, may be null. 6302 * @param replaceChars a set of characters to replace, may be null. 6303 * @return modified String, {@code null} if null string input. 6304 * @since 2.0 6305 */ 6306 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6307 if (isEmpty(str) || isEmpty(searchChars)) { 6308 return str; 6309 } 6310 replaceChars = ObjectUtils.toString(replaceChars); 6311 boolean modified = false; 6312 final int replaceCharsLength = replaceChars.length(); 6313 final int strLength = str.length(); 6314 final StringBuilder buf = new StringBuilder(strLength); 6315 for (int i = 0; i < strLength; i++) { 6316 final char ch = str.charAt(i); 6317 final int index = searchChars.indexOf(ch); 6318 if (index >= 0) { 6319 modified = true; 6320 if (index < replaceCharsLength) { 6321 buf.append(replaceChars.charAt(index)); 6322 } 6323 } else { 6324 buf.append(ch); 6325 } 6326 } 6327 if (modified) { 6328 return buf.toString(); 6329 } 6330 return str; 6331 } 6332 6333 /** 6334 * Replaces all occurrences of Strings within another String. 6335 * 6336 * <p> 6337 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. This 6338 * will not repeat. For repeating replaces, call the overloaded method. 6339 * </p> 6340 * 6341 * <pre> 6342 * StringUtils.replaceEach(null, *, *) = null 6343 * StringUtils.replaceEach("", *, *) = "" 6344 * StringUtils.replaceEach("aba", null, null) = "aba" 6345 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6346 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6347 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6348 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6349 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6350 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6351 * (example of how it does not repeat) 6352 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6353 * </pre> 6354 * 6355 * @param text text to search and replace in, no-op if null. 6356 * @param searchList the Strings to search for, no-op if null. 6357 * @param replacementList the Strings to replace them with, no-op if null. 6358 * @return the text with any replacements processed, {@code null} if null String input. 6359 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6360 * @since 2.4 6361 */ 6362 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6363 return replaceEach(text, searchList, replacementList, false, 0); 6364 } 6365 6366 /** 6367 * Replace all occurrences of Strings within another String. This is a private recursive helper method for 6368 * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])} 6369 * 6370 * <p> 6371 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. 6372 * </p> 6373 * 6374 * <pre> 6375 * StringUtils.replaceEach(null, *, *, *, *) = null 6376 * StringUtils.replaceEach("", *, *, *, *) = "" 6377 * StringUtils.replaceEach("aba", null, null, *, *) = "aba" 6378 * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba" 6379 * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba" 6380 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba" 6381 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b" 6382 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba" 6383 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte" 6384 * (example of how it repeats) 6385 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte" 6386 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte" 6387 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException 6388 * </pre> 6389 * 6390 * @param text text to search and replace in, no-op if null. 6391 * @param searchList the Strings to search for, no-op if null. 6392 * @param replacementList the Strings to replace them with, no-op if null. 6393 * @param repeat if true, then replace repeatedly until there are no more possible replacements or timeToLive < 0. 6394 * @param timeToLive if less than 0 then there is a circular reference and endless loop. 6395 * @return the text with any replacements processed, {@code null} if null String input. 6396 * @throws IllegalStateException if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6397 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6398 * @since 2.4 6399 */ 6400 private static String replaceEach( 6401 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 6402 6403 // mchyzer Performance note: This creates very few new objects (one major goal) 6404 // let me know if there are performance requests, we can create a harness to measure 6405 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) { 6406 return text; 6407 } 6408 6409 // if recursing, this shouldn't be less than 0 6410 if (timeToLive < 0) { 6411 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6412 "output of one loop is the input of another"); 6413 } 6414 6415 final int searchLength = searchList.length; 6416 final int replacementLength = replacementList.length; 6417 6418 // make sure lengths are ok, these need to be equal 6419 if (searchLength != replacementLength) { 6420 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6421 + searchLength 6422 + " vs " 6423 + replacementLength); 6424 } 6425 6426 // keep track of which still have matches 6427 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6428 6429 // index on index that the match was found 6430 int textIndex = -1; 6431 int replaceIndex = -1; 6432 int tempIndex; 6433 6434 // index of replace array that will replace the search string found 6435 // NOTE: logic duplicated below START 6436 for (int i = 0; i < searchLength; i++) { 6437 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6438 continue; 6439 } 6440 tempIndex = text.indexOf(searchList[i]); 6441 6442 // see if we need to keep searching for this 6443 if (tempIndex == -1) { 6444 noMoreMatchesForReplIndex[i] = true; 6445 } else if (textIndex == -1 || tempIndex < textIndex) { 6446 textIndex = tempIndex; 6447 replaceIndex = i; 6448 } 6449 } 6450 // NOTE: logic mostly below END 6451 6452 // no search strings found, we are done 6453 if (textIndex == -1) { 6454 return text; 6455 } 6456 6457 int start = 0; 6458 6459 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6460 int increase = 0; 6461 6462 // count the replacement text elements that are larger than their corresponding text being replaced 6463 for (int i = 0; i < searchList.length; i++) { 6464 if (searchList[i] == null || replacementList[i] == null) { 6465 continue; 6466 } 6467 final int greater = replacementList[i].length() - searchList[i].length(); 6468 if (greater > 0) { 6469 increase += 3 * greater; // assume 3 matches 6470 } 6471 } 6472 // have upper-bound at 20% increase, then let Java take over 6473 increase = Math.min(increase, text.length() / 5); 6474 6475 final StringBuilder buf = new StringBuilder(text.length() + increase); 6476 6477 while (textIndex != -1) { 6478 6479 for (int i = start; i < textIndex; i++) { 6480 buf.append(text.charAt(i)); 6481 } 6482 buf.append(replacementList[replaceIndex]); 6483 6484 start = textIndex + searchList[replaceIndex].length(); 6485 6486 textIndex = -1; 6487 replaceIndex = -1; 6488 // find the next earliest match 6489 // NOTE: logic mostly duplicated above START 6490 for (int i = 0; i < searchLength; i++) { 6491 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6492 continue; 6493 } 6494 tempIndex = text.indexOf(searchList[i], start); 6495 6496 // see if we need to keep searching for this 6497 if (tempIndex == -1) { 6498 noMoreMatchesForReplIndex[i] = true; 6499 } else if (textIndex == -1 || tempIndex < textIndex) { 6500 textIndex = tempIndex; 6501 replaceIndex = i; 6502 } 6503 } 6504 // NOTE: logic duplicated above END 6505 6506 } 6507 final int textLength = text.length(); 6508 for (int i = start; i < textLength; i++) { 6509 buf.append(text.charAt(i)); 6510 } 6511 final String result = buf.toString(); 6512 if (!repeat) { 6513 return result; 6514 } 6515 6516 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6517 } 6518 6519 /** 6520 * Replaces all occurrences of Strings within another String. 6521 * 6522 * <p> 6523 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. 6524 * </p> 6525 * 6526 * <pre> 6527 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6528 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6529 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6530 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6531 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6532 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6533 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6534 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6535 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6536 * (example of how it repeats) 6537 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6538 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException 6539 * </pre> 6540 * 6541 * @param text text to search and replace in, no-op if null. 6542 * @param searchList the Strings to search for, no-op if null. 6543 * @param replacementList the Strings to replace them with, no-op if null. 6544 * @return the text with any replacements processed, {@code null} if null String input. 6545 * @throws IllegalStateException if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6546 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6547 * @since 2.4 6548 */ 6549 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6550 final int timeToLive = Math.max(ArrayUtils.getLength(searchList), DEFAULT_TTL); 6551 return replaceEach(text, searchList, replacementList, true, timeToLive); 6552 } 6553 6554 /** 6555 * Replaces the first substring of the text string that matches the given regular expression with the given replacement. 6556 * 6557 * This method is a {@code null} safe equivalent to: 6558 * <ul> 6559 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6560 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6561 * </ul> 6562 * 6563 * <p> 6564 * A {@code null} reference passed to this method is a no-op. 6565 * </p> 6566 * 6567 * <p> 6568 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as 6569 * single-line mode in Perl. 6570 * </p> 6571 * 6572 * <pre>{@code 6573 * StringUtils.replaceFirst(null, *, *) = null 6574 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6575 * StringUtils.replaceFirst("any", *, null) = "any" 6576 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6577 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6578 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6579 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6580 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6581 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6582 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6583 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6584 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6585 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6586 * }</pre> 6587 * 6588 * @param text text to search and replace in, may be null. 6589 * @param regex the regular expression to which this string is to be matched. 6590 * @param replacement the string to be substituted for the first match. 6591 * @return the text with the first replacement processed, {@code null} if null String input. 6592 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 6593 * @see String#replaceFirst(String, String) 6594 * @see java.util.regex.Pattern 6595 * @see java.util.regex.Pattern#DOTALL 6596 * @since 3.5 6597 * @deprecated Moved to RegExUtils. 6598 */ 6599 @Deprecated 6600 public static String replaceFirst(final String text, final String regex, final String replacement) { 6601 return RegExUtils.replaceFirst(text, regex, replacement); 6602 } 6603 6604 /** 6605 * Case insensitively replaces all occurrences of a String within another String. 6606 * 6607 * <p> 6608 * A {@code null} reference passed to this method is a no-op. 6609 * </p> 6610 * 6611 * <pre> 6612 * StringUtils.replaceIgnoreCase(null, *, *) = null 6613 * StringUtils.replaceIgnoreCase("", *, *) = "" 6614 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6615 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6616 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6617 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6618 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6619 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6620 * </pre> 6621 * 6622 * @param text text to search and replace in, may be null. 6623 * @param searchString the String to search for (case-insensitive), may be null. 6624 * @param replacement the String to replace it with, may be null. 6625 * @return the text with any replacements processed, {@code null} if null String input. 6626 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6627 * @since 3.5 6628 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)} 6629 */ 6630 @Deprecated 6631 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6632 return Strings.CI.replace(text, searchString, replacement); 6633 } 6634 6635 /** 6636 * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6637 * 6638 * <p> 6639 * A {@code null} reference passed to this method is a no-op. 6640 * </p> 6641 * 6642 * <pre> 6643 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6644 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6645 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6646 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6647 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6648 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6649 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6650 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6651 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6652 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6653 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6654 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6655 * </pre> 6656 * 6657 * @param text text to search and replace in, may be null. 6658 * @param searchString the String to search for (case-insensitive), may be null. 6659 * @param replacement the String to replace it with, may be null. 6660 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6661 * @return the text with any replacements processed, {@code null} if null String input. 6662 * @since 3.5 6663 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)} 6664 */ 6665 @Deprecated 6666 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6667 return Strings.CI.replace(text, searchString, replacement, max); 6668 } 6669 6670 /** 6671 * Replaces a String with another String inside a larger String, once. 6672 * 6673 * <p> 6674 * A {@code null} reference passed to this method is a no-op. 6675 * </p> 6676 * 6677 * <pre> 6678 * StringUtils.replaceOnce(null, *, *) = null 6679 * StringUtils.replaceOnce("", *, *) = "" 6680 * StringUtils.replaceOnce("any", null, *) = "any" 6681 * StringUtils.replaceOnce("any", *, null) = "any" 6682 * StringUtils.replaceOnce("any", "", *) = "any" 6683 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6684 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6685 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6686 * </pre> 6687 * 6688 * @param text text to search and replace in, may be null. 6689 * @param searchString the String to search for, may be null. 6690 * @param replacement the String to replace with, may be null. 6691 * @return the text with any replacements processed, {@code null} if null String input. 6692 * @see #replace(String text, String searchString, String replacement, int max) 6693 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)} 6694 */ 6695 @Deprecated 6696 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6697 return Strings.CS.replaceOnce(text, searchString, replacement); 6698 } 6699 6700 /** 6701 * Case insensitively replaces a String with another String inside a larger String, once. 6702 * 6703 * <p> 6704 * A {@code null} reference passed to this method is a no-op. 6705 * </p> 6706 * 6707 * <pre> 6708 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6709 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6710 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6711 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6712 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6713 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6714 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6715 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6716 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6717 * </pre> 6718 * 6719 * @param text text to search and replace in, may be null. 6720 * @param searchString the String to search for (case-insensitive), may be null. 6721 * @param replacement the String to replace with, may be null. 6722 * @return the text with any replacements processed, {@code null} if null String input. 6723 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6724 * @since 3.5 6725 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)} 6726 */ 6727 @Deprecated 6728 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6729 return Strings.CI.replaceOnce(text, searchString, replacement); 6730 } 6731 6732 /** 6733 * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL} 6734 * option. DOTALL is also known as single-line mode in Perl. 6735 * 6736 * This call is a {@code null} safe equivalent to: 6737 * <ul> 6738 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6739 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6740 * </ul> 6741 * 6742 * <p> 6743 * A {@code null} reference passed to this method is a no-op. 6744 * </p> 6745 * 6746 * <pre>{@code 6747 * StringUtils.replacePattern(null, *, *) = null 6748 * StringUtils.replacePattern("any", (String) null, *) = "any" 6749 * StringUtils.replacePattern("any", *, null) = "any" 6750 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6751 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6752 * StringUtils.replacePattern("", ".+", "zzz") = "" 6753 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6754 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6755 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6756 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6757 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6758 * }</pre> 6759 * 6760 * @param source the source string. 6761 * @param regex the regular expression to which this string is to be matched. 6762 * @param replacement the string to be substituted for each match. 6763 * @return The resulting {@link String}. 6764 * @see #replaceAll(String, String, String) 6765 * @see String#replaceAll(String, String) 6766 * @see Pattern#DOTALL 6767 * @since 3.2 6768 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6769 * @deprecated Moved to RegExUtils. 6770 */ 6771 @Deprecated 6772 public static String replacePattern(final String source, final String regex, final String replacement) { 6773 return RegExUtils.replacePattern(source, regex, replacement); 6774 } 6775 6776 /** 6777 * Reverses a String as per {@link StringBuilder#reverse()}. 6778 * 6779 * <p> 6780 * A {@code null} String returns {@code null}. 6781 * </p> 6782 * 6783 * <pre> 6784 * StringUtils.reverse(null) = null 6785 * StringUtils.reverse("") = "" 6786 * StringUtils.reverse("bat") = "tab" 6787 * </pre> 6788 * 6789 * @param str the String to reverse, may be null. 6790 * @return the reversed String, {@code null} if null String input. 6791 */ 6792 public static String reverse(final String str) { 6793 if (str == null) { 6794 return null; 6795 } 6796 return new StringBuilder(str).reverse().toString(); 6797 } 6798 6799 /** 6800 * Reverses a String that is delimited by a specific character. 6801 * 6802 * <p> 6803 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}). 6804 * </p> 6805 * 6806 * <pre> 6807 * StringUtils.reverseDelimited(null, *) = null 6808 * StringUtils.reverseDelimited("", *) = "" 6809 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 6810 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 6811 * </pre> 6812 * 6813 * @param str the String to reverse, may be null. 6814 * @param separatorChar the separator character to use. 6815 * @return the reversed String, {@code null} if null String input. 6816 * @since 2.0 6817 */ 6818 public static String reverseDelimited(final String str, final char separatorChar) { 6819 final String[] strs = split(str, separatorChar); 6820 ArrayUtils.reverse(strs); 6821 return join(strs, separatorChar); 6822 } 6823 6824 /** 6825 * Gets the rightmost {@code len} characters of a String. 6826 * 6827 * <p> 6828 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an an exception. An empty String is 6829 * returned if len is negative. 6830 * </p> 6831 * 6832 * <pre> 6833 * StringUtils.right(null, *) = null 6834 * StringUtils.right(*, -ve) = "" 6835 * StringUtils.right("", *) = "" 6836 * StringUtils.right("abc", 0) = "" 6837 * StringUtils.right("abc", 2) = "bc" 6838 * StringUtils.right("abc", 4) = "abc" 6839 * </pre> 6840 * 6841 * @param str the String to get the rightmost characters from, may be null. 6842 * @param len the length of the required String. 6843 * @return the rightmost characters, {@code null} if null String input. 6844 */ 6845 public static String right(final String str, final int len) { 6846 if (str == null) { 6847 return null; 6848 } 6849 if (len < 0) { 6850 return EMPTY; 6851 } 6852 if (str.length() <= len) { 6853 return str; 6854 } 6855 return str.substring(str.length() - len); 6856 } 6857 6858 /** 6859 * Right pad a String with spaces (' '). 6860 * 6861 * <p> 6862 * The String is padded to the size of {@code size}. 6863 * </p> 6864 * 6865 * <pre> 6866 * StringUtils.rightPad(null, *) = null 6867 * StringUtils.rightPad("", 3) = " " 6868 * StringUtils.rightPad("bat", 3) = "bat" 6869 * StringUtils.rightPad("bat", 5) = "bat " 6870 * StringUtils.rightPad("bat", 1) = "bat" 6871 * StringUtils.rightPad("bat", -1) = "bat" 6872 * </pre> 6873 * 6874 * @param str the String to pad out, may be null. 6875 * @param size the size to pad to. 6876 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6877 */ 6878 public static String rightPad(final String str, final int size) { 6879 return rightPad(str, size, ' '); 6880 } 6881 6882 /** 6883 * Right pad a String with a specified character. 6884 * 6885 * <p> 6886 * The String is padded to the size of {@code size}. 6887 * </p> 6888 * 6889 * <pre> 6890 * StringUtils.rightPad(null, *, *) = null 6891 * StringUtils.rightPad("", 3, 'z') = "zzz" 6892 * StringUtils.rightPad("bat", 3, 'z') = "bat" 6893 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 6894 * StringUtils.rightPad("bat", 1, 'z') = "bat" 6895 * StringUtils.rightPad("bat", -1, 'z') = "bat" 6896 * </pre> 6897 * 6898 * @param str the String to pad out, may be null. 6899 * @param size the size to pad to. 6900 * @param padChar the character to pad with. 6901 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6902 * @since 2.0 6903 */ 6904 public static String rightPad(final String str, final int size, final char padChar) { 6905 if (str == null) { 6906 return null; 6907 } 6908 final int pads = size - str.length(); 6909 if (pads <= 0) { 6910 return str; // returns original String when possible 6911 } 6912 if (pads > PAD_LIMIT) { 6913 return rightPad(str, size, String.valueOf(padChar)); 6914 } 6915 return str.concat(repeat(padChar, pads)); 6916 } 6917 6918 /** 6919 * Right pad a String with a specified String. 6920 * 6921 * <p> 6922 * The String is padded to the size of {@code size}. 6923 * </p> 6924 * 6925 * <pre> 6926 * StringUtils.rightPad(null, *, *) = null 6927 * StringUtils.rightPad("", 3, "z") = "zzz" 6928 * StringUtils.rightPad("bat", 3, "yz") = "bat" 6929 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 6930 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 6931 * StringUtils.rightPad("bat", 1, "yz") = "bat" 6932 * StringUtils.rightPad("bat", -1, "yz") = "bat" 6933 * StringUtils.rightPad("bat", 5, null) = "bat " 6934 * StringUtils.rightPad("bat", 5, "") = "bat " 6935 * </pre> 6936 * 6937 * @param str the String to pad out, may be null. 6938 * @param size the size to pad to. 6939 * @param padStr the String to pad with, null or empty treated as single space. 6940 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6941 */ 6942 public static String rightPad(final String str, final int size, String padStr) { 6943 if (str == null) { 6944 return null; 6945 } 6946 if (isEmpty(padStr)) { 6947 padStr = SPACE; 6948 } 6949 final int padLen = padStr.length(); 6950 final int strLen = str.length(); 6951 final int pads = size - strLen; 6952 if (pads <= 0) { 6953 return str; // returns original String when possible 6954 } 6955 if (padLen == 1 && pads <= PAD_LIMIT) { 6956 return rightPad(str, size, padStr.charAt(0)); 6957 } 6958 if (pads == padLen) { 6959 return str.concat(padStr); 6960 } 6961 if (pads < padLen) { 6962 return str.concat(padStr.substring(0, pads)); 6963 } 6964 final char[] padding = new char[pads]; 6965 final char[] padChars = padStr.toCharArray(); 6966 for (int i = 0; i < pads; i++) { 6967 padding[i] = padChars[i % padLen]; 6968 } 6969 return str.concat(new String(padding)); 6970 } 6971 6972 /** 6973 * Rotate (circular shift) a String of {@code shift} characters. 6974 * <ul> 6975 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 6976 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 6977 * </ul> 6978 * 6979 * <pre> 6980 * StringUtils.rotate(null, *) = null 6981 * StringUtils.rotate("", *) = "" 6982 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 6983 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 6984 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 6985 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 6986 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 6987 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 6988 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 6989 * </pre> 6990 * 6991 * @param str the String to rotate, may be null. 6992 * @param shift number of time to shift (positive : right shift, negative : left shift). 6993 * @return the rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input. 6994 * @since 3.5 6995 */ 6996 public static String rotate(final String str, final int shift) { 6997 if (str == null) { 6998 return null; 6999 } 7000 final int strLen = str.length(); 7001 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7002 return str; 7003 } 7004 final StringBuilder builder = new StringBuilder(strLen); 7005 final int offset = -(shift % strLen); 7006 builder.append(substring(str, offset)); 7007 builder.append(substring(str, 0, offset)); 7008 return builder.toString(); 7009 } 7010 7011 /** 7012 * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 7013 * 7014 * <p> 7015 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7016 * StrTokenizer class. 7017 * </p> 7018 * 7019 * <p> 7020 * A {@code null} input String returns {@code null}. 7021 * </p> 7022 * 7023 * <pre> 7024 * StringUtils.split(null) = null 7025 * StringUtils.split("") = [] 7026 * StringUtils.split("abc def") = ["abc", "def"] 7027 * StringUtils.split("abc def") = ["abc", "def"] 7028 * StringUtils.split(" abc ") = ["abc"] 7029 * </pre> 7030 * 7031 * @param str the String to parse, may be null. 7032 * @return an array of parsed Strings, {@code null} if null String input. 7033 */ 7034 public static String[] split(final String str) { 7035 return split(str, null, -1); 7036 } 7037 7038 /** 7039 * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer. 7040 * 7041 * <p> 7042 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7043 * StrTokenizer class. 7044 * </p> 7045 * 7046 * <p> 7047 * A {@code null} input String returns {@code null}. 7048 * </p> 7049 * 7050 * <pre> 7051 * StringUtils.split(null, *) = null 7052 * StringUtils.split("", *) = [] 7053 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7054 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7055 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7056 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7057 * </pre> 7058 * 7059 * @param str the String to parse, may be null. 7060 * @param separatorChar the character used as the delimiter. 7061 * @return an array of parsed Strings, {@code null} if null String input. 7062 * @since 2.0 7063 */ 7064 public static String[] split(final String str, final char separatorChar) { 7065 return splitWorker(str, separatorChar, false); 7066 } 7067 7068 /** 7069 * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer. 7070 * 7071 * <p> 7072 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7073 * StrTokenizer class. 7074 * </p> 7075 * 7076 * <p> 7077 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7078 * </p> 7079 * 7080 * <pre> 7081 * StringUtils.split(null, *) = null 7082 * StringUtils.split("", *) = [] 7083 * StringUtils.split("abc def", null) = ["abc", "def"] 7084 * StringUtils.split("abc def", " ") = ["abc", "def"] 7085 * StringUtils.split("abc def", " ") = ["abc", "def"] 7086 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7087 * </pre> 7088 * 7089 * @param str the String to parse, may be null. 7090 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7091 * @return an array of parsed Strings, {@code null} if null String input. 7092 */ 7093 public static String[] split(final String str, final String separatorChars) { 7094 return splitWorker(str, separatorChars, -1, false); 7095 } 7096 7097 /** 7098 * Splits the provided text into an array with a maximum length, separators specified. 7099 * 7100 * <p> 7101 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. 7102 * </p> 7103 * 7104 * <p> 7105 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7106 * </p> 7107 * 7108 * <p> 7109 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7110 * strings (including separator characters). 7111 * </p> 7112 * 7113 * <pre> 7114 * StringUtils.split(null, *, *) = null 7115 * StringUtils.split("", *, *) = [] 7116 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7117 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7118 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7119 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7120 * </pre> 7121 * 7122 * @param str the String to parse, may be null. 7123 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7124 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7125 * @return an array of parsed Strings, {@code null} if null String input. 7126 */ 7127 public static String[] split(final String str, final String separatorChars, final int max) { 7128 return splitWorker(str, separatorChars, max, false); 7129 } 7130 7131 /** 7132 * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned 7133 * as complete tokens. 7134 * 7135 * <pre> 7136 * StringUtils.splitByCharacterType(null) = null 7137 * StringUtils.splitByCharacterType("") = [] 7138 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7139 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7140 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7141 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7142 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7143 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7144 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7145 * </pre> 7146 * 7147 * @param str the String to split, may be {@code null}. 7148 * @return an array of parsed Strings, {@code null} if null String input. 7149 * @since 2.4 7150 */ 7151 public static String[] splitByCharacterType(final String str) { 7152 return splitByCharacterType(str, false); 7153 } 7154 7155 /** 7156 * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned 7157 * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@code Character.UPPERCASE_LETTER}, if any, 7158 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, 7159 * {@code Character.UPPERCASE_LETTER} token. 7160 * 7161 * @param str the String to split, may be {@code null}. 7162 * @param camelCase whether to use so-called "camel-case" for letter types. 7163 * @return an array of parsed Strings, {@code null} if null String input. 7164 * @since 2.4 7165 */ 7166 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7167 if (str == null) { 7168 return null; 7169 } 7170 if (str.isEmpty()) { 7171 return ArrayUtils.EMPTY_STRING_ARRAY; 7172 } 7173 final char[] c = str.toCharArray(); 7174 final List<String> list = new ArrayList<>(); 7175 int tokenStart = 0; 7176 int currentType = Character.getType(c[tokenStart]); 7177 for (int pos = tokenStart + 1; pos < c.length; pos++) { 7178 final int type = Character.getType(c[pos]); 7179 if (type == currentType) { 7180 continue; 7181 } 7182 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7183 final int newTokenStart = pos - 1; 7184 if (newTokenStart != tokenStart) { 7185 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7186 tokenStart = newTokenStart; 7187 } 7188 } else { 7189 list.add(new String(c, tokenStart, pos - tokenStart)); 7190 tokenStart = pos; 7191 } 7192 currentType = type; 7193 } 7194 list.add(new String(c, tokenStart, c.length - tokenStart)); 7195 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7196 } 7197 7198 /** 7199 * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned 7200 * as complete tokens, with the following exception: the character of type {@code Character.UPPERCASE_LETTER}, if any, immediately preceding a token of type 7201 * {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@code Character.UPPERCASE_LETTER} token. 7202 * 7203 * <pre> 7204 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7205 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7206 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7207 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7208 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7209 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7210 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7211 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7212 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7213 * </pre> 7214 * 7215 * @param str the String to split, may be {@code null}. 7216 * @return an array of parsed Strings, {@code null} if null String input. 7217 * @since 2.4 7218 */ 7219 public static String[] splitByCharacterTypeCamelCase(final String str) { 7220 return splitByCharacterType(str, true); 7221 } 7222 7223 /** 7224 * Splits the provided text into an array, separator string specified. 7225 * 7226 * <p> 7227 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7228 * </p> 7229 * 7230 * <p> 7231 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7232 * </p> 7233 * 7234 * <pre> 7235 * StringUtils.splitByWholeSeparator(null, *) = null 7236 * StringUtils.splitByWholeSeparator("", *) = [] 7237 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7238 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7239 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7240 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7241 * </pre> 7242 * 7243 * @param str the String to parse, may be null. 7244 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7245 * @return an array of parsed Strings, {@code null} if null String was input. 7246 */ 7247 public static String[] splitByWholeSeparator(final String str, final String separator) { 7248 return splitByWholeSeparatorWorker(str, separator, -1, false); 7249 } 7250 7251 /** 7252 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7253 * 7254 * <p> 7255 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7256 * </p> 7257 * 7258 * <p> 7259 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7260 * </p> 7261 * 7262 * <pre> 7263 * StringUtils.splitByWholeSeparator(null, *, *) = null 7264 * StringUtils.splitByWholeSeparator("", *, *) = [] 7265 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7266 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7267 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7268 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7269 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7270 * </pre> 7271 * 7272 * @param str the String to parse, may be null. 7273 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7274 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7275 * @return an array of parsed Strings, {@code null} if null String was input. 7276 */ 7277 public static String[] splitByWholeSeparator(final String str, final String separator, final int max) { 7278 return splitByWholeSeparatorWorker(str, separator, max, false); 7279 } 7280 7281 /** 7282 * Splits the provided text into an array, separator string specified. 7283 * 7284 * <p> 7285 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7286 * split use the StrTokenizer class. 7287 * </p> 7288 * 7289 * <p> 7290 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7291 * </p> 7292 * 7293 * <pre> 7294 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7295 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7296 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7297 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7298 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7299 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7300 * </pre> 7301 * 7302 * @param str the String to parse, may be null. 7303 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7304 * @return an array of parsed Strings, {@code null} if null String was input. 7305 * @since 2.4 7306 */ 7307 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7308 return splitByWholeSeparatorWorker(str, separator, -1, true); 7309 } 7310 7311 /** 7312 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7313 * 7314 * <p> 7315 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7316 * split use the StrTokenizer class. 7317 * </p> 7318 * 7319 * <p> 7320 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7321 * </p> 7322 * 7323 * <pre> 7324 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7325 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7326 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7327 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7328 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7329 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7330 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7331 * </pre> 7332 * 7333 * @param str the String to parse, may be null. 7334 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7335 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7336 * @return an array of parsed Strings, {@code null} if null String was input. 7337 * @since 2.4 7338 */ 7339 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7340 return splitByWholeSeparatorWorker(str, separator, max, true); 7341 } 7342 7343 /** 7344 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7345 * 7346 * @param str the String to parse, may be {@code null}. 7347 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7348 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7349 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7350 * one separator. 7351 * @return an array of parsed Strings, {@code null} if null String input. 7352 * @since 2.4 7353 */ 7354 private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) { 7355 if (str == null) { 7356 return null; 7357 } 7358 final int len = str.length(); 7359 if (len == 0) { 7360 return ArrayUtils.EMPTY_STRING_ARRAY; 7361 } 7362 if (separator == null || EMPTY.equals(separator)) { 7363 // Split on whitespace. 7364 return splitWorker(str, null, max, preserveAllTokens); 7365 } 7366 final int separatorLength = separator.length(); 7367 final ArrayList<String> substrings = new ArrayList<>(); 7368 int numberOfSubstrings = 0; 7369 int beg = 0; 7370 int end = 0; 7371 while (end < len) { 7372 end = str.indexOf(separator, beg); 7373 if (end > -1) { 7374 if (end > beg) { 7375 numberOfSubstrings += 1; 7376 if (numberOfSubstrings == max) { 7377 end = len; 7378 substrings.add(str.substring(beg)); 7379 } else { 7380 // The following is OK, because String.substring( beg, end ) excludes 7381 // the character at the position 'end'. 7382 substrings.add(str.substring(beg, end)); 7383 // Set the starting point for the next search. 7384 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7385 // which is the right calculation: 7386 beg = end + separatorLength; 7387 } 7388 } else { 7389 // We found a consecutive occurrence of the separator, so skip it. 7390 if (preserveAllTokens) { 7391 numberOfSubstrings += 1; 7392 if (numberOfSubstrings == max) { 7393 end = len; 7394 substrings.add(str.substring(beg)); 7395 } else { 7396 substrings.add(EMPTY); 7397 } 7398 } 7399 beg = end + separatorLength; 7400 } 7401 } else { 7402 // String.substring( beg ) goes from 'beg' to the end of the String. 7403 substrings.add(str.substring(beg)); 7404 end = len; 7405 } 7406 } 7407 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7408 } 7409 7410 /** 7411 * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators. 7412 * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}. 7413 * 7414 * <p> 7415 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7416 * split use the StrTokenizer class. 7417 * </p> 7418 * 7419 * <p> 7420 * A {@code null} input String returns {@code null}. 7421 * </p> 7422 * 7423 * <pre> 7424 * StringUtils.splitPreserveAllTokens(null) = null 7425 * StringUtils.splitPreserveAllTokens("") = [] 7426 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7427 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7428 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7429 * </pre> 7430 * 7431 * @param str the String to parse, may be {@code null}. 7432 * @return an array of parsed Strings, {@code null} if null String input. 7433 * @since 2.1 7434 */ 7435 public static String[] splitPreserveAllTokens(final String str) { 7436 return splitWorker(str, null, -1, true); 7437 } 7438 7439 /** 7440 * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7441 * alternative to using StringTokenizer. 7442 * 7443 * <p> 7444 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7445 * split use the StrTokenizer class. 7446 * </p> 7447 * 7448 * <p> 7449 * A {@code null} input String returns {@code null}. 7450 * </p> 7451 * 7452 * <pre> 7453 * StringUtils.splitPreserveAllTokens(null, *) = null 7454 * StringUtils.splitPreserveAllTokens("", *) = [] 7455 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7456 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7457 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7458 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7459 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7460 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7461 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7462 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "a", "b", "c"] 7463 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", "a", "b", "c"] 7464 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", "a", "b", "c", ""] 7465 * </pre> 7466 * 7467 * @param str the String to parse, may be {@code null}. 7468 * @param separatorChar the character used as the delimiter, {@code null} splits on whitespace. 7469 * @return an array of parsed Strings, {@code null} if null String input. 7470 * @since 2.1 7471 */ 7472 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7473 return splitWorker(str, separatorChar, true); 7474 } 7475 7476 /** 7477 * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7478 * alternative to using StringTokenizer. 7479 * 7480 * <p> 7481 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7482 * split use the StrTokenizer class. 7483 * </p> 7484 * 7485 * <p> 7486 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7487 * </p> 7488 * 7489 * <pre> 7490 * StringUtils.splitPreserveAllTokens(null, *) = null 7491 * StringUtils.splitPreserveAllTokens("", *) = [] 7492 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7493 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7494 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", "def"] 7495 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7496 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7497 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7498 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", "cd", "ef"] 7499 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", "cd", "ef"] 7500 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", "cd", "ef"] 7501 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", "cd", "ef", ""] 7502 * </pre> 7503 * 7504 * @param str the String to parse, may be {@code null}. 7505 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7506 * @return an array of parsed Strings, {@code null} if null String input. 7507 * @since 2.1 7508 */ 7509 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7510 return splitWorker(str, separatorChars, -1, true); 7511 } 7512 7513 /** 7514 * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent 7515 * separators. 7516 * 7517 * <p> 7518 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are 7519 * treated as one separator. 7520 * </p> 7521 * 7522 * <p> 7523 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7524 * </p> 7525 * 7526 * <p> 7527 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7528 * strings (including separator characters). 7529 * </p> 7530 * 7531 * <pre> 7532 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7533 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7534 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7535 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7536 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7537 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7538 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7539 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7540 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7541 * </pre> 7542 * 7543 * @param str the String to parse, may be {@code null}. 7544 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7545 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7546 * @return an array of parsed Strings, {@code null} if null String input. 7547 * @since 2.1 7548 */ 7549 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7550 return splitWorker(str, separatorChars, max, true); 7551 } 7552 7553 /** 7554 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length. 7555 * 7556 * @param str the String to parse, may be {@code null}. 7557 * @param separatorChar the separate character. 7558 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7559 * one separator. 7560 * @return an array of parsed Strings, {@code null} if null String input. 7561 */ 7562 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7563 // Performance tuned for 2.0 (JDK1.4) 7564 if (str == null) { 7565 return null; 7566 } 7567 final int len = str.length(); 7568 if (len == 0) { 7569 return ArrayUtils.EMPTY_STRING_ARRAY; 7570 } 7571 final List<String> list = new ArrayList<>(); 7572 int i = 0; 7573 int start = 0; 7574 boolean match = false; 7575 boolean lastMatch = false; 7576 while (i < len) { 7577 if (str.charAt(i) == separatorChar) { 7578 if (match || preserveAllTokens) { 7579 list.add(str.substring(start, i)); 7580 match = false; 7581 lastMatch = true; 7582 } 7583 start = ++i; 7584 continue; 7585 } 7586 lastMatch = false; 7587 match = true; 7588 i++; 7589 } 7590 if (match || preserveAllTokens && lastMatch) { 7591 list.add(str.substring(start, i)); 7592 } 7593 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7594 } 7595 7596 /** 7597 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length. 7598 * 7599 * @param str the String to parse, may be {@code null}. 7600 * @param separatorChars the separate character. 7601 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7602 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7603 * one separator. 7604 * @return an array of parsed Strings, {@code null} if null String input. 7605 */ 7606 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7607 // Performance tuned for 2.0 (JDK1.4) 7608 // Direct code is quicker than StringTokenizer. 7609 // Also, StringTokenizer uses isSpace() not isWhitespace() 7610 if (str == null) { 7611 return null; 7612 } 7613 final int len = str.length(); 7614 if (len == 0) { 7615 return ArrayUtils.EMPTY_STRING_ARRAY; 7616 } 7617 final List<String> list = new ArrayList<>(); 7618 int sizePlus1 = 1; 7619 int i = 0; 7620 int start = 0; 7621 boolean match = false; 7622 boolean lastMatch = false; 7623 if (separatorChars == null) { 7624 // Null separator means use whitespace 7625 while (i < len) { 7626 if (Character.isWhitespace(str.charAt(i))) { 7627 if (match || preserveAllTokens) { 7628 lastMatch = true; 7629 if (sizePlus1++ == max) { 7630 i = len; 7631 lastMatch = false; 7632 } 7633 list.add(str.substring(start, i)); 7634 match = false; 7635 } 7636 start = ++i; 7637 continue; 7638 } 7639 lastMatch = false; 7640 match = true; 7641 i++; 7642 } 7643 } else if (separatorChars.length() == 1) { 7644 // Optimize 1 character case 7645 final char sep = separatorChars.charAt(0); 7646 while (i < len) { 7647 if (str.charAt(i) == sep) { 7648 if (match || preserveAllTokens) { 7649 lastMatch = true; 7650 if (sizePlus1++ == max) { 7651 i = len; 7652 lastMatch = false; 7653 } 7654 list.add(str.substring(start, i)); 7655 match = false; 7656 } 7657 start = ++i; 7658 continue; 7659 } 7660 lastMatch = false; 7661 match = true; 7662 i++; 7663 } 7664 } else { 7665 // standard case 7666 while (i < len) { 7667 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 7668 if (match || preserveAllTokens) { 7669 lastMatch = true; 7670 if (sizePlus1++ == max) { 7671 i = len; 7672 lastMatch = false; 7673 } 7674 list.add(str.substring(start, i)); 7675 match = false; 7676 } 7677 start = ++i; 7678 continue; 7679 } 7680 lastMatch = false; 7681 match = true; 7682 i++; 7683 } 7684 } 7685 if (match || preserveAllTokens && lastMatch) { 7686 list.add(str.substring(start, i)); 7687 } 7688 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7689 } 7690 7691 /** 7692 * Tests if a CharSequence starts with a specified prefix. 7693 * 7694 * <p> 7695 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 7696 * </p> 7697 * 7698 * <pre> 7699 * StringUtils.startsWith(null, null) = true 7700 * StringUtils.startsWith(null, "abc") = false 7701 * StringUtils.startsWith("abcdef", null) = false 7702 * StringUtils.startsWith("abcdef", "abc") = true 7703 * StringUtils.startsWith("ABCDEF", "abc") = false 7704 * </pre> 7705 * 7706 * @param str the CharSequence to check, may be null. 7707 * @param prefix the prefix to find, may be null. 7708 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}. 7709 * @see String#startsWith(String) 7710 * @since 2.4 7711 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 7712 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)} 7713 */ 7714 @Deprecated 7715 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7716 return Strings.CS.startsWith(str, prefix); 7717 } 7718 7719 /** 7720 * Tests if a CharSequence starts with any of the provided case-sensitive prefixes. 7721 * 7722 * <pre> 7723 * StringUtils.startsWithAny(null, null) = false 7724 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 7725 * StringUtils.startsWithAny("abcxyz", null) = false 7726 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 7727 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 7728 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7729 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 7730 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 7731 * </pre> 7732 * 7733 * @param sequence the CharSequence to check, may be null. 7734 * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}. 7735 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with 7736 * any of the provided case-sensitive {@code searchStrings}. 7737 * @see StringUtils#startsWith(CharSequence, CharSequence) 7738 * @since 2.5 7739 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 7740 * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)} 7741 */ 7742 @Deprecated 7743 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 7744 return Strings.CS.startsWithAny(sequence, searchStrings); 7745 } 7746 7747 /** 7748 * Case-insensitive check if a CharSequence starts with a specified prefix. 7749 * 7750 * <p> 7751 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 7752 * </p> 7753 * 7754 * <pre> 7755 * StringUtils.startsWithIgnoreCase(null, null) = true 7756 * StringUtils.startsWithIgnoreCase(null, "abc") = false 7757 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 7758 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 7759 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 7760 * </pre> 7761 * 7762 * @param str the CharSequence to check, may be null. 7763 * @param prefix the prefix to find, may be null. 7764 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}. 7765 * @see String#startsWith(String) 7766 * @since 2.4 7767 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 7768 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)} 7769 */ 7770 @Deprecated 7771 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 7772 return Strings.CI.startsWith(str, prefix); 7773 } 7774 7775 /** 7776 * Strips whitespace from the start and end of a String. 7777 * 7778 * <p> 7779 * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 7780 * </p> 7781 * 7782 * <p> 7783 * A {@code null} input String returns {@code null}. 7784 * </p> 7785 * 7786 * <pre> 7787 * StringUtils.strip(null) = null 7788 * StringUtils.strip("") = "" 7789 * StringUtils.strip(" ") = "" 7790 * StringUtils.strip("abc") = "abc" 7791 * StringUtils.strip(" abc") = "abc" 7792 * StringUtils.strip("abc ") = "abc" 7793 * StringUtils.strip(" abc ") = "abc" 7794 * StringUtils.strip(" ab c ") = "ab c" 7795 * </pre> 7796 * 7797 * @param str the String to remove whitespace from, may be null. 7798 * @return the stripped String, {@code null} if null String input. 7799 */ 7800 public static String strip(final String str) { 7801 return strip(str, null); 7802 } 7803 7804 /** 7805 * Strips any of a set of characters from the start and end of a String. This is similar to {@link String#trim()} but allows the characters to be stripped 7806 * to be controlled. 7807 * 7808 * <p> 7809 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7810 * </p> 7811 * 7812 * <p> 7813 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use 7814 * {@link #strip(String)}. 7815 * </p> 7816 * 7817 * <pre> 7818 * StringUtils.strip(null, *) = null 7819 * StringUtils.strip("", *) = "" 7820 * StringUtils.strip("abc", null) = "abc" 7821 * StringUtils.strip(" abc", null) = "abc" 7822 * StringUtils.strip("abc ", null) = "abc" 7823 * StringUtils.strip(" abc ", null) = "abc" 7824 * StringUtils.strip(" abcyx", "xyz") = " abc" 7825 * </pre> 7826 * 7827 * @param str the String to remove characters from, may be null. 7828 * @param stripChars the characters to remove, null treated as whitespace. 7829 * @return the stripped String, {@code null} if null String input. 7830 */ 7831 public static String strip(String str, final String stripChars) { 7832 str = stripStart(str, stripChars); 7833 return stripEnd(str, stripChars); 7834 } 7835 7836 /** 7837 * Removes diacritics (~= accents) from a string. The case will not be altered. 7838 * <p> 7839 * For instance, 'à' will be replaced by 'a'. 7840 * </p> 7841 * <p> 7842 * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a> 7843 * </p> 7844 * 7845 * <pre> 7846 * StringUtils.stripAccents(null) = null 7847 * StringUtils.stripAccents("") = "" 7848 * StringUtils.stripAccents("control") = "control" 7849 * StringUtils.stripAccents("éclair") = "eclair" 7850 * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3") = "abc123" 7851 * StringUtils.stripAccents("\u00BC \u00BD \u00BE") = "1â4 1â2 3â4" 7852 * </pre> 7853 * <p> 7854 * See also <a href="http://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>. 7855 * </p> 7856 * 7857 * @param input String to be stripped. 7858 * @return input text with diacritics removed. 7859 * @since 3.0 7860 */ 7861 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: 7862 // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 7863 public static String stripAccents(final String input) { 7864 if (isEmpty(input)) { 7865 return input; 7866 } 7867 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD)); 7868 convertRemainingAccentCharacters(decomposed); 7869 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 7870 } 7871 7872 /** 7873 * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}. 7874 * 7875 * <p> 7876 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A 7877 * {@code null} array entry will be ignored. 7878 * </p> 7879 * 7880 * <pre> 7881 * StringUtils.stripAll(null) = null 7882 * StringUtils.stripAll([]) = [] 7883 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 7884 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 7885 * </pre> 7886 * 7887 * @param strs the array to remove whitespace from, may be null. 7888 * @return the stripped Strings, {@code null} if null array input. 7889 */ 7890 public static String[] stripAll(final String... strs) { 7891 return stripAll(strs, null); 7892 } 7893 7894 /** 7895 * Strips any of a set of characters from the start and end of every String in an array. 7896 * <p> 7897 * Whitespace is defined by {@link Character#isWhitespace(char)}. 7898 * </p> 7899 * 7900 * <p> 7901 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A 7902 * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}. 7903 * </p> 7904 * 7905 * <pre> 7906 * StringUtils.stripAll(null, *) = null 7907 * StringUtils.stripAll([], *) = [] 7908 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 7909 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 7910 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 7911 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 7912 * </pre> 7913 * 7914 * @param strs the array to remove characters from, may be null. 7915 * @param stripChars the characters to remove, null treated as whitespace. 7916 * @return the stripped Strings, {@code null} if null array input. 7917 */ 7918 public static String[] stripAll(final String[] strs, final String stripChars) { 7919 final int strsLen = ArrayUtils.getLength(strs); 7920 if (strsLen == 0) { 7921 return strs; 7922 } 7923 return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars)); 7924 } 7925 7926 /** 7927 * Strips any of a set of characters from the end of a String. 7928 * 7929 * <p> 7930 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7931 * </p> 7932 * 7933 * <p> 7934 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 7935 * </p> 7936 * 7937 * <pre> 7938 * StringUtils.stripEnd(null, *) = null 7939 * StringUtils.stripEnd("", *) = "" 7940 * StringUtils.stripEnd("abc", "") = "abc" 7941 * StringUtils.stripEnd("abc", null) = "abc" 7942 * StringUtils.stripEnd(" abc", null) = " abc" 7943 * StringUtils.stripEnd("abc ", null) = "abc" 7944 * StringUtils.stripEnd(" abc ", null) = " abc" 7945 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 7946 * StringUtils.stripEnd("120.00", ".0") = "12" 7947 * </pre> 7948 * 7949 * @param str the String to remove characters from, may be null. 7950 * @param stripChars the set of characters to remove, null treated as whitespace. 7951 * @return the stripped String, {@code null} if null String input. 7952 */ 7953 public static String stripEnd(final String str, final String stripChars) { 7954 int end = length(str); 7955 if (end == 0) { 7956 return str; 7957 } 7958 if (stripChars == null) { 7959 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 7960 end--; 7961 } 7962 } else if (stripChars.isEmpty()) { 7963 return str; 7964 } else { 7965 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 7966 end--; 7967 } 7968 } 7969 return str.substring(0, end); 7970 } 7971 7972 /** 7973 * Strips any of a set of characters from the start of a String. 7974 * 7975 * <p> 7976 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7977 * </p> 7978 * 7979 * <p> 7980 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 7981 * </p> 7982 * 7983 * <pre> 7984 * StringUtils.stripStart(null, *) = null 7985 * StringUtils.stripStart("", *) = "" 7986 * StringUtils.stripStart("abc", "") = "abc" 7987 * StringUtils.stripStart("abc", null) = "abc" 7988 * StringUtils.stripStart(" abc", null) = "abc" 7989 * StringUtils.stripStart("abc ", null) = "abc " 7990 * StringUtils.stripStart(" abc ", null) = "abc " 7991 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 7992 * </pre> 7993 * 7994 * @param str the String to remove characters from, may be null. 7995 * @param stripChars the characters to remove, null treated as whitespace. 7996 * @return the stripped String, {@code null} if null String input. 7997 */ 7998 public static String stripStart(final String str, final String stripChars) { 7999 final int strLen = length(str); 8000 if (strLen == 0) { 8001 return str; 8002 } 8003 int start = 0; 8004 if (stripChars == null) { 8005 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8006 start++; 8007 } 8008 } else if (stripChars.isEmpty()) { 8009 return str; 8010 } else { 8011 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 8012 start++; 8013 } 8014 } 8015 return str.substring(start); 8016 } 8017 8018 /** 8019 * Strips whitespace from the start and end of a String returning an empty String if {@code null} input. 8020 * 8021 * <p> 8022 * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8023 * </p> 8024 * 8025 * <pre> 8026 * StringUtils.stripToEmpty(null) = "" 8027 * StringUtils.stripToEmpty("") = "" 8028 * StringUtils.stripToEmpty(" ") = "" 8029 * StringUtils.stripToEmpty("abc") = "abc" 8030 * StringUtils.stripToEmpty(" abc") = "abc" 8031 * StringUtils.stripToEmpty("abc ") = "abc" 8032 * StringUtils.stripToEmpty(" abc ") = "abc" 8033 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8034 * </pre> 8035 * 8036 * @param str the String to be stripped, may be null. 8037 * @return the trimmed String, or an empty String if {@code null} input. 8038 * @since 2.0 8039 */ 8040 public static String stripToEmpty(final String str) { 8041 return str == null ? EMPTY : strip(str, null); 8042 } 8043 8044 /** 8045 * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip. 8046 * 8047 * <p> 8048 * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8049 * </p> 8050 * 8051 * <pre> 8052 * StringUtils.stripToNull(null) = null 8053 * StringUtils.stripToNull("") = null 8054 * StringUtils.stripToNull(" ") = null 8055 * StringUtils.stripToNull("abc") = "abc" 8056 * StringUtils.stripToNull(" abc") = "abc" 8057 * StringUtils.stripToNull("abc ") = "abc" 8058 * StringUtils.stripToNull(" abc ") = "abc" 8059 * StringUtils.stripToNull(" ab c ") = "ab c" 8060 * </pre> 8061 * 8062 * @param str the String to be stripped, may be null. 8063 * @return the stripped String, {@code null} if whitespace, empty or null String input. 8064 * @since 2.0 8065 */ 8066 public static String stripToNull(String str) { 8067 if (str == null) { 8068 return null; 8069 } 8070 str = strip(str, null); 8071 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here 8072 } 8073 8074 /** 8075 * Gets a substring from the specified String avoiding exceptions. 8076 * 8077 * <p> 8078 * A negative start position can be used to start {@code n} characters from the end of the String. 8079 * </p> 8080 * 8081 * <p> 8082 * A {@code null} String will return {@code null}. An empty ("") String will return "". 8083 * </p> 8084 * 8085 * <pre> 8086 * StringUtils.substring(null, *) = null 8087 * StringUtils.substring("", *) = "" 8088 * StringUtils.substring("abc", 0) = "abc" 8089 * StringUtils.substring("abc", 2) = "c" 8090 * StringUtils.substring("abc", 4) = "" 8091 * StringUtils.substring("abc", -2) = "bc" 8092 * StringUtils.substring("abc", -4) = "abc" 8093 * </pre> 8094 * 8095 * @param str the String to get the substring from, may be null. 8096 * @param start the position to start from, negative means count back from the end of the String by this many characters. 8097 * @return substring from start position, {@code null} if null String input. 8098 */ 8099 public static String substring(final String str, int start) { 8100 if (str == null) { 8101 return null; 8102 } 8103 // handle negatives, which means last n characters 8104 if (start < 0) { 8105 start = str.length() + start; // remember start is negative 8106 } 8107 if (start < 0) { 8108 start = 0; 8109 } 8110 if (start > str.length()) { 8111 return EMPTY; 8112 } 8113 return str.substring(start); 8114 } 8115 8116 /** 8117 * Gets a substring from the specified String avoiding exceptions. 8118 * 8119 * <p> 8120 * A negative start position can be used to start/end {@code n} characters from the end of the String. 8121 * </p> 8122 * 8123 * <p> 8124 * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is 8125 * zero-based -- i.e., to start at the beginning of the string use {@code start = 0}. Negative start and end positions can be used to specify offsets 8126 * relative to the end of the String. 8127 * </p> 8128 * 8129 * <p> 8130 * If {@code start} is not strictly to the left of {@code end}, "" is returned. 8131 * </p> 8132 * 8133 * <pre> 8134 * StringUtils.substring(null, *, *) = null 8135 * StringUtils.substring("", * , *) = ""; 8136 * StringUtils.substring("abc", 0, 2) = "ab" 8137 * StringUtils.substring("abc", 2, 0) = "" 8138 * StringUtils.substring("abc", 2, 4) = "c" 8139 * StringUtils.substring("abc", 4, 6) = "" 8140 * StringUtils.substring("abc", 2, 2) = "" 8141 * StringUtils.substring("abc", -2, -1) = "b" 8142 * StringUtils.substring("abc", -4, 2) = "ab" 8143 * </pre> 8144 * 8145 * @param str the String to get the substring from, may be null. 8146 * @param start the position to start from, negative means count back from the end of the String by this many characters. 8147 * @param end the position to end at (exclusive), negative means count back from the end of the String by this many characters. 8148 * @return substring from start position to end position, {@code null} if null String input. 8149 */ 8150 public static String substring(final String str, int start, int end) { 8151 if (str == null) { 8152 return null; 8153 } 8154 // handle negatives 8155 if (end < 0) { 8156 end = str.length() + end; // remember end is negative 8157 } 8158 if (start < 0) { 8159 start = str.length() + start; // remember start is negative 8160 } 8161 // check length next 8162 if (end > str.length()) { 8163 end = str.length(); 8164 } 8165 // if start is greater than end, return "" 8166 if (start > end) { 8167 return EMPTY; 8168 } 8169 if (start < 0) { 8170 start = 0; 8171 } 8172 if (end < 0) { 8173 end = 0; 8174 } 8175 return str.substring(start, end); 8176 } 8177 8178 /** 8179 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8180 * 8181 * <p> 8182 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8183 * 8184 * <p> 8185 * If nothing is found, the empty string is returned. 8186 * </p> 8187 * 8188 * <pre> 8189 * StringUtils.substringAfter(null, *) = null 8190 * StringUtils.substringAfter("", *) = "" 8191 * StringUtils.substringAfter("abc", 'a') = "bc" 8192 * StringUtils.substringAfter("abcba", 'b') = "cba" 8193 * StringUtils.substringAfter("abc", 'c') = "" 8194 * StringUtils.substringAfter("abc", 'd') = "" 8195 * StringUtils.substringAfter(" abc", 32) = "abc" 8196 * </pre> 8197 * 8198 * @param str the String to get a substring from, may be null. 8199 * @param find the character (Unicode code point) to find. 8200 * @return the substring after the first occurrence of the specified character, {@code null} if null String input. 8201 * @since 3.11 8202 */ 8203 public static String substringAfter(final String str, final int find) { 8204 if (isEmpty(str)) { 8205 return str; 8206 } 8207 final int pos = str.indexOf(find); 8208 if (pos == INDEX_NOT_FOUND) { 8209 return EMPTY; 8210 } 8211 return str.substring(pos + 1); 8212 } 8213 8214 /** 8215 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8216 * 8217 * <p> 8218 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the 8219 * empty string if the input string is not {@code null}. 8220 * </p> 8221 * 8222 * <p> 8223 * If nothing is found, the empty string is returned. 8224 * </p> 8225 * 8226 * <pre> 8227 * StringUtils.substringAfter(null, *) = null 8228 * StringUtils.substringAfter("", *) = "" 8229 * StringUtils.substringAfter(*, null) = "" 8230 * StringUtils.substringAfter("abc", "a") = "bc" 8231 * StringUtils.substringAfter("abcba", "b") = "cba" 8232 * StringUtils.substringAfter("abc", "c") = "" 8233 * StringUtils.substringAfter("abc", "d") = "" 8234 * StringUtils.substringAfter("abc", "") = "abc" 8235 * </pre> 8236 * 8237 * @param str the String to get a substring from, may be null. 8238 * @param find the String to find, may be null. 8239 * @return the substring after the first occurrence of the specified string, {@code null} if null String input. 8240 * @since 2.0 8241 */ 8242 public static String substringAfter(final String str, final String find) { 8243 if (isEmpty(str)) { 8244 return str; 8245 } 8246 if (find == null) { 8247 return EMPTY; 8248 } 8249 final int pos = str.indexOf(find); 8250 if (pos == INDEX_NOT_FOUND) { 8251 return EMPTY; 8252 } 8253 return str.substring(pos + find.length()); 8254 } 8255 8256 /** 8257 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8258 * 8259 * <p> 8260 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8261 * 8262 * <p> 8263 * If nothing is found, the empty string is returned. 8264 * </p> 8265 * 8266 * <pre> 8267 * StringUtils.substringAfterLast(null, *) = null 8268 * StringUtils.substringAfterLast("", *) = "" 8269 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8270 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8271 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8272 * StringUtils.substringAfterLast("abc", 'c') = "" 8273 * StringUtils.substringAfterLast("a", 'a') = "" 8274 * StringUtils.substringAfterLast("a", 'z') = "" 8275 * </pre> 8276 * 8277 * @param str the String to get a substring from, may be null. 8278 * @param find the character (Unicode code point) to find. 8279 * @return the substring after the last occurrence of the specified character, {@code null} if null String input. 8280 * @since 3.11 8281 */ 8282 public static String substringAfterLast(final String str, final int find) { 8283 if (isEmpty(str)) { 8284 return str; 8285 } 8286 final int pos = str.lastIndexOf(find); 8287 if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) { 8288 return EMPTY; 8289 } 8290 return str.substring(pos + 1); 8291 } 8292 8293 /** 8294 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8295 * 8296 * <p> 8297 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will 8298 * return the empty string if the input string is not {@code null}. 8299 * </p> 8300 * 8301 * <p> 8302 * If nothing is found, the empty string is returned. 8303 * </p> 8304 * 8305 * <pre> 8306 * StringUtils.substringAfterLast(null, *) = null 8307 * StringUtils.substringAfterLast("", *) = "" 8308 * StringUtils.substringAfterLast(*, "") = "" 8309 * StringUtils.substringAfterLast(*, null) = "" 8310 * StringUtils.substringAfterLast("abc", "a") = "bc" 8311 * StringUtils.substringAfterLast("abcba", "b") = "a" 8312 * StringUtils.substringAfterLast("abc", "c") = "" 8313 * StringUtils.substringAfterLast("a", "a") = "" 8314 * StringUtils.substringAfterLast("a", "z") = "" 8315 * </pre> 8316 * 8317 * @param str the String to get a substring from, may be null. 8318 * @param find the String to find, may be null. 8319 * @return the substring after the last occurrence of the specified string, {@code null} if null String input. 8320 * @since 2.0 8321 */ 8322 public static String substringAfterLast(final String str, final String find) { 8323 if (isEmpty(str)) { 8324 return str; 8325 } 8326 if (isEmpty(find)) { 8327 return EMPTY; 8328 } 8329 final int pos = str.lastIndexOf(find); 8330 if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) { 8331 return EMPTY; 8332 } 8333 return str.substring(pos + find.length()); 8334 } 8335 8336 /** 8337 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8338 * 8339 * <p> 8340 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8341 * </p> 8342 * 8343 * <p> 8344 * If nothing is found, the string input is returned. 8345 * </p> 8346 * 8347 * <pre> 8348 * StringUtils.substringBefore(null, *) = null 8349 * StringUtils.substringBefore("", *) = "" 8350 * StringUtils.substringBefore("abc", 'a') = "" 8351 * StringUtils.substringBefore("abcba", 'b') = "a" 8352 * StringUtils.substringBefore("abc", 'c') = "ab" 8353 * StringUtils.substringBefore("abc", 'd') = "abc" 8354 * </pre> 8355 * 8356 * @param str the String to get a substring from, may be null. 8357 * @param find the character (Unicode code point) to find. 8358 * @return the substring before the first occurrence of the specified character, {@code null} if null String input. 8359 * @since 3.12.0 8360 */ 8361 public static String substringBefore(final String str, final int find) { 8362 if (isEmpty(str)) { 8363 return str; 8364 } 8365 final int pos = str.indexOf(find); 8366 if (pos == INDEX_NOT_FOUND) { 8367 return str; 8368 } 8369 return str.substring(0, pos); 8370 } 8371 8372 /** 8373 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8374 * 8375 * <p> 8376 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the 8377 * input string. 8378 * </p> 8379 * 8380 * <p> 8381 * If nothing is found, the string input is returned. 8382 * </p> 8383 * 8384 * <pre> 8385 * StringUtils.substringBefore(null, *) = null 8386 * StringUtils.substringBefore("", *) = "" 8387 * StringUtils.substringBefore("abc", "a") = "" 8388 * StringUtils.substringBefore("abcba", "b") = "a" 8389 * StringUtils.substringBefore("abc", "c") = "ab" 8390 * StringUtils.substringBefore("abc", "d") = "abc" 8391 * StringUtils.substringBefore("abc", "") = "" 8392 * StringUtils.substringBefore("abc", null) = "abc" 8393 * </pre> 8394 * 8395 * @param str the String to get a substring from, may be null. 8396 * @param find the String to find, may be null. 8397 * @return the substring before the first occurrence of the specified string, {@code null} if null String input. 8398 * @since 2.0 8399 */ 8400 public static String substringBefore(final String str, final String find) { 8401 if (isEmpty(str) || find == null) { 8402 return str; 8403 } 8404 if (find.isEmpty()) { 8405 return EMPTY; 8406 } 8407 final int pos = str.indexOf(find); 8408 if (pos == INDEX_NOT_FOUND) { 8409 return str; 8410 } 8411 return str.substring(0, pos); 8412 } 8413 8414 /** 8415 * Gets the substring before the last occurrence of a separator. The separator is not returned. 8416 * 8417 * <p> 8418 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will 8419 * return the input string. 8420 * </p> 8421 * 8422 * <p> 8423 * If nothing is found, the string input is returned. 8424 * </p> 8425 * 8426 * <pre> 8427 * StringUtils.substringBeforeLast(null, *) = null 8428 * StringUtils.substringBeforeLast("", *) = "" 8429 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8430 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8431 * StringUtils.substringBeforeLast("a", "a") = "" 8432 * StringUtils.substringBeforeLast("a", "z") = "a" 8433 * StringUtils.substringBeforeLast("a", null) = "a" 8434 * StringUtils.substringBeforeLast("a", "") = "a" 8435 * </pre> 8436 * 8437 * @param str the String to get a substring from, may be null. 8438 * @param find the String to find, may be null. 8439 * @return the substring before the last occurrence of the specified string, {@code null} if null String input. 8440 * @since 2.0 8441 */ 8442 public static String substringBeforeLast(final String str, final String find) { 8443 if (isEmpty(str) || isEmpty(find)) { 8444 return str; 8445 } 8446 final int pos = str.lastIndexOf(find); 8447 if (pos == INDEX_NOT_FOUND) { 8448 return str; 8449 } 8450 return str.substring(0, pos); 8451 } 8452 8453 /** 8454 * Gets the String that is nested in between two instances of the same String. 8455 * 8456 * <p> 8457 * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}. 8458 * </p> 8459 * 8460 * <pre> 8461 * StringUtils.substringBetween(null, *) = null 8462 * StringUtils.substringBetween("", "") = "" 8463 * StringUtils.substringBetween("", "tag") = null 8464 * StringUtils.substringBetween("tagabctag", null) = null 8465 * StringUtils.substringBetween("tagabctag", "") = "" 8466 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8467 * </pre> 8468 * 8469 * @param str the String containing the substring, may be null. 8470 * @param tag the String before and after the substring, may be null. 8471 * @return the substring, {@code null} if no match. 8472 * @since 2.0 8473 */ 8474 public static String substringBetween(final String str, final String tag) { 8475 return substringBetween(str, tag, tag); 8476 } 8477 8478 /** 8479 * Gets the String that is nested in between two Strings. Only the first match is returned. 8480 * 8481 * <p> 8482 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open and close returns an 8483 * empty string. 8484 * </p> 8485 * 8486 * <pre> 8487 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8488 * StringUtils.substringBetween(null, *, *) = null 8489 * StringUtils.substringBetween(*, null, *) = null 8490 * StringUtils.substringBetween(*, *, null) = null 8491 * StringUtils.substringBetween("", "", "") = "" 8492 * StringUtils.substringBetween("", "", "]") = null 8493 * StringUtils.substringBetween("", "[", "]") = null 8494 * StringUtils.substringBetween("yabcz", "", "") = "" 8495 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8496 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8497 * </pre> 8498 * 8499 * @param str the String containing the substring, may be null. 8500 * @param open the String before the substring, may be null. 8501 * @param close the String after the substring, may be null. 8502 * @return the substring, {@code null} if no match. 8503 * @since 2.0 8504 */ 8505 public static String substringBetween(final String str, final String open, final String close) { 8506 if (!ObjectUtils.allNotNull(str, open, close)) { 8507 return null; 8508 } 8509 final int start = str.indexOf(open); 8510 if (start != INDEX_NOT_FOUND) { 8511 final int end = str.indexOf(close, start + open.length()); 8512 if (end != INDEX_NOT_FOUND) { 8513 return str.substring(start + open.length(), end); 8514 } 8515 } 8516 return null; 8517 } 8518 8519 /** 8520 * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array. 8521 * 8522 * <p> 8523 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns 8524 * {@code null} (no match). 8525 * </p> 8526 * 8527 * <pre> 8528 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8529 * StringUtils.substringsBetween(null, *, *) = null 8530 * StringUtils.substringsBetween(*, null, *) = null 8531 * StringUtils.substringsBetween(*, *, null) = null 8532 * StringUtils.substringsBetween("", "[", "]") = [] 8533 * </pre> 8534 * 8535 * @param str the String containing the substrings, null returns null, empty returns empty. 8536 * @param open the String identifying the start of the substring, empty returns null. 8537 * @param close the String identifying the end of the substring, empty returns null. 8538 * @return a String Array of substrings, or {@code null} if no match. 8539 * @since 2.3 8540 */ 8541 public static String[] substringsBetween(final String str, final String open, final String close) { 8542 if (str == null || isEmpty(open) || isEmpty(close)) { 8543 return null; 8544 } 8545 final int strLen = str.length(); 8546 if (strLen == 0) { 8547 return ArrayUtils.EMPTY_STRING_ARRAY; 8548 } 8549 final int closeLen = close.length(); 8550 final int openLen = open.length(); 8551 final List<String> list = new ArrayList<>(); 8552 int pos = 0; 8553 while (pos < strLen - closeLen) { 8554 int start = str.indexOf(open, pos); 8555 if (start < 0) { 8556 break; 8557 } 8558 start += openLen; 8559 final int end = str.indexOf(close, start); 8560 if (end < 0) { 8561 break; 8562 } 8563 list.add(str.substring(start, end)); 8564 pos = end + closeLen; 8565 } 8566 if (list.isEmpty()) { 8567 return null; 8568 } 8569 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8570 } 8571 8572 /** 8573 * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case. 8574 * 8575 * <ul> 8576 * <li>Upper case character converts to Lower case</li> 8577 * <li>Title case character converts to Lower case</li> 8578 * <li>Lower case character converts to Upper case</li> 8579 * </ul> 8580 * 8581 * <p> 8582 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}. 8583 * </p> 8584 * 8585 * <pre> 8586 * StringUtils.swapCase(null) = null 8587 * StringUtils.swapCase("") = "" 8588 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8589 * </pre> 8590 * 8591 * <p> 8592 * NOTE: This method changed in Lang version 2.0. It no longer performs a word based algorithm. If you only use ASCII, you will notice no change. That 8593 * functionality is available in org.apache.commons.lang3.text.WordUtils. 8594 * </p> 8595 * 8596 * @param str the String to swap case, may be null. 8597 * @return the changed String, {@code null} if null String input. 8598 */ 8599 public static String swapCase(final String str) { 8600 if (isEmpty(str)) { 8601 return str; 8602 } 8603 final int strLen = str.length(); 8604 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8605 int outOffset = 0; 8606 for (int i = 0; i < strLen;) { 8607 final int oldCodepoint = str.codePointAt(i); 8608 final int newCodePoint; 8609 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8610 newCodePoint = Character.toLowerCase(oldCodepoint); 8611 } else if (Character.isLowerCase(oldCodepoint)) { 8612 newCodePoint = Character.toUpperCase(oldCodepoint); 8613 } else { 8614 newCodePoint = oldCodepoint; 8615 } 8616 newCodePoints[outOffset++] = newCodePoint; 8617 i += Character.charCount(newCodePoint); 8618 } 8619 return new String(newCodePoints, 0, outOffset); 8620 } 8621 8622 /** 8623 * Converts a {@link CharSequence} into an array of code points. 8624 * 8625 * <p> 8626 * Valid pairs of surrogate code units will be converted into a single supplementary code point. Isolated surrogate code units (i.e. a high surrogate not 8627 * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is. 8628 * </p> 8629 * 8630 * <pre> 8631 * StringUtils.toCodePoints(null) = null 8632 * StringUtils.toCodePoints("") = [] // empty array 8633 * </pre> 8634 * 8635 * @param cs the character sequence to convert. 8636 * @return an array of code points. 8637 * @since 3.6 8638 */ 8639 public static int[] toCodePoints(final CharSequence cs) { 8640 if (cs == null) { 8641 return null; 8642 } 8643 if (cs.length() == 0) { 8644 return ArrayUtils.EMPTY_INT_ARRAY; 8645 } 8646 return cs.toString().codePoints().toArray(); 8647 } 8648 8649 /** 8650 * Converts a {@code byte[]} to a String using the specified character encoding. 8651 * 8652 * @param bytes the byte array to read from. 8653 * @param charset the encoding to use, if null then use the platform default. 8654 * @return a new String. 8655 * @throws NullPointerException if {@code bytes} is null 8656 * @since 3.2 8657 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8658 */ 8659 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8660 return new String(bytes, Charsets.toCharset(charset)); 8661 } 8662 8663 /** 8664 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8665 * 8666 * @param source A source String or null. 8667 * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8668 * @since 3.10 8669 */ 8670 public static String toRootLowerCase(final String source) { 8671 return source == null ? null : source.toLowerCase(Locale.ROOT); 8672 } 8673 8674 /** 8675 * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8676 * 8677 * @param source A source String or null. 8678 * @return the given source String as an upper-case using the {@link Locale#ROOT} locale or null. 8679 * @since 3.10 8680 */ 8681 public static String toRootUpperCase(final String source) { 8682 return source == null ? null : source.toUpperCase(Locale.ROOT); 8683 } 8684 8685 /** 8686 * Converts a {@code byte[]} to a String using the specified character encoding. 8687 * 8688 * @param bytes the byte array to read from. 8689 * @param charsetName the encoding to use, if null then use the platform default. 8690 * @return a new String. 8691 * @throws NullPointerException if the input is null. 8692 * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code 8693 * @since 3.1 8694 */ 8695 @Deprecated 8696 public static String toString(final byte[] bytes, final String charsetName) { 8697 return new String(bytes, Charsets.toCharset(charsetName)); 8698 } 8699 8700 /** 8701 * Removes control characters (char <= 32) from both ends of this String, handling {@code null} by returning {@code null}. 8702 * 8703 * <p> 8704 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #strip(String)}. 8705 * </p> 8706 * 8707 * <p> 8708 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8709 * </p> 8710 * 8711 * <pre> 8712 * StringUtils.trim(null) = null 8713 * StringUtils.trim("") = "" 8714 * StringUtils.trim(" ") = "" 8715 * StringUtils.trim("abc") = "abc" 8716 * StringUtils.trim(" abc ") = "abc" 8717 * </pre> 8718 * 8719 * @param str the String to be trimmed, may be null. 8720 * @return the trimmed string, {@code null} if null String input. 8721 */ 8722 public static String trim(final String str) { 8723 return str == null ? null : str.trim(); 8724 } 8725 8726 /** 8727 * Removes control characters (char <= 32) from both ends of this String returning an empty String ("") if the String is empty ("") after the trim or if 8728 * it is {@code null}. 8729 * 8730 * <p> 8731 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToEmpty(String)}. 8732 * 8733 * <pre> 8734 * StringUtils.trimToEmpty(null) = "" 8735 * StringUtils.trimToEmpty("") = "" 8736 * StringUtils.trimToEmpty(" ") = "" 8737 * StringUtils.trimToEmpty("abc") = "abc" 8738 * StringUtils.trimToEmpty(" abc ") = "abc" 8739 * </pre> 8740 * 8741 * @param str the String to be trimmed, may be null. 8742 * @return the trimmed String, or an empty String if {@code null} input. 8743 * @since 2.0 8744 */ 8745 public static String trimToEmpty(final String str) { 8746 return str == null ? EMPTY : str.trim(); 8747 } 8748 8749 /** 8750 * Removes control characters (char <= 32) from both ends of this String returning {@code null} if the String is empty ("") after the trim or if it is 8751 * {@code null}. 8752 * 8753 * <p> 8754 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToNull(String)}. 8755 * 8756 * <pre> 8757 * StringUtils.trimToNull(null) = null 8758 * StringUtils.trimToNull("") = null 8759 * StringUtils.trimToNull(" ") = null 8760 * StringUtils.trimToNull("abc") = "abc" 8761 * StringUtils.trimToNull(" abc ") = "abc" 8762 * </pre> 8763 * 8764 * @param str the String to be trimmed, may be null. 8765 * @return the trimmed String, {@code null} if only chars <= 32, empty or null String input. 8766 * @since 2.0 8767 */ 8768 public static String trimToNull(final String str) { 8769 final String ts = trim(str); 8770 return isEmpty(ts) ? null : ts; 8771 } 8772 8773 /** 8774 * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for". 8775 * 8776 * <p> 8777 * Specifically: 8778 * </p> 8779 * <ul> 8780 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 8781 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 8782 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8783 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 8784 * </ul> 8785 * 8786 * <pre> 8787 * StringUtils.truncate(null, 0) = null 8788 * StringUtils.truncate(null, 2) = null 8789 * StringUtils.truncate("", 4) = "" 8790 * StringUtils.truncate("abcdefg", 4) = "abcd" 8791 * StringUtils.truncate("abcdefg", 6) = "abcdef" 8792 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 8793 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 8794 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 8795 * </pre> 8796 * 8797 * @param str the String to truncate, may be null. 8798 * @param maxWidth maximum length of result String, must be positive. 8799 * @return truncated String, {@code null} if null String input. 8800 * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}. 8801 * @since 3.5 8802 */ 8803 public static String truncate(final String str, final int maxWidth) { 8804 return truncate(str, 0, maxWidth); 8805 } 8806 8807 /** 8808 * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all". 8809 * 8810 * <p> 8811 * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset. 8812 * 8813 * <p> 8814 * Specifically: 8815 * </p> 8816 * <ul> 8817 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 8818 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 8819 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8820 * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8821 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 8822 * </ul> 8823 * 8824 * <pre> 8825 * StringUtils.truncate(null, 0, 0) = null 8826 * StringUtils.truncate(null, 2, 4) = null 8827 * StringUtils.truncate("", 0, 10) = "" 8828 * StringUtils.truncate("", 2, 10) = "" 8829 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 8830 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 8831 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 8832 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 8833 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 8834 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 8835 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 8836 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 8837 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 8838 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 8839 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 8840 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 8841 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 8842 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 8843 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 8844 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 8845 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 8846 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 8847 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 8848 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 8849 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 8850 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 8851 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 8852 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 8853 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 8854 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 8855 * </pre> 8856 * 8857 * @param str the String to truncate, may be null. 8858 * @param offset left edge of source String. 8859 * @param maxWidth maximum length of result String, must be positive. 8860 * @return truncated String, {@code null} if null String input. 8861 * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}. 8862 * @since 3.5 8863 */ 8864 public static String truncate(final String str, final int offset, final int maxWidth) { 8865 if (offset < 0) { 8866 throw new IllegalArgumentException("offset cannot be negative"); 8867 } 8868 if (maxWidth < 0) { 8869 throw new IllegalArgumentException("maxWith cannot be negative"); 8870 } 8871 if (str == null) { 8872 return null; 8873 } 8874 if (offset > str.length()) { 8875 return EMPTY; 8876 } 8877 if (str.length() > maxWidth) { 8878 final int ix = Math.min(offset + maxWidth, str.length()); 8879 return str.substring(offset, ix); 8880 } 8881 return str.substring(offset); 8882 } 8883 8884 /** 8885 * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed. 8886 * 8887 * <p> 8888 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}. 8889 * </p> 8890 * 8891 * <pre> 8892 * StringUtils.uncapitalize(null) = null 8893 * StringUtils.uncapitalize("") = "" 8894 * StringUtils.uncapitalize("cat") = "cat" 8895 * StringUtils.uncapitalize("Cat") = "cat" 8896 * StringUtils.uncapitalize("CAT") = "cAT" 8897 * </pre> 8898 * 8899 * @param str the String to uncapitalize, may be null. 8900 * @return the uncapitalized String, {@code null} if null String input. 8901 * @see org.apache.commons.text.WordUtils#uncapitalize(String) 8902 * @see #capitalize(String) 8903 * @since 2.0 8904 */ 8905 public static String uncapitalize(final String str) { 8906 final int strLen = length(str); 8907 if (strLen == 0) { 8908 return str; 8909 } 8910 final int firstCodePoint = str.codePointAt(0); 8911 final int newCodePoint = Character.toLowerCase(firstCodePoint); 8912 if (firstCodePoint == newCodePoint) { 8913 // already uncapitalized 8914 return str; 8915 } 8916 final int[] newCodePoints = str.codePoints().toArray(); 8917 newCodePoints[0] = newCodePoint; // copy the first code point 8918 return new String(newCodePoints, 0, newCodePoints.length); 8919 } 8920 8921 /** 8922 * Unwraps a given string from a character. 8923 * 8924 * <pre> 8925 * StringUtils.unwrap(null, null) = null 8926 * StringUtils.unwrap(null, '\0') = null 8927 * StringUtils.unwrap(null, '1') = null 8928 * StringUtils.unwrap("a", 'a') = "a" 8929 * StringUtils.unwrap("aa", 'a') = "" 8930 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 8931 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 8932 * StringUtils.unwrap("A", '#') = "A" 8933 * StringUtils.unwrap("#A", '#') = "#A" 8934 * StringUtils.unwrap("A#", '#') = "A#" 8935 * </pre> 8936 * 8937 * @param str the String to be unwrapped, can be null. 8938 * @param wrapChar the character used to unwrap. 8939 * @return unwrapped String or the original string if it is not quoted properly with the wrapChar. 8940 * @since 3.6 8941 */ 8942 public static String unwrap(final String str, final char wrapChar) { 8943 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 8944 return str; 8945 } 8946 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 8947 final int startIndex = 0; 8948 final int endIndex = str.length() - 1; 8949 return str.substring(startIndex + 1, endIndex); 8950 } 8951 return str; 8952 } 8953 8954 /** 8955 * Unwraps a given string from another string. 8956 * 8957 * <pre> 8958 * StringUtils.unwrap(null, null) = null 8959 * StringUtils.unwrap(null, "") = null 8960 * StringUtils.unwrap(null, "1") = null 8961 * StringUtils.unwrap("a", "a") = "a" 8962 * StringUtils.unwrap("aa", "a") = "" 8963 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 8964 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 8965 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 8966 * StringUtils.unwrap("A", "#") = "A" 8967 * StringUtils.unwrap("#A", "#") = "#A" 8968 * StringUtils.unwrap("A#", "#") = "A#" 8969 * </pre> 8970 * 8971 * @param str the String to be unwrapped, can be null. 8972 * @param wrapToken the String used to unwrap. 8973 * @return unwrapped String or the original string if it is not quoted properly with the wrapToken. 8974 * @since 3.6 8975 */ 8976 public static String unwrap(final String str, final String wrapToken) { 8977 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) { 8978 return str; 8979 } 8980 if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) { 8981 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken)); 8982 } 8983 return str; 8984 } 8985 8986 /** 8987 * Converts a String to upper case as per {@link String#toUpperCase()}. 8988 * 8989 * <p> 8990 * A {@code null} input String returns {@code null}. 8991 * </p> 8992 * 8993 * <pre> 8994 * StringUtils.upperCase(null) = null 8995 * StringUtils.upperCase("") = "" 8996 * StringUtils.upperCase("aBc") = "ABC" 8997 * </pre> 8998 * 8999 * <p> 9000 * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale. 9001 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g. 9002 * {@link Locale#ENGLISH}). 9003 * </p> 9004 * 9005 * @param str the String to upper case, may be null. 9006 * @return the upper-cased String, {@code null} if null String input. 9007 */ 9008 public static String upperCase(final String str) { 9009 if (str == null) { 9010 return null; 9011 } 9012 return str.toUpperCase(); 9013 } 9014 9015 /** 9016 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}. 9017 * 9018 * <p> 9019 * A {@code null} input String returns {@code null}. 9020 * </p> 9021 * 9022 * <pre> 9023 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9024 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9025 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9026 * </pre> 9027 * 9028 * @param str the String to upper case, may be null. 9029 * @param locale the locale that defines the case transformation rules, must not be null. 9030 * @return the upper-cased String, {@code null} if null String input. 9031 * @since 2.5 9032 */ 9033 public static String upperCase(final String str, final Locale locale) { 9034 if (str == null) { 9035 return null; 9036 } 9037 return str.toUpperCase(LocaleUtils.toLocale(locale)); 9038 } 9039 9040 /** 9041 * Returns the string representation of the {@code char} array or null. 9042 * 9043 * @param value the character array. 9044 * @return a String or null. 9045 * @see String#valueOf(char[]) 9046 * @since 3.9 9047 */ 9048 public static String valueOf(final char[] value) { 9049 return value == null ? null : String.valueOf(value); 9050 } 9051 9052 /** 9053 * Wraps a string with a char. 9054 * 9055 * <pre> 9056 * StringUtils.wrap(null, *) = null 9057 * StringUtils.wrap("", *) = "" 9058 * StringUtils.wrap("ab", '\0') = "ab" 9059 * StringUtils.wrap("ab", 'x') = "xabx" 9060 * StringUtils.wrap("ab", '\'') = "'ab'" 9061 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9062 * </pre> 9063 * 9064 * @param str the string to be wrapped, may be {@code null}. 9065 * @param wrapWith the char that will wrap {@code str}. 9066 * @return the wrapped string, or {@code null} if {@code str == null}. 9067 * @since 3.4 9068 */ 9069 public static String wrap(final String str, final char wrapWith) { 9070 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9071 return str; 9072 } 9073 return wrapWith + str + wrapWith; 9074 } 9075 9076 /** 9077 * Wraps a String with another String. 9078 * 9079 * <p> 9080 * A {@code null} input String returns {@code null}. 9081 * </p> 9082 * 9083 * <pre> 9084 * StringUtils.wrap(null, *) = null 9085 * StringUtils.wrap("", *) = "" 9086 * StringUtils.wrap("ab", null) = "ab" 9087 * StringUtils.wrap("ab", "x") = "xabx" 9088 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9089 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9090 * StringUtils.wrap("ab", "'") = "'ab'" 9091 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9092 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9093 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9094 * </pre> 9095 * 9096 * @param str the String to be wrapper, may be null. 9097 * @param wrapWith the String that will wrap str. 9098 * @return wrapped String, {@code null} if null String input. 9099 * @since 3.4 9100 */ 9101 public static String wrap(final String str, final String wrapWith) { 9102 if (isEmpty(str) || isEmpty(wrapWith)) { 9103 return str; 9104 } 9105 return wrapWith.concat(str).concat(wrapWith); 9106 } 9107 9108 /** 9109 * Wraps a string with a char if that char is missing from the start or end of the given string. 9110 * 9111 * <p> 9112 * A new {@link String} will not be created if {@code str} is already wrapped. 9113 * </p> 9114 * 9115 * <pre> 9116 * StringUtils.wrapIfMissing(null, *) = null 9117 * StringUtils.wrapIfMissing("", *) = "" 9118 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9119 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9120 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9121 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9122 * StringUtils.wrapIfMissing("/", '/') = "/" 9123 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9124 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9125 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9126 * </pre> 9127 * 9128 * @param str the string to be wrapped, may be {@code null}. 9129 * @param wrapWith the char that will wrap {@code str}. 9130 * @return the wrapped string, or {@code null} if {@code str == null}. 9131 * @since 3.5 9132 */ 9133 public static String wrapIfMissing(final String str, final char wrapWith) { 9134 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9135 return str; 9136 } 9137 final boolean wrapStart = str.charAt(0) != wrapWith; 9138 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9139 if (!wrapStart && !wrapEnd) { 9140 return str; 9141 } 9142 final StringBuilder builder = new StringBuilder(str.length() + 2); 9143 if (wrapStart) { 9144 builder.append(wrapWith); 9145 } 9146 builder.append(str); 9147 if (wrapEnd) { 9148 builder.append(wrapWith); 9149 } 9150 return builder.toString(); 9151 } 9152 9153 /** 9154 * Wraps a string with a string if that string is missing from the start or end of the given string. 9155 * 9156 * <p> 9157 * A new {@link String} will not be created if {@code str} is already wrapped. 9158 * </p> 9159 * 9160 * <pre> 9161 * StringUtils.wrapIfMissing(null, *) = null 9162 * StringUtils.wrapIfMissing("", *) = "" 9163 * StringUtils.wrapIfMissing("ab", null) = "ab" 9164 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9165 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9166 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9167 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9168 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9169 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9170 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9171 * StringUtils.wrapIfMissing("/", "/") = "/" 9172 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9173 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9174 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9175 * </pre> 9176 * 9177 * @param str the string to be wrapped, may be {@code null}. 9178 * @param wrapWith the string that will wrap {@code str}. 9179 * @return the wrapped string, or {@code null} if {@code str == null}. 9180 * @since 3.5 9181 */ 9182 public static String wrapIfMissing(final String str, final String wrapWith) { 9183 if (isEmpty(str) || isEmpty(wrapWith)) { 9184 return str; 9185 } 9186 final boolean wrapStart = !str.startsWith(wrapWith); 9187 final boolean wrapEnd = !str.endsWith(wrapWith); 9188 if (!wrapStart && !wrapEnd) { 9189 return str; 9190 } 9191 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9192 if (wrapStart) { 9193 builder.append(wrapWith); 9194 } 9195 builder.append(str); 9196 if (wrapEnd) { 9197 builder.append(wrapWith); 9198 } 9199 return builder.toString(); 9200 } 9201 9202 /** 9203 * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}. 9204 * 9205 * <p> 9206 * This constructor is public to permit tools that require a JavaBean instance to operate. 9207 * </p> 9208 * 9209 * @deprecated TODO Make private in 4.0. 9210 */ 9211 @Deprecated 9212 public StringUtils() { 9213 // empty 9214 } 9215 9216 }