001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.io.UnsupportedEncodingException; 020import java.nio.CharBuffer; 021import java.nio.charset.Charset; 022import java.text.Normalizer; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Iterator; 026import java.util.List; 027import java.util.Locale; 028import java.util.Objects; 029import java.util.Set; 030import java.util.function.Supplier; 031import java.util.regex.Pattern; 032import java.util.stream.Collectors; 033 034import org.apache.commons.lang3.function.Suppliers; 035import org.apache.commons.lang3.stream.LangCollectors; 036import org.apache.commons.lang3.stream.Streams; 037 038/** 039 * Operations on {@link String} that are 040 * {@code null} safe. 041 * 042 * <ul> 043 * <li><strong>IsEmpty/IsBlank</strong> 044 * - checks if a String contains text</li> 045 * <li><strong>Trim/Strip</strong> 046 * - removes leading and trailing whitespace</li> 047 * <li><strong>Equals/Compare</strong> 048 * - compares two strings in a null-safe manner</li> 049 * <li><strong>startsWith</strong> 050 * - check if a String starts with a prefix in a null-safe manner</li> 051 * <li><strong>endsWith</strong> 052 * - check if a String ends with a suffix in a null-safe manner</li> 053 * <li><strong>IndexOf/LastIndexOf/Contains</strong> 054 * - null-safe index-of checks</li> 055 * <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong> 056 * - index-of any of a set of Strings</li> 057 * <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong> 058 * - checks if String contains only/none/any of these characters</li> 059 * <li><strong>Substring/Left/Right/Mid</strong> 060 * - null-safe substring extractions</li> 061 * <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong> 062 * - substring extraction relative to other strings</li> 063 * <li><strong>Split/Join</strong> 064 * - splits a String into an array of substrings and vice versa</li> 065 * <li><strong>Remove/Delete</strong> 066 * - removes part of a String</li> 067 * <li><strong>Replace/Overlay</strong> 068 * - Searches a String and replaces one String with another</li> 069 * <li><strong>Chomp/Chop</strong> 070 * - removes the last part of a String</li> 071 * <li><strong>AppendIfMissing</strong> 072 * - appends a suffix to the end of the String if not present</li> 073 * <li><strong>PrependIfMissing</strong> 074 * - prepends a prefix to the start of the String if not present</li> 075 * <li><strong>Wrap</strong> 076 * - wraps a String with a character or another String</li> 077 * <li><strong>WrapIfMissing</strong> 078 * - wraps a String only where the wrapping character or String is missing</li> 079 * <li><strong>Unwrap</strong> 080 * - removes matching wrapping characters or Strings from both ends of a String</li> 081 * <li><strong>LeftPad/RightPad/Center/Repeat</strong> 082 * - pads a String</li> 083 * <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong> 084 * - changes the case of a String</li> 085 * <li><strong>CountMatches</strong> 086 * - counts the number of occurrences of one String in another</li> 087 * <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong> 088 * - checks the characters in a String</li> 089 * <li><strong>DefaultString</strong> 090 * - protects against a null input String</li> 091 * <li><strong>Rotate</strong> 092 * - rotate (circular shift) a String</li> 093 * <li><strong>Reverse/ReverseDelimited</strong> 094 * - reverses a String</li> 095 * <li><strong>Abbreviate</strong> 096 * - abbreviates a string using ellipses or another given String</li> 097 * <li><strong>Difference</strong> 098 * - compares Strings and reports on their differences</li> 099 * <li><strong>LevenshteinDistance</strong> 100 * - the number of changes needed to change one String into another</li> 101 * </ul> 102 * 103 * <p> 104 * The {@link StringUtils} class defines certain words related to 105 * String handling. 106 * </p> 107 * 108 * <ul> 109 * <li>null - {@code null}</li> 110 * <li>empty - a zero-length string ({@code ""})</li> 111 * <li>space - the space character ({@code ' '}, char 32)</li> 112 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 113 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 114 * </ul> 115 * 116 * <p> 117 * {@link StringUtils} handles {@code null} input Strings quietly. 118 * That is to say that a {@code null} input will return {@code null}. 119 * Where a {@code boolean} or {@code int} is being returned 120 * details vary by method. 121 * </p> 122 * 123 * <p> 124 * A side effect of the {@code null} handling is that a 125 * {@link NullPointerException} should be considered a bug in 126 * {@link StringUtils}. 127 * </p> 128 * 129 * <p> 130 * Methods in this class include sample code in their Javadoc comments to explain their operation. 131 * The symbol {@code *} is used to indicate any input including {@code null}. 132 * </p> 133 * 134 * <p> 135 * #ThreadSafe# 136 * </p> 137 * 138 * @see String 139 * @since 1.0 140 */ 141//@Immutable 142public class StringUtils { 143 144 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 145 // Whitespace: 146 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 147 // where WHITESPACE is a string of all whitespace characters 148 // 149 // Character access: 150 // String.charAt(n) versus toCharArray(), then array[n] 151 // String.charAt(n) is about 15% worse for a 10K string 152 // They are about equal for a length 50 string 153 // String.charAt(n) is about 4 times better for a length 3 string 154 // String.charAt(n) is best bet overall 155 // 156 // Append: 157 // String.concat about twice as fast as StringBuffer.append 158 // (not sure who tested this) 159 160 /** 161 * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 '…', this isn't it. 162 */ 163 private static final String ELLIPSIS3 = "..."; 164 165 /** 166 * A String for a space character. 167 * 168 * @since 3.2 169 */ 170 public static final String SPACE = " "; 171 172 /** 173 * The empty String {@code ""}. 174 * 175 * @since 2.0 176 */ 177 public static final String EMPTY = ""; 178 179 /** 180 * The null String {@code null}. Package-private only. 181 */ 182 static final String NULL = null; 183 184 /** 185 * A String for linefeed LF ("\n"). 186 * 187 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 188 * for Character and String Literals</a> 189 * @since 3.2 190 */ 191 public static final String LF = "\n"; 192 193 /** 194 * A String for carriage return CR ("\r"). 195 * 196 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 197 * for Character and String Literals</a> 198 * @since 3.2 199 */ 200 public static final String CR = "\r"; 201 202 /** 203 * Represents a failed index search. 204 * 205 * @since 2.1 206 */ 207 public static final int INDEX_NOT_FOUND = -1; 208 209 /** 210 * The maximum size to which the padding constant(s) can expand. 211 */ 212 private static final int PAD_LIMIT = 8192; 213 214 /** 215 * The default maximum depth at which recursive replacement will continue until no further search replacements are possible. 216 */ 217 private static final int DEFAULT_TTL = 5; 218 219 /** 220 * Pattern used in {@link #stripAccents(String)}. 221 */ 222 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 223 224 /** 225 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "Now is the time for..." 226 * 227 * <p> 228 * Specifically: 229 * </p> 230 * <ul> 231 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 232 * <li>Else abbreviate it to {@code (substring(str, 0, max - 3) + "...")}.</li> 233 * <li>If {@code maxWidth} is less than {@code 4}, throw an {@link IllegalArgumentException}.</li> 234 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 235 * </ul> 236 * 237 * <pre> 238 * StringUtils.abbreviate(null, *) = null 239 * StringUtils.abbreviate("", 4) = "" 240 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 241 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 242 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 243 * StringUtils.abbreviate("abcdefg", 4) = "a..." 244 * StringUtils.abbreviate("abcdefg", 3) = Throws {@link IllegalArgumentException}. 245 * </pre> 246 * 247 * @param str The String to check, may be null. 248 * @param maxWidth maximum length of result String, must be at least 4. 249 * @return abbreviated String, {@code null} if null String input. 250 * @throws IllegalArgumentException Thrown if the width is too small. 251 * @since 2.0 252 */ 253 public static String abbreviate(final String str, final int maxWidth) { 254 return abbreviate(str, ELLIPSIS3, 0, maxWidth); 255 } 256 257 /** 258 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "...is the time for...". 259 * 260 * <p> 261 * 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 262 * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result. 263 * </p> 264 * <p> 265 * In no case will it return a String of length greater than {@code maxWidth}. 266 * </p> 267 * 268 * <pre> 269 * StringUtils.abbreviate(null, *, *) = null 270 * StringUtils.abbreviate("", 0, 4) = "" 271 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 272 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 273 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 274 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 275 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 276 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 277 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 278 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 279 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 280 * StringUtils.abbreviate("abcdefghij", 0, 3) = Throws {@link IllegalArgumentException}. 281 * StringUtils.abbreviate("abcdefghij", 5, 6) = Throws {@link IllegalArgumentException}. 282 * </pre> 283 * 284 * @param str The String to check, may be null. 285 * @param offset left edge of source String. 286 * @param maxWidth maximum length of result String, must be at least 4. 287 * @return abbreviated String, {@code null} if null String input. 288 * @throws IllegalArgumentException Thrown if the width is too small. 289 * @since 2.0 290 */ 291 public static String abbreviate(final String str, final int offset, final int maxWidth) { 292 return abbreviate(str, ELLIPSIS3, offset, maxWidth); 293 } 294 295 /** 296 * Abbreviates a String using another given String as replacement marker. This will convert "Now is the time for all good men" into "Now is the time for..." 297 * when "..." is the replacement marker. 298 * 299 * <p> 300 * Specifically: 301 * </p> 302 * <ul> 303 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 304 * <li>Else abbreviate it to {@code (substring(str, 0, max - abbrevMarker.length) + abbrevMarker)}.</li> 305 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li> 306 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 307 * </ul> 308 * 309 * <pre> 310 * StringUtils.abbreviate(null, "...", *) = null 311 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 312 * StringUtils.abbreviate("", "...", 4) = "" 313 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 314 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 315 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 316 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 317 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 318 * StringUtils.abbreviate("abcdefg", "..", 2) = Throws {@link IllegalArgumentException}. 319 * StringUtils.abbreviate("abcdefg", "...", 3) = Throws {@link IllegalArgumentException}. 320 * </pre> 321 * 322 * @param str The String to check, may be null. 323 * @param abbrevMarker The String used as replacement marker. 324 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}. 325 * @return abbreviated String, {@code null} if null String input. 326 * @throws IllegalArgumentException Thrown if the width is too small. 327 * @since 3.6 328 */ 329 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 330 return abbreviate(str, abbrevMarker, 0, maxWidth); 331 } 332 333 /** 334 * Abbreviates a String using a given replacement marker. This will convert "Now is the time for all good men" into "...is the time for..." when "..." is 335 * the replacement marker. 336 * <p> 337 * 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 338 * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result. 339 * </p> 340 * <p> 341 * In no case will it return a String of length greater than {@code maxWidth}. 342 * </p> 343 * 344 * <pre> 345 * StringUtils.abbreviate(null, null, *, *) = null 346 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 347 * StringUtils.abbreviate("", "...", 0, 4) = "" 348 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 349 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 350 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 351 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 352 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 353 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 354 * StringUtils.abbreviate("abcdefghijklmno", "…", 6, 10) = "…ghijklmno" 355 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 356 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 357 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 358 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = Throws {@link IllegalArgumentException}. 359 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = Throws {@link IllegalArgumentException}. 360 * </pre> 361 * 362 * @param str The String to check, may be null. 363 * @param abbrevMarker The String used as replacement marker, for example "...", or Unicode HORIZONTAL ELLIPSIS, U+2026 '…'. 364 * @param offset left edge of source String. 365 * @param maxWidth maximum length of result String, must be at least 4. 366 * @return abbreviated String, {@code null} if null String input. 367 * @throws IllegalArgumentException Thrown if the width is too small. 368 * @since 3.6 369 */ 370 public static String abbreviate(final String str, String abbrevMarker, final int offset, final int maxWidth) { 371 if (isEmpty(str)) { 372 return str; 373 } 374 if (abbrevMarker == null) { 375 abbrevMarker = EMPTY; 376 } 377 final int abbrevMarkerLength = abbrevMarker.length(); 378 final int minAbbrevWidth = abbrevMarkerLength + 1; 379 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 380 381 if (maxWidth < minAbbrevWidth) { 382 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 383 } 384 final int strLen = str.length(); 385 if (strLen <= maxWidth) { 386 return str; 387 } 388 if (strLen - offset <= maxWidth - abbrevMarkerLength) { 389 int tailStart = strLen - (maxWidth - abbrevMarkerLength); 390 if (splitsSurrogatePair(str, tailStart)) { 391 tailStart++; 392 } 393 return abbrevMarker + str.substring(tailStart); 394 } 395 if (offset <= abbrevMarkerLength + 1) { 396 int headEnd = maxWidth - abbrevMarkerLength; 397 if (splitsSurrogatePair(str, headEnd)) { 398 headEnd--; 399 } 400 return str.substring(0, headEnd) + abbrevMarker; 401 } 402 if (maxWidth < minAbbrevWidthOffset) { 403 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 404 } 405 int from = offset; 406 if (splitsSurrogatePair(str, from)) { 407 from++; 408 } 409 return abbrevMarker + abbreviate(str.substring(from), abbrevMarker, maxWidth - abbrevMarkerLength); 410 } 411 412 /** 413 * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String. 414 * 415 * <p> 416 * This abbreviation only occurs if the following criteria is met: 417 * </p> 418 * <ul> 419 * <li>Neither the String for abbreviation nor the replacement String are null or empty</li> 420 * <li>The length to truncate to is less than the length of the supplied String</li> 421 * <li>The length to truncate to is greater than 0</li> 422 * <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 423 * abbreviation</li> 424 * </ul> 425 * <p> 426 * Otherwise, the returned String will be the same as the supplied String for abbreviation. 427 * </p> 428 * 429 * <pre> 430 * StringUtils.abbreviateMiddle(null, null, 0) = null 431 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 432 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 433 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 434 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 435 * </pre> 436 * 437 * @param str The String to abbreviate, may be null. 438 * @param middle The String to replace the middle characters with, may be null. 439 * @param length The length to abbreviate {@code str} to. 440 * @return The abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 441 * @since 2.5 442 */ 443 public static String abbreviateMiddle(final String str, final String middle, final int length) { 444 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) { 445 return str; 446 } 447 final int targetString = length - middle.length(); 448 int startOffset = targetString / 2 + targetString % 2; 449 int endOffset = str.length() - targetString / 2; 450 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 451 if (splitsSurrogatePair(str, startOffset)) { 452 startOffset--; 453 } 454 if (splitsSurrogatePair(str, endOffset)) { 455 endOffset++; 456 } 457 return str.substring(0, startOffset) + middle + str.substring(endOffset); 458 } 459 460 /** 461 * Appends the suffix to the end of the string if the string does not already end with any of the suffixes. 462 * 463 * <pre> 464 * StringUtils.appendIfMissing(null, null) = null 465 * StringUtils.appendIfMissing("abc", null) = "abc" 466 * StringUtils.appendIfMissing("", "xyz") = "xyz" 467 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 468 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 469 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 470 * </pre> 471 * <p> 472 * With additional suffixes, 473 * </p> 474 * 475 * <pre> 476 * StringUtils.appendIfMissing(null, null, null) = null 477 * StringUtils.appendIfMissing("abc", null, null) = "abc" 478 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 479 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 480 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 481 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 482 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 483 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 484 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 485 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 486 * </pre> 487 * 488 * @param str The string. 489 * @param suffix The suffix to append to the end of the string. 490 * @param suffixes Additional suffixes that are valid terminators. 491 * @return A new String if suffix was appended, the same string otherwise. 492 * @since 3.2 493 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}. 494 */ 495 @Deprecated 496 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 497 return Strings.CS.appendIfMissing(str, suffix, suffixes); 498 } 499 500 /** 501 * Appends the suffix to the end of the string if the string does not 502 * already end, case-insensitive, with any of the suffixes. 503 * 504 * <pre> 505 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 506 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 507 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 508 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 509 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 510 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 511 * </pre> 512 * <p> 513 * With additional suffixes, 514 * </p> 515 * <pre> 516 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 517 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 518 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 519 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 520 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 521 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 522 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 523 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 524 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 525 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 526 * </pre> 527 * 528 * @param str The string. 529 * @param suffix The suffix to append to the end of the string. 530 * @param suffixes Additional suffixes that are valid terminators. 531 * @return A new String if suffix was appended, the same string otherwise. 532 * @since 3.2 533 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}. 534 */ 535 @Deprecated 536 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 537 return Strings.CI.appendIfMissing(str, suffix, suffixes); 538 } 539 540 /** 541 * Computes the capacity required for a StringBuilder to hold {@code items} of {@code maxElementChars} characters plus the separators between them. The 542 * separator is assumed to be 1 character. 543 * 544 * @param count The number of items. 545 * @param maxElementChars The maximum number of characters per item. 546 * @return A StringBuilder with the appropriate capacity. 547 */ 548 private static StringBuilder capacity(final int count, final byte maxElementChars) { 549 return new StringBuilder(count * maxElementChars + count - 1); 550 } 551 552 /** 553 * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed. 554 * 555 * <p> 556 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}. 557 * </p> 558 * 559 * <pre> 560 * StringUtils.capitalize(null) = null 561 * StringUtils.capitalize("") = "" 562 * StringUtils.capitalize("cat") = "Cat" 563 * StringUtils.capitalize("cAt") = "CAt" 564 * StringUtils.capitalize("'cat'") = "'cat'" 565 * </pre> 566 * 567 * @param str The String to capitalize, may be null. 568 * @return The capitalized String, {@code null} if null String input. 569 * @see org.apache.commons.text.WordUtils#capitalize(String) 570 * @see #uncapitalize(String) 571 * @since 2.0 572 */ 573 public static String capitalize(final String str) { 574 if (isEmpty(str)) { 575 return str; 576 } 577 final int firstCodepoint = str.codePointAt(0); 578 final int newCodePoint = Character.toTitleCase(firstCodepoint); 579 if (firstCodepoint == newCodePoint) { 580 // already capitalized 581 return str; 582 } 583 final int[] newCodePoints = str.codePoints().toArray(); 584 newCodePoints[0] = newCodePoint; // copy the first code point 585 return new String(newCodePoints, 0, newCodePoints.length); 586 } 587 588 /** 589 * Centers a String in a larger String of size {@code size} using the space character (' '). 590 * 591 * <p> 592 * 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 593 * zero. 594 * </p> 595 * 596 * <p> 597 * Equivalent to {@code center(str, size, " ")}. 598 * </p> 599 * 600 * <pre> 601 * StringUtils.center(null, *) = null 602 * StringUtils.center("", 4) = " " 603 * StringUtils.center("ab", -1) = "ab" 604 * StringUtils.center("ab", 4) = " ab " 605 * StringUtils.center("abcd", 2) = "abcd" 606 * StringUtils.center("a", 4) = " a " 607 * </pre> 608 * 609 * @param str The String to center, may be null. 610 * @param size The int size of new String, negative treated as zero. 611 * @return centered String, {@code null} if null String input. 612 */ 613 public static String center(final String str, final int size) { 614 return center(str, size, ' '); 615 } 616 617 /** 618 * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with. 619 * 620 * <p> 621 * 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. 622 * </p> 623 * 624 * <pre> 625 * StringUtils.center(null, *, *) = null 626 * StringUtils.center("", 4, ' ') = " " 627 * StringUtils.center("ab", -1, ' ') = "ab" 628 * StringUtils.center("ab", 4, ' ') = " ab " 629 * StringUtils.center("abcd", 2, ' ') = "abcd" 630 * StringUtils.center("a", 4, ' ') = " a " 631 * StringUtils.center("a", 4, 'y') = "yayy" 632 * </pre> 633 * 634 * @param str The String to center, may be null. 635 * @param size The int size of new String, negative treated as zero. 636 * @param padChar The character to pad the new String with. 637 * @return centered String, {@code null} if null String input. 638 * @since 2.0 639 */ 640 public static String center(String str, final int size, final char padChar) { 641 if (str == null || size <= 0) { 642 return str; 643 } 644 final int strLen = str.length(); 645 final int pads = size - strLen; 646 if (pads <= 0) { 647 return str; 648 } 649 str = leftPad(str, strLen + pads / 2, padChar); 650 return rightPad(str, size, padChar); 651 } 652 653 /** 654 * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with. 655 * 656 * <p> 657 * 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. 658 * If the requested padding length on either side would split a Unicode surrogate pair in {@code padStr}, the padding is shortened by one {@code char} 659 * (via delegation to {@link #leftPad(String, int, String)} and {@link #rightPad(String, int, String)}) to avoid introducing an unpaired 660 * surrogate by splitting the pair. In that case, the returned String may be shorter than {@code size}, but by no more than one {@code char}. 661 * </p> 662 * 663 * <pre> 664 * StringUtils.center(null, *, *) = null 665 * StringUtils.center("", 4, " ") = " " 666 * StringUtils.center("ab", -1, " ") = "ab" 667 * StringUtils.center("ab", 4, " ") = " ab " 668 * StringUtils.center("abcd", 2, " ") = "abcd" 669 * StringUtils.center("a", 4, " ") = " a " 670 * StringUtils.center("a", 4, "yz") = "yayz" 671 * StringUtils.center("abc", 7, null) = " abc " 672 * StringUtils.center("abc", 7, "") = " abc " 673 * StringUtils.center("a", 2, "\uD83D\uDE00") = "a" 674 * StringUtils.center("a", 3, "\uD83D\uDE00") = "a\uD83D\uDE00" 675 * </pre> 676 * 677 * @param str The String to center, may be null. 678 * @param size The int size of new String, negative treated as zero. 679 * @param padStr The String to pad the new String with, must not be null or empty. 680 * @return centered String, {@code null} if null String input. 681 * @throws IllegalArgumentException Thrown if padStr is {@code null} or empty. 682 */ 683 public static String center(String str, final int size, String padStr) { 684 if (str == null || size <= 0) { 685 return str; 686 } 687 if (isEmpty(padStr)) { 688 padStr = SPACE; 689 } 690 final int strLen = str.length(); 691 final int pads = size - strLen; 692 if (pads <= 0) { 693 return str; 694 } 695 str = leftPad(str, strLen + pads / 2, padStr); 696 return rightPad(str, size, padStr); 697 } 698 699 private static void checkFromToIndex(final int startIndex, final int endIndex, final int length) { 700 if (startIndex < 0) { 701 throw new ArrayIndexOutOfBoundsException(startIndex); 702 } 703 if (endIndex > length) { 704 throw new ArrayIndexOutOfBoundsException(endIndex); 705 } 706 } 707 708 /** 709 * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is "{@code \n}", "{@code \r}", or 710 * "{@code \r\n}". 711 * 712 * <p> 713 * NOTE: This method changed in 2.0. It now more closely matches Perl chomp. 714 * </p> 715 * 716 * <pre> 717 * StringUtils.chomp(null) = null 718 * StringUtils.chomp("") = "" 719 * StringUtils.chomp("abc \r") = "abc " 720 * StringUtils.chomp("abc\n") = "abc" 721 * StringUtils.chomp("abc\r\n") = "abc" 722 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 723 * StringUtils.chomp("abc\n\r") = "abc\n" 724 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 725 * StringUtils.chomp("\r") = "" 726 * StringUtils.chomp("\n") = "" 727 * StringUtils.chomp("\r\n") = "" 728 * </pre> 729 * 730 * @param str The String to chomp a newline from, may be null. 731 * @return String without newline, {@code null} if null String input. 732 */ 733 public static String chomp(final String str) { 734 if (isEmpty(str)) { 735 return str; 736 } 737 if (str.length() == 1) { 738 final char ch = str.charAt(0); 739 if (ch == CharUtils.CR || ch == CharUtils.LF) { 740 return EMPTY; 741 } 742 return str; 743 } 744 int lastIdx = str.length() - 1; 745 final char last = str.charAt(lastIdx); 746 if (last == CharUtils.LF) { 747 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 748 lastIdx--; 749 } 750 } else if (last != CharUtils.CR) { 751 lastIdx++; 752 } 753 return str.substring(0, lastIdx); 754 } 755 756 /** 757 * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone. 758 * 759 * <p> 760 * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use 761 * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}. 762 * </p> 763 * 764 * <pre> 765 * StringUtils.chomp(null, *) = null 766 * StringUtils.chomp("", *) = "" 767 * StringUtils.chomp("foobar", "bar") = "foo" 768 * StringUtils.chomp("foobar", "baz") = "foobar" 769 * StringUtils.chomp("foo", "foo") = "" 770 * StringUtils.chomp("foo ", "foo") = "foo " 771 * StringUtils.chomp(" foo", "foo") = " " 772 * StringUtils.chomp("foo", "foooo") = "foo" 773 * StringUtils.chomp("foo", "") = "foo" 774 * StringUtils.chomp("foo", null) = "foo" 775 * </pre> 776 * 777 * @param str The String to chomp from, may be null. 778 * @param separator separator String, may be null. 779 * @return String without trailing separator, {@code null} if null String input. 780 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead. 781 */ 782 @Deprecated 783 public static String chomp(final String str, final String separator) { 784 return Strings.CS.removeEnd(str, separator); 785 } 786 787 /** 788 * Removes the last character from a String. 789 * 790 * <p> 791 * If the String ends in {@code \r\n}, then remove both of them. 792 * </p> 793 * 794 * <pre> 795 * StringUtils.chop(null) = null 796 * StringUtils.chop("") = "" 797 * StringUtils.chop("abc \r") = "abc " 798 * StringUtils.chop("abc\n") = "abc" 799 * StringUtils.chop("abc\r\n") = "abc" 800 * StringUtils.chop("abc") = "ab" 801 * StringUtils.chop("abc\nabc") = "abc\nab" 802 * StringUtils.chop("a") = "" 803 * StringUtils.chop("\r") = "" 804 * StringUtils.chop("\n") = "" 805 * StringUtils.chop("\r\n") = "" 806 * </pre> 807 * 808 * @param str The String to chop last character from, may be null. 809 * @return String without last character, {@code null} if null String input. 810 */ 811 public static String chop(final String str) { 812 if (str == null) { 813 return null; 814 } 815 final int strLen = str.length(); 816 if (strLen < 2) { 817 return EMPTY; 818 } 819 final int lastIdx = strLen - 1; 820 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 821 if (splitsSurrogatePair(str, lastIdx)) { 822 return str.substring(0, lastIdx - 1); 823 } 824 final String ret = str.substring(0, lastIdx); 825 final char last = str.charAt(lastIdx); 826 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 827 return ret.substring(0, lastIdx - 1); 828 } 829 return ret; 830 } 831 832 /** 833 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 834 * <ul> 835 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 836 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 837 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 838 * </ul> 839 * 840 * <p> 841 * This is a {@code null} safe version of: 842 * </p> 843 * 844 * <pre> 845 * str1.compareTo(str2) 846 * </pre> 847 * 848 * <p> 849 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. 850 * </p> 851 * 852 * <pre>{@code 853 * StringUtils.compare(null, null) = 0 854 * StringUtils.compare(null , "a") < 0 855 * StringUtils.compare("a", null) > 0 856 * StringUtils.compare("abc", "abc") = 0 857 * StringUtils.compare("a", "b") < 0 858 * StringUtils.compare("b", "a") > 0 859 * StringUtils.compare("a", "B") > 0 860 * StringUtils.compare("ab", "abc") < 0 861 * }</pre> 862 * 863 * @param str1 The String to compare from. 864 * @param str2 The String to compare to. 865 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2}. 866 * @see #compare(String, String, boolean) 867 * @see String#compareTo(String) 868 * @since 3.5 869 * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}. 870 */ 871 @Deprecated 872 public static int compare(final String str1, final String str2) { 873 return Strings.CS.compare(str1, str2); 874 } 875 876 /** 877 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 878 * <ul> 879 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 880 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 881 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 882 * </ul> 883 * 884 * <p> 885 * This is a {@code null} safe version of : 886 * </p> 887 * 888 * <pre> 889 * str1.compareTo(str2) 890 * </pre> 891 * 892 * <p> 893 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. 894 * </p> 895 * 896 * <pre>{@code 897 * StringUtils.compare(null, null, *) = 0 898 * StringUtils.compare(null , "a", true) < 0 899 * StringUtils.compare(null , "a", false) > 0 900 * StringUtils.compare("a", null, true) > 0 901 * StringUtils.compare("a", null, false) < 0 902 * StringUtils.compare("abc", "abc", *) = 0 903 * StringUtils.compare("a", "b", *) < 0 904 * StringUtils.compare("b", "a", *) > 0 905 * StringUtils.compare("a", "B", *) > 0 906 * StringUtils.compare("ab", "abc", *) < 0 907 * }</pre> 908 * 909 * @param str1 The String to compare from. 910 * @param str2 The String to compare to. 911 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 912 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}. 913 * @see String#compareTo(String) 914 * @since 3.5 915 */ 916 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 917 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 918 return 0; 919 } 920 if (str1 == null) { 921 return nullIsLess ? -1 : 1; 922 } 923 if (str2 == null) { 924 return nullIsLess ? 1 : -1; 925 } 926 return str1.compareTo(str2); 927 } 928 929 /** 930 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 931 * <ul> 932 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 933 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 934 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 935 * </ul> 936 * 937 * <p> 938 * This is a {@code null} safe version of: 939 * </p> 940 * 941 * <pre> 942 * str1.compareToIgnoreCase(str2) 943 * </pre> 944 * 945 * <p> 946 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive. 947 * </p> 948 * 949 * <pre>{@code 950 * StringUtils.compareIgnoreCase(null, null) = 0 951 * StringUtils.compareIgnoreCase(null , "a") < 0 952 * StringUtils.compareIgnoreCase("a", null) > 0 953 * StringUtils.compareIgnoreCase("abc", "abc") = 0 954 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 955 * StringUtils.compareIgnoreCase("a", "b") < 0 956 * StringUtils.compareIgnoreCase("b", "a") > 0 957 * StringUtils.compareIgnoreCase("a", "B") < 0 958 * StringUtils.compareIgnoreCase("A", "b") < 0 959 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 960 * }</pre> 961 * 962 * @param str1 The String to compare from. 963 * @param str2 The String to compare to. 964 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 965 * @see #compareIgnoreCase(String, String, boolean) 966 * @see String#compareToIgnoreCase(String) 967 * @since 3.5 968 * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}. 969 */ 970 @Deprecated 971 public static int compareIgnoreCase(final String str1, final String str2) { 972 return Strings.CI.compare(str1, str2); 973 } 974 975 /** 976 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 977 * <ul> 978 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 979 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 980 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 981 * </ul> 982 * 983 * <p> 984 * This is a {@code null} safe version of : 985 * </p> 986 * <pre> 987 * str1.compareToIgnoreCase(str2) 988 * </pre> 989 * 990 * <p> 991 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case 992 * insensitive. 993 * </p> 994 * 995 * <pre>{@code 996 * StringUtils.compareIgnoreCase(null, null, *) = 0 997 * StringUtils.compareIgnoreCase(null , "a", true) < 0 998 * StringUtils.compareIgnoreCase(null , "a", false) > 0 999 * StringUtils.compareIgnoreCase("a", null, true) > 0 1000 * StringUtils.compareIgnoreCase("a", null, false) < 0 1001 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 1002 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 1003 * StringUtils.compareIgnoreCase("a", "b", *) < 0 1004 * StringUtils.compareIgnoreCase("b", "a", *) > 0 1005 * StringUtils.compareIgnoreCase("a", "B", *) < 0 1006 * StringUtils.compareIgnoreCase("A", "b", *) < 0 1007 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 1008 * }</pre> 1009 * 1010 * @param str1 The String to compare from. 1011 * @param str2 The String to compare to. 1012 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 1013 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 1014 * @see String#compareToIgnoreCase(String) 1015 * @since 3.5 1016 */ 1017 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 1018 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 1019 return 0; 1020 } 1021 if (str1 == null) { 1022 return nullIsLess ? -1 : 1; 1023 } 1024 if (str2 == null) { 1025 return nullIsLess ? 1 : -1; 1026 } 1027 return str1.compareToIgnoreCase(str2); 1028 } 1029 1030 /** 1031 * Tests if CharSequence contains a search CharSequence, handling {@code null}. 1032 * This method uses {@link String#indexOf(String)} if possible. 1033 * 1034 * <p> 1035 * A {@code null} CharSequence will return {@code false}. 1036 * </p> 1037 * 1038 * <pre> 1039 * StringUtils.contains(null, *) = false 1040 * StringUtils.contains(*, null) = false 1041 * StringUtils.contains("", "") = true 1042 * StringUtils.contains("abc", "") = true 1043 * StringUtils.contains("abc", "a") = true 1044 * StringUtils.contains("abc", "z") = false 1045 * </pre> 1046 * 1047 * @param seq The CharSequence to check, may be null 1048 * @param searchSeq The CharSequence to find, may be null 1049 * @return true if the CharSequence contains the search CharSequence, 1050 * false if not or {@code null} string input 1051 * @since 2.0 1052 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 1053 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}. 1054 */ 1055 @Deprecated 1056 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 1057 return Strings.CS.contains(seq, searchSeq); 1058 } 1059 1060 /** 1061 * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible. 1062 * 1063 * <p> 1064 * A {@code null} or empty ("") CharSequence will return {@code false}. 1065 * </p> 1066 * 1067 * <pre> 1068 * StringUtils.contains(null, *) = false 1069 * StringUtils.contains("", *) = false 1070 * StringUtils.contains("abc", 'a') = true 1071 * StringUtils.contains("abc", 'z') = false 1072 * </pre> 1073 * 1074 * @param seq The CharSequence to check, may be null 1075 * @param searchChar The character to find 1076 * @return true if the CharSequence contains the search character, false if not or {@code null} string input 1077 * @since 2.0 1078 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1079 */ 1080 public static boolean contains(final CharSequence seq, final int searchChar) { 1081 if (isEmpty(seq)) { 1082 return false; 1083 } 1084 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1085 } 1086 1087 /** 1088 * Tests if the CharSequence contains any character in the given set of characters. 1089 * 1090 * <p> 1091 * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}. 1092 * </p> 1093 * 1094 * <pre> 1095 * StringUtils.containsAny(null, *) = false 1096 * StringUtils.containsAny("", *) = false 1097 * StringUtils.containsAny(*, null) = false 1098 * StringUtils.containsAny(*, []) = false 1099 * StringUtils.containsAny("zzabyycdxx", 'z', 'a') = true 1100 * StringUtils.containsAny("zzabyycdxx", 'b', 'y') = true 1101 * StringUtils.containsAny("zzabyycdxx", 'z', 'y') = true 1102 * StringUtils.containsAny("aba", 'z]) = false 1103 * </pre> 1104 * 1105 * @param cs The CharSequence to check, may be null. 1106 * @param searchChars The chars to search for, may be null. 1107 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input. 1108 * @since 2.4 1109 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1110 */ 1111 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1112 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1113 return false; 1114 } 1115 final int csLength = cs.length(); 1116 final int searchLength = searchChars.length; 1117 final int csLast = csLength - 1; 1118 final int searchLast = searchLength - 1; 1119 for (int i = 0; i < csLength; i++) { 1120 final char ch = cs.charAt(i); 1121 for (int j = 0; j < searchLength; j++) { 1122 if (searchChars[j] == ch) { 1123 if (Character.isHighSurrogate(ch) 1124 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 1125 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 1126 return true; 1127 } 1128 } 1129 } 1130 } 1131 return false; 1132 } 1133 1134 /** 1135 * Tests if the CharSequence contains any character in the given set of characters. 1136 * 1137 * <p> 1138 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}. 1139 * </p> 1140 * 1141 * <pre> 1142 * StringUtils.containsAny(null, *) = false 1143 * StringUtils.containsAny("", *) = false 1144 * StringUtils.containsAny(*, null) = false 1145 * StringUtils.containsAny(*, "") = false 1146 * StringUtils.containsAny("zzabyycdxx", "za") = true 1147 * StringUtils.containsAny("zzabyycdxx", "by") = true 1148 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1149 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1150 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1151 * StringUtils.containsAny("aba", "z") = false 1152 * </pre> 1153 * 1154 * @param cs The CharSequence to check, may be null. 1155 * @param searchChars The chars to search for, may be null. 1156 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input. 1157 * @since 2.4 1158 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1159 */ 1160 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1161 if (searchChars == null) { 1162 return false; 1163 } 1164 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1165 } 1166 1167 /** 1168 * Tests if the CharSequence contains any of the CharSequences in the given array. 1169 * 1170 * <p> 1171 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1172 * return {@code false}. 1173 * </p> 1174 * 1175 * <pre> 1176 * StringUtils.containsAny(null, *) = false 1177 * StringUtils.containsAny("", *) = false 1178 * StringUtils.containsAny(*, null) = false 1179 * StringUtils.containsAny(*, []) = false 1180 * StringUtils.containsAny("abcd", "ab", null) = true 1181 * StringUtils.containsAny("abcd", "ab", "cd") = true 1182 * StringUtils.containsAny("abc", "d", "abc") = true 1183 * </pre> 1184 * 1185 * @param cs The CharSequence to check, may be null. 1186 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1187 * null as well. 1188 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise. 1189 * @since 3.4 1190 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}. 1191 */ 1192 @Deprecated 1193 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1194 return Strings.CS.containsAny(cs, searchCharSequences); 1195 } 1196 1197 /** 1198 * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case. 1199 * 1200 * <p> 1201 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1202 * return {@code false}. 1203 * </p> 1204 * 1205 * <pre> 1206 * StringUtils.containsAnyIgnoreCase(null, *) = false 1207 * StringUtils.containsAnyIgnoreCase("", *) = false 1208 * StringUtils.containsAnyIgnoreCase(*, null) = false 1209 * StringUtils.containsAnyIgnoreCase(*, []) = false 1210 * StringUtils.containsAnyIgnoreCase("abcd", "ab", null) = true 1211 * StringUtils.containsAnyIgnoreCase("abcd", "ab", "cd") = true 1212 * StringUtils.containsAnyIgnoreCase("abc", "d", "abc") = true 1213 * StringUtils.containsAnyIgnoreCase("abc", "D", "ABC") = true 1214 * StringUtils.containsAnyIgnoreCase("ABC", "d", "abc") = true 1215 * </pre> 1216 * 1217 * @param cs The CharSequence to check, may be null. 1218 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1219 * null as well. 1220 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1221 * @since 3.12.0 1222 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}. 1223 */ 1224 @Deprecated 1225 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) { 1226 return Strings.CI.containsAny(cs, searchCharSequences); 1227 } 1228 1229 /** 1230 * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by 1231 * {@link String#equalsIgnoreCase(String)}. 1232 * 1233 * <p> 1234 * A {@code null} CharSequence will return {@code false}. 1235 * </p> 1236 * 1237 * <pre> 1238 * StringUtils.containsIgnoreCase(null, *) = false 1239 * StringUtils.containsIgnoreCase(*, null) = false 1240 * StringUtils.containsIgnoreCase("", "") = true 1241 * StringUtils.containsIgnoreCase("abc", "") = true 1242 * StringUtils.containsIgnoreCase("abc", "a") = true 1243 * StringUtils.containsIgnoreCase("abc", "z") = false 1244 * StringUtils.containsIgnoreCase("abc", "A") = true 1245 * StringUtils.containsIgnoreCase("abc", "Z") = false 1246 * </pre> 1247 * 1248 * @param str The CharSequence to check, may be null. 1249 * @param searchStr The CharSequence to find, may be null. 1250 * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input. 1251 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence). 1252 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}. 1253 */ 1254 @Deprecated 1255 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1256 return Strings.CI.contains(str, searchStr); 1257 } 1258 1259 /** 1260 * Tests that the CharSequence does not contain certain characters. 1261 * 1262 * <p> 1263 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0) 1264 * always returns true. 1265 * </p> 1266 * 1267 * <pre> 1268 * StringUtils.containsNone(null, *) = true 1269 * StringUtils.containsNone(*, null) = true 1270 * StringUtils.containsNone("", *) = true 1271 * StringUtils.containsNone("ab", '') = true 1272 * StringUtils.containsNone("abab", 'x', 'y', 'z') = true 1273 * StringUtils.containsNone("ab1", 'x', 'y', 'z') = true 1274 * StringUtils.containsNone("abz", 'x', 'y', 'z') = false 1275 * </pre> 1276 * 1277 * @param cs The CharSequence to check, may be null. 1278 * @param searchChars An array of invalid chars, may be null. 1279 * @return true if it contains none of the invalid chars, or is null. 1280 * @since 2.0 1281 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1282 */ 1283 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1284 if (cs == null || searchChars == null) { 1285 return true; 1286 } 1287 final int csLen = cs.length(); 1288 final int csLast = csLen - 1; 1289 final int searchLen = searchChars.length; 1290 final int searchLast = searchLen - 1; 1291 for (int i = 0; i < csLen; i++) { 1292 final char ch = cs.charAt(i); 1293 for (int j = 0; j < searchLen; j++) { 1294 if (searchChars[j] == ch) { 1295 if (Character.isHighSurrogate(ch) 1296 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 1297 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 1298 return false; 1299 } 1300 } 1301 } 1302 } 1303 return true; 1304 } 1305 1306 /** 1307 * Tests that the CharSequence does not contain certain characters. 1308 * 1309 * <p> 1310 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always 1311 * returns true. 1312 * </p> 1313 * 1314 * <pre> 1315 * StringUtils.containsNone(null, *) = true 1316 * StringUtils.containsNone(*, null) = true 1317 * StringUtils.containsNone("", *) = true 1318 * StringUtils.containsNone("ab", "") = true 1319 * StringUtils.containsNone("abab", "xyz") = true 1320 * StringUtils.containsNone("ab1", "xyz") = true 1321 * StringUtils.containsNone("abz", "xyz") = false 1322 * </pre> 1323 * 1324 * @param cs The CharSequence to check, may be null. 1325 * @param invalidChars A String of invalid chars, may be null. 1326 * @return true if it contains none of the invalid chars, or is null. 1327 * @since 2.0 1328 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1329 */ 1330 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1331 if (invalidChars == null) { 1332 return true; 1333 } 1334 return containsNone(cs, invalidChars.toCharArray()); 1335 } 1336 1337 /** 1338 * Tests if the CharSequence contains only certain characters. 1339 * 1340 * <p> 1341 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0) 1342 * always returns {@code true}. 1343 * </p> 1344 * 1345 * <pre> 1346 * StringUtils.containsOnly(null, *) = false 1347 * StringUtils.containsOnly(*, null) = false 1348 * StringUtils.containsOnly("", *) = true 1349 * StringUtils.containsOnly("ab", '') = false 1350 * StringUtils.containsOnly("abab", 'a', 'b', 'c') = true 1351 * StringUtils.containsOnly("ab1", 'a', 'b', 'c') = false 1352 * StringUtils.containsOnly("abz", 'a', 'b', 'c') = false 1353 * </pre> 1354 * 1355 * @param cs The String to check, may be null. 1356 * @param valid An array of valid chars, may be null. 1357 * @return true if it only contains valid chars and is non-null. 1358 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1359 */ 1360 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1361 // All these pre-checks are to maintain API with an older version 1362 if (valid == null || cs == null) { 1363 return false; 1364 } 1365 if (isEmpty(cs)) { 1366 return true; 1367 } 1368 if (valid.length == 0) { 1369 return false; 1370 } 1371 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1372 } 1373 1374 /** 1375 * Tests if the CharSequence contains only certain characters. 1376 * 1377 * <p> 1378 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0) 1379 * always returns {@code true}. 1380 * </p> 1381 * 1382 * <pre> 1383 * StringUtils.containsOnly(null, *) = false 1384 * StringUtils.containsOnly(*, null) = false 1385 * StringUtils.containsOnly("", *) = true 1386 * StringUtils.containsOnly("ab", "") = false 1387 * StringUtils.containsOnly("abab", "abc") = true 1388 * StringUtils.containsOnly("ab1", "abc") = false 1389 * StringUtils.containsOnly("abz", "abc") = false 1390 * </pre> 1391 * 1392 * @param cs The CharSequence to check, may be null. 1393 * @param validChars A String of valid chars, may be null. 1394 * @return true if it only contains valid chars and is non-null. 1395 * @since 2.0 1396 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1397 */ 1398 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1399 if (cs == null || validChars == null) { 1400 return false; 1401 } 1402 return containsOnly(cs, validChars.toCharArray()); 1403 } 1404 1405 /** 1406 * Tests whether the given CharSequence contains any whitespace characters. 1407 * 1408 * <p> 1409 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1410 * </p> 1411 * 1412 * <pre> 1413 * StringUtils.containsWhitespace(null) = false 1414 * StringUtils.containsWhitespace("") = false 1415 * StringUtils.containsWhitespace("ab") = false 1416 * StringUtils.containsWhitespace(" ab") = true 1417 * StringUtils.containsWhitespace("a b") = true 1418 * StringUtils.containsWhitespace("ab ") = true 1419 * </pre> 1420 * 1421 * @param seq The CharSequence to check (may be {@code null}). 1422 * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character. 1423 * @since 3.0 1424 */ 1425 public static boolean containsWhitespace(final CharSequence seq) { 1426 if (isEmpty(seq)) { 1427 return false; 1428 } 1429 final int strLen = seq.length(); 1430 for (int i = 0; i < strLen; i++) { 1431 if (Character.isWhitespace(seq.charAt(i))) { 1432 return true; 1433 } 1434 } 1435 return false; 1436 } 1437 1438 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1439 for (int i = 0; i < decomposed.length(); i++) { 1440 final char charAt = decomposed.charAt(i); 1441 switch (charAt) { 1442 case '\u0141': 1443 decomposed.setCharAt(i, 'L'); 1444 break; 1445 case '\u0142': 1446 decomposed.setCharAt(i, 'l'); 1447 break; 1448 // D with stroke 1449 case '\u0110': 1450 // LATIN CAPITAL LETTER D WITH STROKE 1451 decomposed.setCharAt(i, 'D'); 1452 break; 1453 case '\u0111': 1454 // LATIN SMALL LETTER D WITH STROKE 1455 decomposed.setCharAt(i, 'd'); 1456 break; 1457 // I with bar 1458 case '\u0197': 1459 decomposed.setCharAt(i, 'I'); 1460 break; 1461 case '\u0268': 1462 decomposed.setCharAt(i, 'i'); 1463 break; 1464 case '\u1D7B': 1465 decomposed.setCharAt(i, 'I'); 1466 break; 1467 case '\u1DA4': 1468 decomposed.setCharAt(i, 'i'); 1469 break; 1470 case '\u1DA7': 1471 decomposed.setCharAt(i, 'I'); 1472 break; 1473 // U with bar 1474 case '\u0244': 1475 // LATIN CAPITAL LETTER U BAR 1476 decomposed.setCharAt(i, 'U'); 1477 break; 1478 case '\u0289': 1479 // LATIN SMALL LETTER U BAR 1480 decomposed.setCharAt(i, 'u'); 1481 break; 1482 case '\u1D7E': 1483 // LATIN SMALL CAPITAL LETTER U WITH STROKE 1484 decomposed.setCharAt(i, 'U'); 1485 break; 1486 case '\u1DB6': 1487 // MODIFIER LETTER SMALL U BAR 1488 decomposed.setCharAt(i, 'u'); 1489 break; 1490 // T with stroke 1491 case '\u0166': 1492 // LATIN CAPITAL LETTER T WITH STROKE 1493 decomposed.setCharAt(i, 'T'); 1494 break; 1495 case '\u0167': 1496 // LATIN SMALL LETTER T WITH STROKE 1497 decomposed.setCharAt(i, 't'); 1498 break; 1499 default: 1500 break; 1501 } 1502 } 1503 } 1504 1505 /** 1506 * Counts how many times the char appears in the given string. 1507 * 1508 * <p> 1509 * A {@code null} or empty ("") String input returns {@code 0}. 1510 * </p> 1511 * 1512 * <pre> 1513 * StringUtils.countMatches(null, *) = 0 1514 * StringUtils.countMatches("", *) = 0 1515 * StringUtils.countMatches("abba", '\0') = 0 1516 * StringUtils.countMatches("abba", 'a') = 2 1517 * StringUtils.countMatches("abba", 'b') = 2 1518 * StringUtils.countMatches("abba", 'x') = 0 1519 * </pre> 1520 * 1521 * @param str The CharSequence to check, may be null. 1522 * @param ch The char to count. 1523 * @return The number of occurrences, 0 if the CharSequence is {@code null}. 1524 * @since 3.4 1525 */ 1526 public static int countMatches(final CharSequence str, final char ch) { 1527 if (isEmpty(str)) { 1528 return 0; 1529 } 1530 int count = 0; 1531 // We could also call str.toCharArray() for faster lookups but that would generate more garbage. 1532 for (int i = 0; i < str.length(); i++) { 1533 if (ch == str.charAt(i)) { 1534 count++; 1535 } 1536 } 1537 return count; 1538 } 1539 1540 /** 1541 * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches. 1542 * 1543 * <p> 1544 * A {@code null} or empty ("") String input returns {@code 0}. 1545 * </p> 1546 * 1547 * <pre> 1548 * StringUtils.countMatches(null, *) = 0 1549 * StringUtils.countMatches("", *) = 0 1550 * StringUtils.countMatches("abba", null) = 0 1551 * StringUtils.countMatches("abba", "") = 0 1552 * StringUtils.countMatches("abba", "a") = 2 1553 * StringUtils.countMatches("abba", "ab") = 1 1554 * StringUtils.countMatches("abba", "xxx") = 0 1555 * StringUtils.countMatches("ababa", "aba") = 1 1556 * </pre> 1557 * 1558 * @param str The CharSequence to check, may be null. 1559 * @param sub The substring to count, may be null. 1560 * @return The number of occurrences, 0 if either CharSequence is {@code null}. 1561 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1562 */ 1563 public static int countMatches(final CharSequence str, final CharSequence sub) { 1564 if (isEmpty(str) || isEmpty(sub)) { 1565 return 0; 1566 } 1567 int count = 0; 1568 int idx = 0; 1569 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1570 count++; 1571 idx += sub.length(); 1572 } 1573 return count; 1574 } 1575 1576 /** 1577 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1578 * {@code null}), the value of {@code defaultStr}. 1579 * 1580 * <p> 1581 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1582 * </p> 1583 * 1584 * <pre> 1585 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1586 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1587 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1588 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1589 * StringUtils.defaultIfBlank("", null) = null 1590 * </pre> 1591 * 1592 * @param <T> the specific kind of CharSequence. 1593 * @param str The CharSequence to check, may be null. 1594 * @param defaultStr The default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1595 * {@code null}); may be null. 1596 * @return The passed in CharSequence, or the default. 1597 * @see StringUtils#defaultString(String, String) 1598 * @see #isBlank(CharSequence) 1599 */ 1600 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1601 return isBlank(str) ? defaultStr : str; 1602 } 1603 1604 /** 1605 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}. 1606 * 1607 * <pre> 1608 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1609 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1610 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1611 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1612 * StringUtils.defaultIfEmpty("", null) = null 1613 * </pre> 1614 * 1615 * @param <T> the specific kind of CharSequence. 1616 * @param str The CharSequence to check, may be null. 1617 * @param defaultStr The default CharSequence to return if the input is empty ("") or {@code null}, may be null. 1618 * @return The passed in CharSequence, or the default. 1619 * @see StringUtils#defaultString(String, String) 1620 */ 1621 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1622 return isEmpty(str) ? defaultStr : str; 1623 } 1624 1625 /** 1626 * Returns either the passed in String, or if the String is {@code null}, an empty String (""). 1627 * 1628 * <pre> 1629 * StringUtils.defaultString(null) = "" 1630 * StringUtils.defaultString("") = "" 1631 * StringUtils.defaultString("bat") = "bat" 1632 * </pre> 1633 * 1634 * @param str The String to check, may be null. 1635 * @return The passed in String, or the empty String if it was {@code null}. 1636 * @see Objects#toString(Object, String) 1637 * @see String#valueOf(Object) 1638 */ 1639 public static String defaultString(final String str) { 1640 return Objects.toString(str, EMPTY); 1641 } 1642 1643 /** 1644 * Returns either the given String, or if the String is {@code null}, {@code nullDefault}. 1645 * 1646 * <pre> 1647 * StringUtils.defaultString(null, "NULL") = "NULL" 1648 * StringUtils.defaultString("", "NULL") = "" 1649 * StringUtils.defaultString("bat", "NULL") = "bat" 1650 * </pre> 1651 * <p> 1652 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}: 1653 * </p> 1654 * 1655 * <pre> 1656 * Objects.toString(null, "NULL") = "NULL" 1657 * Objects.toString("", "NULL") = "" 1658 * Objects.toString("bat", "NULL") = "bat" 1659 * </pre> 1660 * 1661 * @param str The String to check, may be null. 1662 * @param nullDefault The default String to return if the input is {@code null}, may be null. 1663 * @return The passed in String, or the default if it was {@code null}. 1664 * @see Objects#toString(Object, String) 1665 * @see String#valueOf(Object) 1666 * @deprecated Use {@link Objects#toString(Object, String)}. 1667 */ 1668 @Deprecated 1669 public static String defaultString(final String str, final String nullDefault) { 1670 return Objects.toString(str, nullDefault); 1671 } 1672 1673 /** 1674 * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}. 1675 * 1676 * <pre> 1677 * StringUtils.deleteWhitespace(null) = null 1678 * StringUtils.deleteWhitespace("") = "" 1679 * StringUtils.deleteWhitespace("abc") = "abc" 1680 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1681 * </pre> 1682 * 1683 * @param str The String to delete whitespace from, may be null. 1684 * @return The String without whitespaces, {@code null} if null String input. 1685 */ 1686 public static String deleteWhitespace(final String str) { 1687 if (isEmpty(str)) { 1688 return str; 1689 } 1690 final int sz = str.length(); 1691 final char[] chs = new char[sz]; 1692 int count = 0; 1693 for (int i = 0; i < sz; i++) { 1694 if (!Character.isWhitespace(str.charAt(i))) { 1695 chs[count++] = str.charAt(i); 1696 } 1697 } 1698 if (count == sz) { 1699 return str; 1700 } 1701 if (count == 0) { 1702 return EMPTY; 1703 } 1704 return new String(chs, 0, count); 1705 } 1706 1707 /** 1708 * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's 1709 * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c". 1710 * 1711 * <p> 1712 * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}. 1713 * </p> 1714 * 1715 * <pre> 1716 * StringUtils.difference(null, null) = null 1717 * StringUtils.difference("", "") = "" 1718 * StringUtils.difference("", "abc") = "abc" 1719 * StringUtils.difference("abc", "") = "" 1720 * StringUtils.difference("abc", "abc") = "" 1721 * StringUtils.difference("abc", "ab") = "" 1722 * StringUtils.difference("ab", "abxyz") = "xyz" 1723 * StringUtils.difference("abcde", "abxyz") = "xyz" 1724 * StringUtils.difference("abcde", "xyz") = "xyz" 1725 * </pre> 1726 * 1727 * @param str1 The first String, may be null. 1728 * @param str2 The second String, may be null. 1729 * @return The portion of str2 where it differs from str1; returns the empty String if they are equal. 1730 * @see #indexOfDifference(CharSequence,CharSequence) 1731 * @since 2.0 1732 */ 1733 public static String difference(final String str1, final String str2) { 1734 if (str1 == null) { 1735 return str2; 1736 } 1737 if (str2 == null) { 1738 return str1; 1739 } 1740 final int at = indexOfDifference(str1, str2); 1741 if (at == INDEX_NOT_FOUND) { 1742 return EMPTY; 1743 } 1744 return str2.substring(at); 1745 } 1746 1747 /** 1748 * Tests if a CharSequence ends with a specified suffix. 1749 * 1750 * <p> 1751 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 1752 * </p> 1753 * 1754 * <pre> 1755 * StringUtils.endsWith(null, null) = true 1756 * StringUtils.endsWith(null, "def") = false 1757 * StringUtils.endsWith("abcdef", null) = false 1758 * StringUtils.endsWith("abcdef", "def") = true 1759 * StringUtils.endsWith("ABCDEF", "def") = false 1760 * StringUtils.endsWith("ABCDEF", "cde") = false 1761 * StringUtils.endsWith("ABCDEF", "") = true 1762 * </pre> 1763 * 1764 * @param str The CharSequence to check, may be null. 1765 * @param suffix The suffix to find, may be null. 1766 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}. 1767 * @see String#endsWith(String) 1768 * @since 2.4 1769 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1770 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}. 1771 */ 1772 @Deprecated 1773 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1774 return Strings.CS.endsWith(str, suffix); 1775 } 1776 1777 /** 1778 * Tests if a CharSequence ends with any of the provided case-sensitive suffixes. 1779 * 1780 * <pre> 1781 * StringUtils.endsWithAny(null, null) = false 1782 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1783 * StringUtils.endsWithAny("abcxyz", null) = false 1784 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1785 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1786 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1787 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1788 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1789 * </pre> 1790 * 1791 * @param sequence The CharSequence to check, may be null. 1792 * @param searchStrings The case-sensitive CharSequences to find, may be empty or contain {@code null}. 1793 * @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 1794 * of the provided case-sensitive {@code searchStrings}. 1795 * @see StringUtils#endsWith(CharSequence, CharSequence) 1796 * @since 3.0 1797 * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}. 1798 */ 1799 @Deprecated 1800 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1801 return Strings.CS.endsWithAny(sequence, searchStrings); 1802 } 1803 1804 /** 1805 * Case-insensitive check if a CharSequence ends with a specified suffix. 1806 * 1807 * <p> 1808 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 1809 * </p> 1810 * 1811 * <pre> 1812 * StringUtils.endsWithIgnoreCase(null, null) = true 1813 * StringUtils.endsWithIgnoreCase(null, "def") = false 1814 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1815 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1816 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1817 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1818 * </pre> 1819 * 1820 * @param str The CharSequence to check, may be null 1821 * @param suffix The suffix to find, may be null 1822 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null} 1823 * @see String#endsWith(String) 1824 * @since 2.4 1825 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1826 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)}. 1827 */ 1828 @Deprecated 1829 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1830 return Strings.CI.endsWith(str, suffix); 1831 } 1832 1833 /** 1834 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters. 1835 * 1836 * <p> 1837 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>. 1838 * </p> 1839 * 1840 * <pre> 1841 * StringUtils.equals(null, null) = true 1842 * StringUtils.equals(null, "abc") = false 1843 * StringUtils.equals("abc", null) = false 1844 * StringUtils.equals("abc", "abc") = true 1845 * StringUtils.equals("abc", "ABC") = false 1846 * </pre> 1847 * 1848 * @param cs1 The first CharSequence, may be {@code null}. 1849 * @param cs2 The second CharSequence, may be {@code null}. 1850 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}. 1851 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1852 * @see Object#equals(Object) 1853 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1854 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}. 1855 */ 1856 @Deprecated 1857 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1858 return Strings.CS.equals(cs1, cs2); 1859 } 1860 1861 /** 1862 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the 1863 * {@code searchStrings}. 1864 * 1865 * <pre> 1866 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1867 * StringUtils.equalsAny(null, null, null) = true 1868 * StringUtils.equalsAny(null, "abc", "def") = false 1869 * StringUtils.equalsAny("abc", null, "def") = false 1870 * StringUtils.equalsAny("abc", "abc", "def") = true 1871 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1872 * </pre> 1873 * 1874 * @param string to compare, may be {@code null}. 1875 * @param searchStrings A vararg of strings, may be {@code null}. 1876 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is 1877 * null or contains no matches. 1878 * @since 3.5 1879 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}. 1880 */ 1881 @Deprecated 1882 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1883 return Strings.CS.equalsAny(string, searchStrings); 1884 } 1885 1886 /** 1887 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1888 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1889 * 1890 * <pre> 1891 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1892 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1893 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1894 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1895 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1896 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1897 * </pre> 1898 * 1899 * @param string to compare, may be {@code null}. 1900 * @param searchStrings A vararg of strings, may be {@code null}. 1901 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1902 * {@code false} if {@code searchStrings} is null or contains no matches. 1903 * @since 3.5 1904 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI.equalsAny(CharSequence, CharSequence...)}. 1905 */ 1906 @Deprecated 1907 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) { 1908 return Strings.CI.equalsAny(string, searchStrings); 1909 } 1910 1911 /** 1912 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case. 1913 * 1914 * <p> 1915 * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>. 1916 * </p> 1917 * 1918 * <pre> 1919 * StringUtils.equalsIgnoreCase(null, null) = true 1920 * StringUtils.equalsIgnoreCase(null, "abc") = false 1921 * StringUtils.equalsIgnoreCase("abc", null) = false 1922 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1923 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1924 * </pre> 1925 * 1926 * @param cs1 The first CharSequence, may be {@code null}. 1927 * @param cs2 The second CharSequence, may be {@code null}. 1928 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}. 1929 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1930 * @see #equals(CharSequence, CharSequence) 1931 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}. 1932 */ 1933 @Deprecated 1934 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1935 return Strings.CI.equals(cs1, cs2); 1936 } 1937 1938 /** 1939 * Returns the first value in the array which is not empty (""), {@code null} or whitespace only. 1940 * 1941 * <p> 1942 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1943 * </p> 1944 * 1945 * <p> 1946 * If all values are blank or the array is {@code null} or empty then {@code null} is returned. 1947 * </p> 1948 * 1949 * <pre> 1950 * StringUtils.firstNonBlank(null, null, null) = null 1951 * StringUtils.firstNonBlank(null, "", " ") = null 1952 * StringUtils.firstNonBlank("abc") = "abc" 1953 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1954 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1955 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1956 * StringUtils.firstNonBlank() = null 1957 * </pre> 1958 * 1959 * @param <T> the specific kind of CharSequence. 1960 * @param values The values to test, may be {@code null} or empty. 1961 * @return The first value from {@code values} which is not blank, or {@code null} if there are no non-blank values. 1962 * @since 3.8 1963 */ 1964 @SafeVarargs 1965 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1966 if (values != null) { 1967 for (final T val : values) { 1968 if (isNotBlank(val)) { 1969 return val; 1970 } 1971 } 1972 } 1973 return null; 1974 } 1975 1976 /** 1977 * Returns the first value in the array which is not empty. 1978 * 1979 * <p> 1980 * If all values are empty or the array is {@code null} or empty then {@code null} is returned. 1981 * </p> 1982 * 1983 * <pre> 1984 * StringUtils.firstNonEmpty(null, null, null) = null 1985 * StringUtils.firstNonEmpty(null, null, "") = null 1986 * StringUtils.firstNonEmpty(null, "", " ") = " " 1987 * StringUtils.firstNonEmpty("abc") = "abc" 1988 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1989 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1990 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1991 * StringUtils.firstNonEmpty() = null 1992 * </pre> 1993 * 1994 * @param <T> the specific kind of CharSequence. 1995 * @param values The values to test, may be {@code null} or empty. 1996 * @return The first value from {@code values} which is not empty, or {@code null} if there are no non-empty values. 1997 * @since 3.8 1998 */ 1999 @SafeVarargs 2000 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 2001 if (values != null) { 2002 for (final T val : values) { 2003 if (isNotEmpty(val)) { 2004 return val; 2005 } 2006 } 2007 } 2008 return null; 2009 } 2010 2011 /** 2012 * Gets the bytes of the string using {@link String#getBytes(Charset)}, handling {@code null} safely. 2013 * 2014 * @param string input string. 2015 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 2016 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 2017 * @see String#getBytes(Charset) 2018 * @since 3.10 2019 */ 2020 public static byte[] getBytes(final String string, final Charset charset) { 2021 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 2022 } 2023 2024 /** 2025 * Gets the bytes of the string using {@link String#getBytes(String)}, handling {@code null} safely. 2026 * 2027 * @param string input string. 2028 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 2029 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 2030 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 2031 * @see String#getBytes(String) 2032 * @since 3.10 2033 */ 2034 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 2035 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 2036 } 2037 2038 /** 2039 * Gets the initial sequence of characters common to all strings in the array. 2040 * 2041 * <p> 2042 * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -> "i am a "} 2043 * </p> 2044 * 2045 * <pre> 2046 * StringUtils.getCommonPrefix(null) = "" 2047 * StringUtils.getCommonPrefix(new String[] {}) = "" 2048 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 2049 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 2050 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 2051 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 2052 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 2053 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 2054 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 2055 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 2056 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 2057 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 2058 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 2059 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 2060 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2061 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2062 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2063 * </pre> 2064 * 2065 * @param strs array of String objects, entries may be null. 2066 * @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 2067 * if there is no common prefix. 2068 * @since 2.4 2069 */ 2070 public static String getCommonPrefix(final String... strs) { 2071 if (ArrayUtils.isEmpty(strs)) { 2072 return EMPTY; 2073 } 2074 final int smallestIndexOfDiff = indexOfDifference(strs); 2075 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2076 // all strings were identical 2077 if (strs[0] == null) { 2078 return EMPTY; 2079 } 2080 return strs[0]; 2081 } 2082 if (smallestIndexOfDiff == 0) { 2083 // there were no common initial characters 2084 return EMPTY; 2085 } 2086 // we found a common initial character sequence 2087 return strs[0].substring(0, smallestIndexOfDiff); 2088 } 2089 2090 /** 2091 * Gets the Unicode digits in {@code str}, concatenated in their original order. 2092 * 2093 * <p> 2094 * An empty ("") String will be returned if no digits are found in {@code str}. 2095 * </p> 2096 * 2097 * <pre> 2098 * StringUtils.getDigits(null) = null 2099 * StringUtils.getDigits("") = "" 2100 * StringUtils.getDigits("abc") = "" 2101 * StringUtils.getDigits("1000$") = "1000" 2102 * StringUtils.getDigits("1123~45") = "112345" 2103 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2104 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2105 * </pre> 2106 * 2107 * @param str The String to extract digits from, may be null. 2108 * @return String with only digits, or an empty ("") String if no digits are found, or {@code null} String if {@code str} is null. 2109 * @since 3.6 2110 */ 2111 public static String getDigits(final String str) { 2112 if (isEmpty(str)) { 2113 return str; 2114 } 2115 final int len = str.length(); 2116 final char[] buffer = new char[len]; 2117 int count = 0; 2118 2119 for (int i = 0; i < len;) { 2120 final int codePoint = str.codePointAt(i); 2121 if (Character.isDigit(codePoint)) { 2122 count += Character.toChars(codePoint, buffer, count); 2123 } 2124 i += Character.charCount(codePoint); 2125 } 2126 return new String(buffer, 0, count); 2127 } 2128 2129 /** 2130 * Gets the Fuzzy Distance which indicates the similarity score between two Strings. 2131 * 2132 * <p> 2133 * 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 2134 * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity. 2135 * </p> 2136 * 2137 * <pre> 2138 * StringUtils.getFuzzyDistance(null, null, null) = Throws {@link IllegalArgumentException} 2139 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2140 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2141 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2142 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2143 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2144 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2145 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2146 * </pre> 2147 * 2148 * @param term A full term that should be matched against, must not be null. 2149 * @param query The query that will be matched against a term, must not be null. 2150 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case. 2151 * @return result score. 2152 * @throws IllegalArgumentException Thrown if either String input {@code null} or Locale input {@code null}. 2153 * @since 3.4 2154 * @deprecated As of 3.6, use Apache Commons Text 2155 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2156 * FuzzyScore</a> instead. 2157 */ 2158 @Deprecated 2159 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2160 if (term == null || query == null) { 2161 throw new IllegalArgumentException("Strings must not be null"); 2162 } 2163 if (locale == null) { 2164 throw new IllegalArgumentException("Locale must not be null"); 2165 } 2166 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2167 // case right from the start. Turning characters to lower case 2168 // via Character.toLowerCase(char) is unfortunately insufficient 2169 // as it does not accept a locale. 2170 final String termLowerCase = term.toString().toLowerCase(locale); 2171 final String queryLowerCase = query.toString().toLowerCase(locale); 2172 // the resulting score 2173 int score = 0; 2174 // the position in the term which will be scanned next for potential 2175 // query character matches 2176 int termIndex = 0; 2177 // index of the previously matched character in the term 2178 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2179 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2180 final char queryChar = queryLowerCase.charAt(queryIndex); 2181 boolean termCharacterMatchFound = false; 2182 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2183 final char termChar = termLowerCase.charAt(termIndex); 2184 if (queryChar == termChar) { 2185 // simple character matches result in one point 2186 score++; 2187 // subsequent character matches further improve 2188 // the score. 2189 if (previousMatchingCharacterIndex + 1 == termIndex) { 2190 score += 2; 2191 } 2192 previousMatchingCharacterIndex = termIndex; 2193 // we can leave the nested loop. Every character in the 2194 // query can match at most one character in the term. 2195 termCharacterMatchFound = true; 2196 } 2197 } 2198 } 2199 return score; 2200 } 2201 2202 /** 2203 * Gets either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 2204 * {@code null}), the value supplied by {@code defaultStrSupplier}. 2205 * 2206 * <p> 2207 * Whitespace is defined by {@link Character#isWhitespace(char)}. 2208 * </p> 2209 * 2210 * <p> 2211 * The caller is responsible for thread safety and exception handling for the default value supplier. 2212 * </p> 2213 * 2214 * <pre> 2215 * {@code 2216 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2217 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2218 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2219 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2220 * StringUtils.getIfBlank("", () -> null) = null 2221 * StringUtils.getIfBlank("", null) = null 2222 * }</pre> 2223 * 2224 * @param <T> the specific kind of CharSequence. 2225 * @param str The CharSequence to check, may be null. 2226 * @param defaultSupplier The supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty 2227 * ({@code ""}), or {@code null}); may be null. 2228 * @return The passed in CharSequence, or the default 2229 * @see StringUtils#defaultString(String, String) 2230 * @see #isBlank(CharSequence) 2231 * @since 3.10 2232 */ 2233 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2234 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2235 } 2236 2237 /** 2238 * Gets either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2239 * 2240 * <p> 2241 * The caller is responsible for thread safety and exception handling for the default value supplier. 2242 * </p> 2243 * 2244 * <pre> 2245 * {@code 2246 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2247 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2248 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2249 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2250 * StringUtils.getIfEmpty("", () -> null) = null 2251 * StringUtils.getIfEmpty("", null) = null 2252 * } 2253 * </pre> 2254 * 2255 * @param <T> the specific kind of CharSequence. 2256 * @param str The CharSequence to check, may be null. 2257 * @param defaultSupplier The supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null. 2258 * @return The passed in CharSequence, or the default. 2259 * @see StringUtils#defaultString(String, String) 2260 * @since 3.10 2261 */ 2262 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2263 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2264 } 2265 2266 /** 2267 * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings. 2268 * 2269 * <p> 2270 * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for 2271 * matching initial characters. 2272 * </p> 2273 * 2274 * <p> 2275 * This implementation is based on the Jaro Winkler similarity algorithm from 2276 * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>. 2277 * </p> 2278 * 2279 * <pre> 2280 * StringUtils.getJaroWinklerDistance(null, null) = Throws {@link IllegalArgumentException} 2281 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2282 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2283 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2284 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2285 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2286 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2287 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2288 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2289 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2290 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2291 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2292 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2293 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2294 * </pre> 2295 * 2296 * @param first The first String, must not be null. 2297 * @param second The second String, must not be null. 2298 * @return result distance. 2299 * @throws IllegalArgumentException Thrown if either String input {@code null}. 2300 * @since 3.3 2301 * @deprecated As of 3.6, use Apache Commons Text 2302 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2303 * JaroWinklerDistance</a> instead. 2304 */ 2305 @Deprecated 2306 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2307 final double DEFAULT_SCALING_FACTOR = 0.1; 2308 2309 if (first == null || second == null) { 2310 throw new IllegalArgumentException("Strings must not be null"); 2311 } 2312 2313 final int[] mtp = matches(first, second); 2314 final double m = mtp[0]; 2315 if (m == 0) { 2316 return 0D; 2317 } 2318 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2319 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2320 return Math.round(jw * 100.0D) / 100.0D; 2321 } 2322 2323 /** 2324 * Gets the Levenshtein distance between two Strings. 2325 * 2326 * <p> 2327 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2328 * substitution). 2329 * </p> 2330 * 2331 * <p> 2332 * The implementation uses a single-dimensional array of length s.length() + 1. See 2333 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2334 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details. 2335 * </p> 2336 * 2337 * <pre> 2338 * StringUtils.getLevenshteinDistance(null, *) = Throws {@link IllegalArgumentException} 2339 * StringUtils.getLevenshteinDistance(*, null) = Throws {@link IllegalArgumentException} 2340 * StringUtils.getLevenshteinDistance("", "") = 0 2341 * StringUtils.getLevenshteinDistance("", "a") = 1 2342 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2343 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2344 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2345 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2346 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2347 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2348 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2349 * </pre> 2350 * 2351 * @param s The first String, must not be null. 2352 * @param t The second String, must not be null. 2353 * @return result distance. 2354 * @throws IllegalArgumentException Thrown if either String input {@code null}. 2355 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence) 2356 * @deprecated As of 3.6, use Apache Commons Text 2357 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2358 * LevenshteinDistance</a> instead. 2359 */ 2360 @Deprecated 2361 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2362 if (s == null || t == null) { 2363 throw new IllegalArgumentException("Strings must not be null"); 2364 } 2365 2366 int n = s.length(); 2367 int m = t.length(); 2368 2369 if (n == 0) { 2370 return m; 2371 } 2372 if (m == 0) { 2373 return n; 2374 } 2375 2376 if (n > m) { 2377 // swap the input strings to consume less memory 2378 final CharSequence tmp = s; 2379 s = t; 2380 t = tmp; 2381 n = m; 2382 m = t.length(); 2383 } 2384 2385 final int[] p = new int[n + 1]; 2386 // indexes into strings s and t 2387 int i; // iterates through s 2388 int j; // iterates through t 2389 int upperleft; 2390 int upper; 2391 2392 char jOfT; // jth character of t 2393 int cost; 2394 2395 for (i = 0; i <= n; i++) { 2396 p[i] = i; 2397 } 2398 2399 for (j = 1; j <= m; j++) { 2400 upperleft = p[0]; 2401 jOfT = t.charAt(j - 1); 2402 p[0] = j; 2403 2404 for (i = 1; i <= n; i++) { 2405 upper = p[i]; 2406 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2407 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2408 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2409 upperleft = upper; 2410 } 2411 } 2412 2413 return p[n]; 2414 } 2415 2416 /** 2417 * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold. 2418 * 2419 * <p> 2420 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2421 * substitution). 2422 * </p> 2423 * 2424 * <p> 2425 * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance 2426 * algorithm. 2427 * </p> 2428 * 2429 * <pre> 2430 * StringUtils.getLevenshteinDistance(null, *, *) = Throws {@link IllegalArgumentException} 2431 * StringUtils.getLevenshteinDistance(*, null, *) = Throws {@link IllegalArgumentException} 2432 * StringUtils.getLevenshteinDistance(*, *, -1) = Throws {@link IllegalArgumentException} 2433 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2434 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2435 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2436 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2437 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2438 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2439 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2440 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2441 * </pre> 2442 * 2443 * @param s The first String, must not be null. 2444 * @param t The second String, must not be null. 2445 * @param threshold The target threshold, must not be negative. 2446 * @return result distance, or {@code -1} if the distance would be greater than the threshold. 2447 * @throws IllegalArgumentException Thrown if either String input {@code null} or negative threshold. 2448 * @deprecated As of 3.6, use Apache Commons Text 2449 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2450 * LevenshteinDistance</a> instead. 2451 */ 2452 @Deprecated 2453 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2454 if (s == null || t == null) { 2455 throw new IllegalArgumentException("Strings must not be null"); 2456 } 2457 if (threshold < 0) { 2458 throw new IllegalArgumentException("Threshold must not be negative"); 2459 } 2460 2461 /* 2462 This implementation only computes the distance if it's less than or equal to the 2463 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2464 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2465 computing a diagonal stripe of width 2k + 1 of the cost table. 2466 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2467 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2468 d is the distance. 2469 2470 One subtlety comes from needing to ignore entries on the border of our stripe 2471 for example, 2472 p[] = |#|#|#|* 2473 d[] = *|#|#|#| 2474 We must ignore the entry to the left of the leftmost member 2475 We must ignore the entry above the rightmost member 2476 2477 Another subtlety comes from our stripe running off the matrix if the strings aren't 2478 of the same size. Since string s is always swapped to be the shorter of the two, 2479 the stripe will always run off to the upper right instead of the lower left of the matrix. 2480 2481 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2482 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2483 2484 1 2 3 4 5 2485 1 |#|#| | | | 2486 2 |#|#|#| | | 2487 3 | |#|#|#| | 2488 4 | | |#|#|#| 2489 5 | | | |#|#| 2490 6 | | | | |#| 2491 7 | | | | | | 2492 2493 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2494 into one of length 7 in edit distance of 1. 2495 2496 Additionally, this implementation decreases memory usage by using two 2497 single-dimensional arrays and swapping them back and forth instead of allocating 2498 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2499 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2500 large values so that entries we don't compute are ignored. 2501 2502 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2503 */ 2504 2505 int n = s.length(); // length of s 2506 int m = t.length(); // length of t 2507 2508 // if one string is empty, the edit distance is necessarily the length of the other 2509 if (n == 0) { 2510 return m <= threshold ? m : -1; 2511 } 2512 if (m == 0) { 2513 return n <= threshold ? n : -1; 2514 } 2515 if (Math.abs(n - m) > threshold) { 2516 // no need to calculate the distance if the length difference is greater than the threshold 2517 return -1; 2518 } 2519 2520 if (n > m) { 2521 // swap the two strings to consume less memory 2522 final CharSequence tmp = s; 2523 s = t; 2524 t = tmp; 2525 n = m; 2526 m = t.length(); 2527 } 2528 2529 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2530 int[] d = new int[n + 1]; // cost array, horizontally 2531 int[] tmp; // placeholder to assist in swapping p and d 2532 2533 // fill in starting table values 2534 final int boundary = Math.min(n, threshold) + 1; 2535 for (int i = 0; i < boundary; i++) { 2536 p[i] = i; 2537 } 2538 // these fills ensure that the value above the rightmost entry of our 2539 // stripe will be ignored in following loop iterations 2540 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2541 Arrays.fill(d, Integer.MAX_VALUE); 2542 2543 // iterates through t 2544 for (int j = 1; j <= m; j++) { 2545 final char jOfT = t.charAt(j - 1); // jth character of t 2546 d[0] = j; 2547 2548 // compute stripe indices, constrain to array size 2549 final int min = Math.max(1, j - threshold); 2550 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2551 2552 // the stripe may lead off of the table if s and t are of different sizes 2553 if (min > max) { 2554 return -1; 2555 } 2556 2557 // ignore entry left of leftmost 2558 if (min > 1) { 2559 d[min - 1] = Integer.MAX_VALUE; 2560 } 2561 2562 // iterates through [min, max] in s 2563 for (int i = min; i <= max; i++) { 2564 if (s.charAt(i - 1) == jOfT) { 2565 // diagonally left and up 2566 d[i] = p[i - 1]; 2567 } else { 2568 // 1 + minimum of cell to the left, to the top, diagonally left and up 2569 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2570 } 2571 } 2572 2573 // copy current distance counts to 'previous row' distance counts 2574 tmp = p; 2575 p = d; 2576 d = tmp; 2577 } 2578 2579 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2580 // distance 2581 if (p[n] <= threshold) { 2582 return p[n]; 2583 } 2584 return -1; 2585 } 2586 2587 /** 2588 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2589 * 2590 * <p> 2591 * A {@code null} CharSequence will return {@code -1}. 2592 * </p> 2593 * 2594 * <pre> 2595 * StringUtils.indexOf(null, *) = -1 2596 * StringUtils.indexOf(*, null) = -1 2597 * StringUtils.indexOf("", "") = 0 2598 * StringUtils.indexOf("", *) = -1 (except when * = "") 2599 * StringUtils.indexOf("aabaabaa", "a") = 0 2600 * StringUtils.indexOf("aabaabaa", "b") = 2 2601 * StringUtils.indexOf("aabaabaa", "ab") = 1 2602 * StringUtils.indexOf("aabaabaa", "") = 0 2603 * </pre> 2604 * 2605 * @param seq The CharSequence to check, may be null. 2606 * @param searchSeq The CharSequence to find, may be null. 2607 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 2608 * @since 2.0 2609 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2610 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}. 2611 */ 2612 @Deprecated 2613 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2614 return Strings.CS.indexOf(seq, searchSeq); 2615 } 2616 2617 /** 2618 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2619 * 2620 * <p> 2621 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 2622 * start position greater than the string length only matches an empty search CharSequence. 2623 * </p> 2624 * 2625 * <pre> 2626 * StringUtils.indexOf(null, *, *) = -1 2627 * StringUtils.indexOf(*, null, *) = -1 2628 * StringUtils.indexOf("", "", 0) = 0 2629 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2630 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2631 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2632 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2633 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2634 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2635 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2636 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2637 * StringUtils.indexOf("abc", "", 9) = 3 2638 * </pre> 2639 * 2640 * @param seq The CharSequence to check, may be null. 2641 * @param searchSeq The CharSequence to find, may be null. 2642 * @param startPos The start position, negative treated as zero. 2643 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 2644 * @since 2.0 2645 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2646 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}. 2647 */ 2648 @Deprecated 2649 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2650 return Strings.CS.indexOf(seq, searchSeq, startPos); 2651 } 2652 2653 /** 2654 * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the 2655 * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is 2656 * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that: 2657 * 2658 * <pre> 2659 * this.charAt(<em>k</em>) == searchChar 2660 * </pre> 2661 * 2662 * <p> 2663 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2664 * </p> 2665 * 2666 * <pre> 2667 * this.codePointAt(<em>k</em>) == searchChar 2668 * </pre> 2669 * 2670 * <p> 2671 * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned. 2672 * </p> 2673 * 2674 * <p> 2675 * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}. 2676 * </p> 2677 * 2678 * <pre> 2679 * StringUtils.indexOf(null, *) = -1 2680 * StringUtils.indexOf("", *) = -1 2681 * StringUtils.indexOf("aabaabaa", 'a') = 0 2682 * StringUtils.indexOf("aabaabaa", 'b') = 2 2683 * StringUtils.indexOf("aaaaaaaa", 'Z') = -1 2684 * </pre> 2685 * 2686 * @param seq The CharSequence to check, may be null. 2687 * @param searchChar The character to find. 2688 * @return The first index of the search character, -1 if no match or {@code null} string input. 2689 * @since 2.0 2690 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2691 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2692 */ 2693 public static int indexOf(final CharSequence seq, final int searchChar) { 2694 if (isEmpty(seq)) { 2695 return INDEX_NOT_FOUND; 2696 } 2697 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2698 } 2699 2700 /** 2701 * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index. 2702 * <p> 2703 * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no 2704 * 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 2705 * (inclusive), this is the smallest value <em>k</em> such that: 2706 * </p> 2707 * 2708 * <pre> 2709 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2710 * </pre> 2711 * 2712 * <p> 2713 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2714 * </p> 2715 * 2716 * <pre> 2717 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2718 * </pre> 2719 * 2720 * <p> 2721 * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned. 2722 * </p> 2723 * 2724 * <p> 2725 * 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 2726 * 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: 2727 * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}. 2728 * </p> 2729 * <p> 2730 * All indices are specified in {@code char} values (Unicode code units). 2731 * </p> 2732 * 2733 * <pre> 2734 * StringUtils.indexOf(null, *, *) = -1 2735 * StringUtils.indexOf("", *, *) = -1 2736 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2737 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2738 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2739 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2740 * </pre> 2741 * 2742 * @param seq The CharSequence to check, may be null. 2743 * @param searchChar The character to find. 2744 * @param startPos The start position, negative treated as zero. 2745 * @return The first index of the search character (always ≥ startPos), -1 if no match or {@code null} string input. 2746 * @since 2.0 2747 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2748 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2749 */ 2750 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2751 if (isEmpty(seq)) { 2752 return INDEX_NOT_FOUND; 2753 } 2754 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2755 } 2756 2757 /** 2758 * Search a CharSequence to find the first index of any character in the given set of characters. 2759 * 2760 * <p> 2761 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2762 * </p> 2763 * 2764 * <pre> 2765 * StringUtils.indexOfAny(null, *) = -1 2766 * StringUtils.indexOfAny("", *) = -1 2767 * StringUtils.indexOfAny(*, null) = -1 2768 * StringUtils.indexOfAny(*, []) = -1 2769 * StringUtils.indexOfAny("zzabyycdxx", 'z', 'a') = 0 2770 * StringUtils.indexOfAny("zzabyycdxx", 'b', 'y') = 3 2771 * StringUtils.indexOfAny("aba", 'z') = -1 2772 * </pre> 2773 * 2774 * @param cs The CharSequence to check, may be null. 2775 * @param searchChars The chars to search for, may be null. 2776 * @return The index of any of the chars, -1 if no match or null input. 2777 * @since 2.0 2778 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2779 */ 2780 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2781 return indexOfAny(cs, 0, searchChars); 2782 } 2783 2784 /** 2785 * Find the first index of any of a set of potential substrings. 2786 * 2787 * <p> 2788 * 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 2789 * 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 2790 * possible. 2791 * </p> 2792 * 2793 * <pre> 2794 * StringUtils.indexOfAny(null, *) = -1 2795 * StringUtils.indexOfAny(*, null) = -1 2796 * StringUtils.indexOfAny(*, []) = -1 2797 * StringUtils.indexOfAny("zzabyycdxx", "ab", "cd") = 2 2798 * StringUtils.indexOfAny("zzabyycdxx", "cd", "ab") = 2 2799 * StringUtils.indexOfAny("zzabyycdxx", "mn", "op") = -1 2800 * StringUtils.indexOfAny("zzabyycdxx", "zab", "aby") = 1 2801 * StringUtils.indexOfAny("zzabyycdxx", new CharSequence[] { "" }) = 0 2802 * StringUtils.indexOfAny("", new CharSequence[] { "" }) = 0 2803 * StringUtils.indexOfAny("", new CharSequence[] { "a" }) = -1 2804 * </pre> 2805 * 2806 * <p> 2807 * Use an explicit array when searching for a single substring. Passing a single {@link String} as the second argument instead selects 2808 * {@link #indexOfAny(CharSequence, String)}, which searches for individual characters. 2809 * </p> 2810 * 2811 * @param str The CharSequence to check, may be null. 2812 * @param searchStrs The CharSequences to search for, may be null. 2813 * @return The first index of any of the searchStrs in str, -1 if no match. 2814 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2815 */ 2816 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2817 if (str == null || searchStrs == null) { 2818 return INDEX_NOT_FOUND; 2819 } 2820 // String's can't have a MAX_VALUEth index. 2821 int ret = Integer.MAX_VALUE; 2822 int tmp; 2823 for (final CharSequence search : searchStrs) { 2824 if (search == null) { 2825 continue; 2826 } 2827 tmp = CharSequenceUtils.indexOf(str, search, 0); 2828 if (tmp == INDEX_NOT_FOUND) { 2829 continue; 2830 } 2831 if (tmp < ret) { 2832 ret = tmp; 2833 } 2834 } 2835 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2836 } 2837 2838 /** 2839 * Search a CharSequence to find the first index of any character in the given set of characters. 2840 * 2841 * <p> 2842 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2843 * </p> 2844 * <p> 2845 * The following is the same as {@code indexOfAny(cs, 0, searchChars)}. 2846 * </p> 2847 * <pre> 2848 * StringUtils.indexOfAny(null, 0, *) = -1 2849 * StringUtils.indexOfAny("", 0, *) = -1 2850 * StringUtils.indexOfAny(*, 0, null) = -1 2851 * StringUtils.indexOfAny(*, 0, []) = -1 2852 * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0 2853 * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3 2854 * StringUtils.indexOfAny("aba", 0, ['z']) = -1 2855 * </pre> 2856 * 2857 * @param cs The CharSequence to check, may be null. 2858 * @param csStart Start searching the input {@code cs} at this index. 2859 * @param searchChars The chars to search for, may be null. 2860 * @return The index of any of the chars, -1 if no match or null input. 2861 * @since 2.0 2862 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2863 */ 2864 public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) { 2865 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2866 return INDEX_NOT_FOUND; 2867 } 2868 final int csLen = cs.length(); 2869 final int csLast = csLen - 1; 2870 final int searchLen = searchChars.length; 2871 final int searchLast = searchLen - 1; 2872 for (int i = Math.max(csStart, 0); i < csLen; i++) { 2873 final char ch = cs.charAt(i); 2874 for (int j = 0; j < searchLen; j++) { 2875 if (searchChars[j] == ch) { 2876 if (Character.isHighSurrogate(ch) 2877 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 2878 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 2879 return i; 2880 } 2881 } 2882 } 2883 } 2884 return INDEX_NOT_FOUND; 2885 } 2886 2887 /** 2888 * Search a CharSequence to find the first index of any character in the given set of characters. 2889 * 2890 * <p> 2891 * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}. 2892 * </p> 2893 * 2894 * <pre> 2895 * StringUtils.indexOfAny(null, *) = -1 2896 * StringUtils.indexOfAny("", *) = -1 2897 * StringUtils.indexOfAny(*, null) = -1 2898 * StringUtils.indexOfAny(*, "") = -1 2899 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2900 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2901 * StringUtils.indexOfAny("aba", "z") = -1 2902 * </pre> 2903 * 2904 * @param cs The CharSequence to check, may be null. 2905 * @param searchChars The chars to search for, may be null. 2906 * @return The index of any of the chars, -1 if no match or null input. 2907 * @since 2.0 2908 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2909 */ 2910 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2911 if (isEmpty(cs) || isEmpty(searchChars)) { 2912 return INDEX_NOT_FOUND; 2913 } 2914 return indexOfAny(cs, searchChars.toCharArray()); 2915 } 2916 2917 /** 2918 * 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 2919 * (cs.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2920 * 2921 * <p> 2922 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2923 * </p> 2924 * 2925 * <pre> 2926 * StringUtils.indexOfAnyBut(null, *) = -1 2927 * StringUtils.indexOfAnyBut("", *) = -1 2928 * StringUtils.indexOfAnyBut(*, null) = -1 2929 * StringUtils.indexOfAnyBut(*, []) = -1 2930 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2931 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2932 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2933 * </pre> 2934 * 2935 * @param cs The CharSequence to check, may be null. 2936 * @param searchChars The chars to search for, may be null. 2937 * @return The index of any of the chars, -1 if no match or null input. 2938 * @since 2.0 2939 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2940 */ 2941 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2942 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2943 return INDEX_NOT_FOUND; 2944 } 2945 return indexOfAnyBut(cs, CharBuffer.wrap(searchChars)); 2946 } 2947 2948 /** 2949 * 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 2950 * (seq.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2951 * 2952 * <p> 2953 * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}. 2954 * </p> 2955 * 2956 * <pre> 2957 * StringUtils.indexOfAnyBut(null, *) = -1 2958 * StringUtils.indexOfAnyBut("", *) = -1 2959 * StringUtils.indexOfAnyBut(*, null) = -1 2960 * StringUtils.indexOfAnyBut(*, "") = -1 2961 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2962 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2963 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2964 * </pre> 2965 * 2966 * @param seq The CharSequence to check, may be null. 2967 * @param searchChars The chars to search for, may be null. 2968 * @return The index of any of the chars, -1 if no match or null input. 2969 * @since 2.0 2970 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2971 */ 2972 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2973 if (isEmpty(seq) || isEmpty(searchChars)) { 2974 return INDEX_NOT_FOUND; 2975 } 2976 final Set<Integer> searchSetCodePoints = searchChars.codePoints() 2977 .boxed().collect(Collectors.toSet()); 2978 // advance character index from one interpreted codepoint to the next 2979 for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) { 2980 final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx); 2981 if (!searchSetCodePoints.contains(curSeqCodePoint)) { 2982 return curSeqCharIdx; 2983 } 2984 curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates 2985 } 2986 return INDEX_NOT_FOUND; 2987 } 2988 2989 /** 2990 * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ. 2991 * 2992 * <p> 2993 * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7} 2994 * </p> 2995 * 2996 * <pre> 2997 * StringUtils.indexOfDifference(null) = -1 2998 * StringUtils.indexOfDifference(new String[] {}) = -1 2999 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 3000 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 3001 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 3002 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 3003 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 3004 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 3005 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 3006 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 3007 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 3008 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 3009 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 3010 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 3011 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 3012 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 3013 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 3014 * </pre> 3015 * 3016 * @param css array of CharSequences, entries may be null. 3017 * @return The index where the strings begin to differ; -1 if they are all equal. 3018 * @since 2.4 3019 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 3020 */ 3021 public static int indexOfDifference(final CharSequence... css) { 3022 if (ArrayUtils.getLength(css) <= 1) { 3023 return INDEX_NOT_FOUND; 3024 } 3025 boolean anyStringNull = false; 3026 boolean allStringsNull = true; 3027 final int arrayLen = css.length; 3028 int shortestStrLen = Integer.MAX_VALUE; 3029 int longestStrLen = 0; 3030 // find the min and max string lengths; this avoids checking to make 3031 // sure we are not exceeding the length of the string each time through 3032 // the bottom loop. 3033 for (final CharSequence cs : css) { 3034 if (cs == null) { 3035 anyStringNull = true; 3036 shortestStrLen = 0; 3037 } else { 3038 allStringsNull = false; 3039 shortestStrLen = Math.min(cs.length(), shortestStrLen); 3040 longestStrLen = Math.max(cs.length(), longestStrLen); 3041 } 3042 } 3043 // handle lists containing all nulls or all empty strings 3044 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 3045 return INDEX_NOT_FOUND; 3046 } 3047 // handle lists containing some nulls or some empty strings 3048 if (shortestStrLen == 0) { 3049 return 0; 3050 } 3051 // find the position with the first difference across all strings 3052 int firstDiff = -1; 3053 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 3054 final char comparisonChar = css[0].charAt(stringPos); 3055 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3056 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3057 firstDiff = stringPos; 3058 break; 3059 } 3060 } 3061 if (firstDiff != -1) { 3062 break; 3063 } 3064 } 3065 if (firstDiff > 0 && Character.isLowSurrogate(css[0].charAt(firstDiff)) 3066 && Character.isHighSurrogate(css[0].charAt(firstDiff - 1))) { 3067 // the difference splits a surrogate pair whose high half is common; report the start of the 3068 // pair so getCommonPrefix never slices it in half and leaves a stray high surrogate. 3069 firstDiff--; 3070 } 3071 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3072 // we compared all of the characters up to the length of the 3073 // shortest string and didn't find a match, but the string lengths 3074 // vary, so return the length of the shortest string. 3075 return shortestStrLen; 3076 } 3077 return firstDiff; 3078 } 3079 3080 /** 3081 * Compares two CharSequences, and returns the index at which the CharSequences begin to differ. 3082 * 3083 * <p> 3084 * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7} 3085 * </p> 3086 * 3087 * <pre> 3088 * StringUtils.indexOfDifference(null, null) = -1 3089 * StringUtils.indexOfDifference("", "") = -1 3090 * StringUtils.indexOfDifference("", "abc") = 0 3091 * StringUtils.indexOfDifference("abc", "") = 0 3092 * StringUtils.indexOfDifference("abc", "abc") = -1 3093 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3094 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3095 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3096 * </pre> 3097 * 3098 * @param cs1 The first CharSequence, may be null. 3099 * @param cs2 The second CharSequence, may be null. 3100 * @return The index where cs1 and cs2 begin to differ; -1 if they are equal. 3101 * @since 2.0 3102 * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence) 3103 */ 3104 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3105 if (cs1 == cs2) { 3106 return INDEX_NOT_FOUND; 3107 } 3108 if (cs1 == null || cs2 == null) { 3109 return 0; 3110 } 3111 int i; 3112 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3113 if (cs1.charAt(i) != cs2.charAt(i)) { 3114 break; 3115 } 3116 } 3117 if (i > 0 && i < cs1.length() && i < cs2.length() && Character.isHighSurrogate(cs1.charAt(i - 1)) 3118 && (Character.isLowSurrogate(cs1.charAt(i)) || Character.isLowSurrogate(cs2.charAt(i)))) { 3119 // the difference splits a surrogate pair whose high half is common; report the start of the 3120 // pair so difference does not return a string that begins with a stray low surrogate. 3121 i--; 3122 } 3123 if (i < cs2.length() || i < cs1.length()) { 3124 return i; 3125 } 3126 return INDEX_NOT_FOUND; 3127 } 3128 3129 /** 3130 * Case insensitive find of the first index within a CharSequence. 3131 * 3132 * <p> 3133 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3134 * start position greater than the string length only matches an empty search CharSequence. 3135 * </p> 3136 * 3137 * <pre> 3138 * StringUtils.indexOfIgnoreCase(null, *) = -1 3139 * StringUtils.indexOfIgnoreCase(*, null) = -1 3140 * StringUtils.indexOfIgnoreCase("", "") = 0 3141 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3142 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3143 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3144 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3145 * </pre> 3146 * 3147 * @param str The CharSequence to check, may be null. 3148 * @param searchStr The CharSequence to find, may be null. 3149 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 3150 * @since 2.5 3151 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3152 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}. 3153 */ 3154 @Deprecated 3155 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3156 return Strings.CI.indexOf(str, searchStr); 3157 } 3158 3159 /** 3160 * Case insensitive find of the first index within a CharSequence from the specified position. 3161 * 3162 * <p> 3163 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3164 * start position greater than the string length only matches an empty search CharSequence. 3165 * </p> 3166 * 3167 * <pre> 3168 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3169 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3170 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3171 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3172 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3173 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3174 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3175 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3176 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3177 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3178 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3179 * </pre> 3180 * 3181 * @param str The CharSequence to check, may be null. 3182 * @param searchStr The CharSequence to find, may be null. 3183 * @param startPos The start position, negative treated as zero. 3184 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 3185 * @since 2.5 3186 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3187 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}. 3188 */ 3189 @Deprecated 3190 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 3191 return Strings.CI.indexOf(str, searchStr, startPos); 3192 } 3193 3194 /** 3195 * Tests if all of the CharSequences are empty (""), null or whitespace only. 3196 * 3197 * <p> 3198 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3199 * </p> 3200 * 3201 * <pre> 3202 * StringUtils.isAllBlank(null) = true 3203 * StringUtils.isAllBlank(null, "foo") = false 3204 * StringUtils.isAllBlank(null, null) = true 3205 * StringUtils.isAllBlank("", "bar") = false 3206 * StringUtils.isAllBlank("bob", "") = false 3207 * StringUtils.isAllBlank(" bob ", null) = false 3208 * StringUtils.isAllBlank(" ", "bar") = false 3209 * StringUtils.isAllBlank("foo", "bar") = false 3210 * StringUtils.isAllBlank(new String[] {}) = true 3211 * </pre> 3212 * 3213 * @param css The CharSequences to check, may be null or empty. 3214 * @return {@code true} if all of the CharSequences are empty or null or whitespace only. 3215 * @since 3.6 3216 */ 3217 public static boolean isAllBlank(final CharSequence... css) { 3218 if (ArrayUtils.isEmpty(css)) { 3219 return true; 3220 } 3221 for (final CharSequence cs : css) { 3222 if (isNotBlank(cs)) { 3223 return false; 3224 } 3225 } 3226 return true; 3227 } 3228 3229 /** 3230 * Tests if all of the CharSequences are empty ("") or null. 3231 * 3232 * <pre> 3233 * StringUtils.isAllEmpty(null) = true 3234 * StringUtils.isAllEmpty(null, "") = true 3235 * StringUtils.isAllEmpty(new String[] {}) = true 3236 * StringUtils.isAllEmpty(null, "foo") = false 3237 * StringUtils.isAllEmpty("", "bar") = false 3238 * StringUtils.isAllEmpty("bob", "") = false 3239 * StringUtils.isAllEmpty(" bob ", null) = false 3240 * StringUtils.isAllEmpty(" ", "bar") = false 3241 * StringUtils.isAllEmpty("foo", "bar") = false 3242 * </pre> 3243 * 3244 * @param css The CharSequences to check, may be null or empty. 3245 * @return {@code true} if all of the CharSequences are empty or null. 3246 * @since 3.6 3247 */ 3248 public static boolean isAllEmpty(final CharSequence... css) { 3249 if (ArrayUtils.isEmpty(css)) { 3250 return true; 3251 } 3252 for (final CharSequence cs : css) { 3253 if (isNotEmpty(cs)) { 3254 return false; 3255 } 3256 } 3257 return true; 3258 } 3259 3260 /** 3261 * Tests if the CharSequence contains only lowercase characters. 3262 * 3263 * <p> 3264 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3265 * </p> 3266 * 3267 * <pre> 3268 * StringUtils.isAllLowerCase(null) = false 3269 * StringUtils.isAllLowerCase("") = false 3270 * StringUtils.isAllLowerCase(" ") = false 3271 * StringUtils.isAllLowerCase("abc") = true 3272 * StringUtils.isAllLowerCase("abC") = false 3273 * StringUtils.isAllLowerCase("ab c") = false 3274 * StringUtils.isAllLowerCase("ab1c") = false 3275 * StringUtils.isAllLowerCase("ab/c") = false 3276 * </pre> 3277 * 3278 * @param cs The CharSequence to check, may be null. 3279 * @return {@code true} if only contains lowercase characters, and is non-null. 3280 * @since 2.5 3281 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3282 */ 3283 public static boolean isAllLowerCase(final CharSequence cs) { 3284 if (isEmpty(cs)) { 3285 return false; 3286 } 3287 final int sz = cs.length(); 3288 for (int i = 0; i < sz;) { 3289 final int codePoint = Character.codePointAt(cs, i); 3290 if (!Character.isLowerCase(codePoint)) { 3291 return false; 3292 } 3293 i += Character.charCount(codePoint); 3294 } 3295 return true; 3296 } 3297 3298 /** 3299 * Tests if the CharSequence contains only uppercase characters. 3300 * 3301 * <p> 3302 * {@code null} will return {@code false}. 3303 * An empty String (length()=0) will return {@code false}. 3304 * </p> 3305 * 3306 * <pre> 3307 * StringUtils.isAllUpperCase(null) = false 3308 * StringUtils.isAllUpperCase("") = false 3309 * StringUtils.isAllUpperCase(" ") = false 3310 * StringUtils.isAllUpperCase("ABC") = true 3311 * StringUtils.isAllUpperCase("aBC") = false 3312 * StringUtils.isAllUpperCase("A C") = false 3313 * StringUtils.isAllUpperCase("A1C") = false 3314 * StringUtils.isAllUpperCase("A/C") = false 3315 * </pre> 3316 * 3317 * @param cs The CharSequence to check, may be null. 3318 * @return {@code true} if only contains uppercase characters, and is non-null. 3319 * @since 2.5 3320 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3321 */ 3322 public static boolean isAllUpperCase(final CharSequence cs) { 3323 if (isEmpty(cs)) { 3324 return false; 3325 } 3326 final int sz = cs.length(); 3327 for (int i = 0; i < sz;) { 3328 final int codePoint = Character.codePointAt(cs, i); 3329 if (!Character.isUpperCase(codePoint)) { 3330 return false; 3331 } 3332 i += Character.charCount(codePoint); 3333 } 3334 return true; 3335 } 3336 3337 /** 3338 * Tests if the CharSequence contains only Unicode letters. 3339 * 3340 * <p> 3341 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3342 * </p> 3343 * 3344 * <pre> 3345 * StringUtils.isAlpha(null) = false 3346 * StringUtils.isAlpha("") = false 3347 * StringUtils.isAlpha(" ") = false 3348 * StringUtils.isAlpha("abc") = true 3349 * StringUtils.isAlpha("ab2c") = false 3350 * StringUtils.isAlpha("ab-c") = false 3351 * </pre> 3352 * 3353 * @param cs The CharSequence to check, may be null. 3354 * @return {@code true} if only contains letters, and is non-null. 3355 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3356 * @since 3.0 Changed "" to return false and not true 3357 */ 3358 public static boolean isAlpha(final CharSequence cs) { 3359 if (isEmpty(cs)) { 3360 return false; 3361 } 3362 final int sz = cs.length(); 3363 for (int i = 0; i < sz;) { 3364 final int codePoint = Character.codePointAt(cs, i); 3365 if (!Character.isLetter(codePoint)) { 3366 return false; 3367 } 3368 i += Character.charCount(codePoint); 3369 } 3370 return true; 3371 } 3372 3373 /** 3374 * Tests if the CharSequence contains only Unicode letters or digits. 3375 * 3376 * <p> 3377 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3378 * </p> 3379 * 3380 * <pre> 3381 * StringUtils.isAlphanumeric(null) = false 3382 * StringUtils.isAlphanumeric("") = false 3383 * StringUtils.isAlphanumeric(" ") = false 3384 * StringUtils.isAlphanumeric("abc") = true 3385 * StringUtils.isAlphanumeric("ab c") = false 3386 * StringUtils.isAlphanumeric("ab2c") = true 3387 * StringUtils.isAlphanumeric("ab-c") = false 3388 * </pre> 3389 * 3390 * @param cs The CharSequence to check, may be null. 3391 * @return {@code true} if only contains letters or digits, and is non-null. 3392 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3393 * @since 3.0 Changed "" to return false and not true 3394 */ 3395 public static boolean isAlphanumeric(final CharSequence cs) { 3396 if (isEmpty(cs)) { 3397 return false; 3398 } 3399 final int sz = cs.length(); 3400 for (int i = 0; i < sz;) { 3401 final int codePoint = Character.codePointAt(cs, i); 3402 if (!Character.isLetterOrDigit(codePoint)) { 3403 return false; 3404 } 3405 i += Character.charCount(codePoint); 3406 } 3407 return true; 3408 } 3409 3410 /** 3411 * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}). 3412 * 3413 * <p> 3414 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3415 * </p> 3416 * 3417 * <pre> 3418 * StringUtils.isAlphanumericSpace(null) = false 3419 * StringUtils.isAlphanumericSpace("") = true 3420 * StringUtils.isAlphanumericSpace(" ") = true 3421 * StringUtils.isAlphanumericSpace("abc") = true 3422 * StringUtils.isAlphanumericSpace("ab c") = true 3423 * StringUtils.isAlphanumericSpace("ab2c") = true 3424 * StringUtils.isAlphanumericSpace("ab-c") = false 3425 * </pre> 3426 * 3427 * @param cs The CharSequence to check, may be null. 3428 * @return {@code true} if only contains letters, digits or space, and is non-null. 3429 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3430 */ 3431 public static boolean isAlphanumericSpace(final CharSequence cs) { 3432 if (cs == null) { 3433 return false; 3434 } 3435 final int sz = cs.length(); 3436 for (int i = 0; i < sz;) { 3437 final int codePoint = Character.codePointAt(cs, i); 3438 if (codePoint != ' ' && !Character.isLetterOrDigit(codePoint)) { 3439 return false; 3440 } 3441 i += Character.charCount(codePoint); 3442 } 3443 return true; 3444 } 3445 3446 /** 3447 * Tests if the CharSequence contains only Unicode letters and space (' '). 3448 * 3449 * <p> 3450 * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}. 3451 * </p> 3452 * 3453 * <pre> 3454 * StringUtils.isAlphaSpace(null) = false 3455 * StringUtils.isAlphaSpace("") = true 3456 * StringUtils.isAlphaSpace(" ") = true 3457 * StringUtils.isAlphaSpace("abc") = true 3458 * StringUtils.isAlphaSpace("ab c") = true 3459 * StringUtils.isAlphaSpace("ab2c") = false 3460 * StringUtils.isAlphaSpace("ab-c") = false 3461 * </pre> 3462 * 3463 * @param cs The CharSequence to check, may be null. 3464 * @return {@code true} if only contains letters and space, and is non-null. 3465 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3466 */ 3467 public static boolean isAlphaSpace(final CharSequence cs) { 3468 if (cs == null) { 3469 return false; 3470 } 3471 final int sz = cs.length(); 3472 for (int i = 0; i < sz;) { 3473 final int codePoint = Character.codePointAt(cs, i); 3474 if (codePoint != ' ' && !Character.isLetter(codePoint)) { 3475 return false; 3476 } 3477 i += Character.charCount(codePoint); 3478 } 3479 return true; 3480 } 3481 3482 /** 3483 * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3484 * 3485 * <p> 3486 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3487 * </p> 3488 * 3489 * <pre> 3490 * StringUtils.isAnyBlank((String) null) = true 3491 * StringUtils.isAnyBlank((String[]) null) = false 3492 * StringUtils.isAnyBlank(null, "foo") = true 3493 * StringUtils.isAnyBlank(null, null) = true 3494 * StringUtils.isAnyBlank("", "bar") = true 3495 * StringUtils.isAnyBlank("bob", "") = true 3496 * StringUtils.isAnyBlank(" bob ", null) = true 3497 * StringUtils.isAnyBlank(" ", "bar") = true 3498 * StringUtils.isAnyBlank(new String[] {}) = false 3499 * StringUtils.isAnyBlank(new String[]{""}) = true 3500 * StringUtils.isAnyBlank("foo", "bar") = false 3501 * </pre> 3502 * 3503 * @param css The CharSequences to check, may be null or empty. 3504 * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3505 * @see #isBlank(CharSequence) 3506 * @since 3.2 3507 */ 3508 public static boolean isAnyBlank(final CharSequence... css) { 3509 if (ArrayUtils.isEmpty(css)) { 3510 return false; 3511 } 3512 for (final CharSequence cs : css) { 3513 if (isBlank(cs)) { 3514 return true; 3515 } 3516 } 3517 return false; 3518 } 3519 3520 /** 3521 * Tests if any of the CharSequences are empty ("") or null. 3522 * 3523 * <pre> 3524 * StringUtils.isAnyEmpty((String) null) = true 3525 * StringUtils.isAnyEmpty((String[]) null) = false 3526 * StringUtils.isAnyEmpty(null, "foo") = true 3527 * StringUtils.isAnyEmpty("", "bar") = true 3528 * StringUtils.isAnyEmpty("bob", "") = true 3529 * StringUtils.isAnyEmpty(" bob ", null) = true 3530 * StringUtils.isAnyEmpty(" ", "bar") = false 3531 * StringUtils.isAnyEmpty("foo", "bar") = false 3532 * StringUtils.isAnyEmpty(new String[]{}) = false 3533 * StringUtils.isAnyEmpty(new String[]{""}) = true 3534 * </pre> 3535 * 3536 * @param css The CharSequences to check, may be null or empty. 3537 * @return {@code true} if any of the CharSequences are empty or null. 3538 * @since 3.2 3539 */ 3540 public static boolean isAnyEmpty(final CharSequence... css) { 3541 if (ArrayUtils.isEmpty(css)) { 3542 return false; 3543 } 3544 for (final CharSequence cs : css) { 3545 if (isEmpty(cs)) { 3546 return true; 3547 } 3548 } 3549 return false; 3550 } 3551 3552 /** 3553 * Tests if the CharSequence contains only ASCII printable characters. 3554 * 3555 * <p> 3556 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3557 * </p> 3558 * 3559 * <pre> 3560 * StringUtils.isAsciiPrintable(null) = false 3561 * StringUtils.isAsciiPrintable("") = true 3562 * StringUtils.isAsciiPrintable(" ") = true 3563 * StringUtils.isAsciiPrintable("Ceki") = true 3564 * StringUtils.isAsciiPrintable("ab2c") = true 3565 * StringUtils.isAsciiPrintable("!ab-c~") = true 3566 * StringUtils.isAsciiPrintable("\u0020") = true 3567 * StringUtils.isAsciiPrintable("\u0021") = true 3568 * StringUtils.isAsciiPrintable("\u007e") = true 3569 * StringUtils.isAsciiPrintable("\u007f") = false 3570 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3571 * </pre> 3572 * 3573 * @param cs The CharSequence to check, may be null. 3574 * @return {@code true} if every character is in the range 32 through 126. 3575 * @since 2.1 3576 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3577 */ 3578 public static boolean isAsciiPrintable(final CharSequence cs) { 3579 if (cs == null) { 3580 return false; 3581 } 3582 final int sz = cs.length(); 3583 for (int i = 0; i < sz; i++) { 3584 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3585 return false; 3586 } 3587 } 3588 return true; 3589 } 3590 3591 /** 3592 * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}. 3593 * 3594 * <pre> 3595 * StringUtils.isBlank(null) = true 3596 * StringUtils.isBlank("") = true 3597 * StringUtils.isBlank(" ") = true 3598 * StringUtils.isBlank("bob") = false 3599 * StringUtils.isBlank(" bob ") = false 3600 * </pre> 3601 * 3602 * @param cs The CharSequence to check, may be null. 3603 * @return {@code true} if the CharSequence is null, empty or whitespace only. 3604 * @since 2.0 3605 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3606 */ 3607 public static boolean isBlank(final CharSequence cs) { 3608 final int strLen = length(cs); 3609 for (int i = 0; i < strLen; i++) { 3610 if (!Character.isWhitespace(cs.charAt(i))) { 3611 return false; 3612 } 3613 } 3614 return true; 3615 } 3616 3617 /** 3618 * Tests if a CharSequence is empty ("") or null. 3619 * 3620 * <pre> 3621 * StringUtils.isEmpty(null) = true 3622 * StringUtils.isEmpty("") = true 3623 * StringUtils.isEmpty(" ") = false 3624 * StringUtils.isEmpty("bob") = false 3625 * StringUtils.isEmpty(" bob ") = false 3626 * </pre> 3627 * 3628 * <p> 3629 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank(). 3630 * </p> 3631 * 3632 * @param cs The CharSequence to check, may be null. 3633 * @return {@code true} if the CharSequence is empty or null. 3634 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3635 */ 3636 public static boolean isEmpty(final CharSequence cs) { 3637 return cs == null || cs.length() == 0; 3638 } 3639 3640 /** 3641 * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3642 * 3643 * <p> 3644 * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}. 3645 * </p> 3646 * 3647 * <pre> 3648 * StringUtils.isMixedCase(null) = false 3649 * StringUtils.isMixedCase("") = false 3650 * StringUtils.isMixedCase(" ") = false 3651 * StringUtils.isMixedCase("ABC") = false 3652 * StringUtils.isMixedCase("abc") = false 3653 * StringUtils.isMixedCase("aBc") = true 3654 * StringUtils.isMixedCase("A c") = true 3655 * StringUtils.isMixedCase("A1c") = true 3656 * StringUtils.isMixedCase("a/C") = true 3657 * StringUtils.isMixedCase("aC\t") = true 3658 * </pre> 3659 * 3660 * @param cs The CharSequence to check, may be null. 3661 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters. 3662 * @since 3.5 3663 */ 3664 public static boolean isMixedCase(final CharSequence cs) { 3665 if (isEmpty(cs) || cs.length() == 1) { 3666 return false; 3667 } 3668 boolean containsUppercase = false; 3669 boolean containsLowercase = false; 3670 final int sz = cs.length(); 3671 for (int i = 0; i < sz;) { 3672 final int codePoint = Character.codePointAt(cs, i); 3673 if (Character.isUpperCase(codePoint)) { 3674 containsUppercase = true; 3675 } else if (Character.isLowerCase(codePoint)) { 3676 containsLowercase = true; 3677 } 3678 if (containsUppercase && containsLowercase) { 3679 return true; 3680 } 3681 i += Character.charCount(codePoint); 3682 } 3683 return false; 3684 } 3685 3686 /** 3687 * Tests if none of the CharSequences are empty (""), null or whitespace only. 3688 * 3689 * <p> 3690 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3691 * </p> 3692 * 3693 * <pre> 3694 * StringUtils.isNoneBlank((String) null) = false 3695 * StringUtils.isNoneBlank((String[]) null) = true 3696 * StringUtils.isNoneBlank(null, "foo") = false 3697 * StringUtils.isNoneBlank(null, null) = false 3698 * StringUtils.isNoneBlank("", "bar") = false 3699 * StringUtils.isNoneBlank("bob", "") = false 3700 * StringUtils.isNoneBlank(" bob ", null) = false 3701 * StringUtils.isNoneBlank(" ", "bar") = false 3702 * StringUtils.isNoneBlank(new String[] {}) = true 3703 * StringUtils.isNoneBlank(new String[]{""}) = false 3704 * StringUtils.isNoneBlank("foo", "bar") = true 3705 * </pre> 3706 * 3707 * @param css The CharSequences to check, may be null or empty. 3708 * @return {@code true} if none of the CharSequences are empty or null or whitespace only. 3709 * @since 3.2 3710 */ 3711 public static boolean isNoneBlank(final CharSequence... css) { 3712 return !isAnyBlank(css); 3713 } 3714 3715 /** 3716 * Tests if none of the CharSequences are empty ("") or null. 3717 * 3718 * <pre> 3719 * StringUtils.isNoneEmpty((String) null) = false 3720 * StringUtils.isNoneEmpty((String[]) null) = true 3721 * StringUtils.isNoneEmpty(null, "foo") = false 3722 * StringUtils.isNoneEmpty("", "bar") = false 3723 * StringUtils.isNoneEmpty("bob", "") = false 3724 * StringUtils.isNoneEmpty(" bob ", null) = false 3725 * StringUtils.isNoneEmpty(new String[] {}) = true 3726 * StringUtils.isNoneEmpty(new String[]{""}) = false 3727 * StringUtils.isNoneEmpty(" ", "bar") = true 3728 * StringUtils.isNoneEmpty("foo", "bar") = true 3729 * </pre> 3730 * 3731 * @param css The CharSequences to check, may be null or empty. 3732 * @return {@code true} if none of the CharSequences are empty or null. 3733 * @since 3.2 3734 */ 3735 public static boolean isNoneEmpty(final CharSequence... css) { 3736 return !isAnyEmpty(css); 3737 } 3738 3739 /** 3740 * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3741 * 3742 * <p> 3743 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3744 * </p> 3745 * 3746 * <pre> 3747 * StringUtils.isNotBlank(null) = false 3748 * StringUtils.isNotBlank("") = false 3749 * StringUtils.isNotBlank(" ") = false 3750 * StringUtils.isNotBlank("bob") = true 3751 * StringUtils.isNotBlank(" bob ") = true 3752 * </pre> 3753 * 3754 * @param cs The CharSequence to check, may be null. 3755 * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3756 * @see #isBlank(CharSequence) 3757 * @since 2.0 3758 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3759 */ 3760 public static boolean isNotBlank(final CharSequence cs) { 3761 return !isBlank(cs); 3762 } 3763 3764 /** 3765 * Tests if a CharSequence is not empty ("") and not null. 3766 * 3767 * <pre> 3768 * StringUtils.isNotEmpty(null) = false 3769 * StringUtils.isNotEmpty("") = false 3770 * StringUtils.isNotEmpty(" ") = true 3771 * StringUtils.isNotEmpty("bob") = true 3772 * StringUtils.isNotEmpty(" bob ") = true 3773 * </pre> 3774 * 3775 * @param cs The CharSequence to check, may be null. 3776 * @return {@code true} if the CharSequence is not empty and not null. 3777 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3778 */ 3779 public static boolean isNotEmpty(final CharSequence cs) { 3780 return !isEmpty(cs); 3781 } 3782 3783 /** 3784 * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false. 3785 * 3786 * <p> 3787 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3788 * </p> 3789 * 3790 * <p> 3791 * 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 3792 * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively. 3793 * </p> 3794 * 3795 * <pre> 3796 * StringUtils.isNumeric(null) = false 3797 * StringUtils.isNumeric("") = false 3798 * StringUtils.isNumeric(" ") = false 3799 * StringUtils.isNumeric("123") = true 3800 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3801 * StringUtils.isNumeric("12 3") = false 3802 * StringUtils.isNumeric("ab2c") = false 3803 * StringUtils.isNumeric("12-3") = false 3804 * StringUtils.isNumeric("12.3") = false 3805 * StringUtils.isNumeric("-123") = false 3806 * StringUtils.isNumeric("+123") = false 3807 * </pre> 3808 * 3809 * @param cs The CharSequence to check, may be null. 3810 * @return {@code true} if only contains digits, and is non-null. 3811 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3812 * @since 3.0 Changed "" to return false and not true 3813 */ 3814 public static boolean isNumeric(final CharSequence cs) { 3815 if (isEmpty(cs)) { 3816 return false; 3817 } 3818 final int sz = cs.length(); 3819 for (int i = 0; i < sz;) { 3820 final int codePoint = Character.codePointAt(cs, i); 3821 if (!Character.isDigit(codePoint)) { 3822 return false; 3823 } 3824 i += Character.charCount(codePoint); 3825 } 3826 return true; 3827 } 3828 3829 /** 3830 * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false. 3831 * 3832 * <p> 3833 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3834 * </p> 3835 * 3836 * <pre> 3837 * StringUtils.isNumericSpace(null) = false 3838 * StringUtils.isNumericSpace("") = true 3839 * StringUtils.isNumericSpace(" ") = true 3840 * StringUtils.isNumericSpace("123") = true 3841 * StringUtils.isNumericSpace("12 3") = true 3842 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3843 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3844 * StringUtils.isNumericSpace("ab2c") = false 3845 * StringUtils.isNumericSpace("12-3") = false 3846 * StringUtils.isNumericSpace("12.3") = false 3847 * </pre> 3848 * 3849 * @param cs The CharSequence to check, may be null. 3850 * @return {@code true} if only contains digits or space, and is non-null. 3851 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3852 */ 3853 public static boolean isNumericSpace(final CharSequence cs) { 3854 if (cs == null) { 3855 return false; 3856 } 3857 final int sz = cs.length(); 3858 for (int i = 0; i < sz;) { 3859 final int codePoint = Character.codePointAt(cs, i); 3860 if (codePoint != ' ' && !Character.isDigit(codePoint)) { 3861 return false; 3862 } 3863 i += Character.charCount(codePoint); 3864 } 3865 return true; 3866 } 3867 3868 /** 3869 * Tests if the CharSequence contains only whitespace. 3870 * 3871 * <p> 3872 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3873 * </p> 3874 * 3875 * <p> 3876 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3877 * </p> 3878 * 3879 * <pre> 3880 * StringUtils.isWhitespace(null) = false 3881 * StringUtils.isWhitespace("") = true 3882 * StringUtils.isWhitespace(" ") = true 3883 * StringUtils.isWhitespace("abc") = false 3884 * StringUtils.isWhitespace("ab2c") = false 3885 * StringUtils.isWhitespace("ab-c") = false 3886 * </pre> 3887 * 3888 * @param cs The CharSequence to check, may be null. 3889 * @return {@code true} if only contains whitespace, and is non-null. 3890 * @since 2.0 3891 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3892 */ 3893 public static boolean isWhitespace(final CharSequence cs) { 3894 if (cs == null) { 3895 return false; 3896 } 3897 final int sz = cs.length(); 3898 for (int i = 0; i < sz; i++) { 3899 if (!Character.isWhitespace(cs.charAt(i))) { 3900 return false; 3901 } 3902 } 3903 return true; 3904 } 3905 3906 /** 3907 * Joins the elements of the provided array into a single String containing the provided list of elements. 3908 * 3909 * <p> 3910 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 3911 * </p> 3912 * 3913 * <pre> 3914 * StringUtils.join(null, *) = null 3915 * StringUtils.join([], *) = "" 3916 * StringUtils.join([null], *) = "" 3917 * StringUtils.join([false, false], ';') = "false;false" 3918 * </pre> 3919 * 3920 * @param array The array of values to join together, may be null. 3921 * @param delimiter The separator character to use. 3922 * @return The joined String, {@code null} if null array input. 3923 * @since 3.12.0 3924 */ 3925 public static String join(final boolean[] array, final char delimiter) { 3926 if (array == null) { 3927 return null; 3928 } 3929 return join(array, delimiter, 0, array.length); 3930 } 3931 3932 /** 3933 * Joins the elements of the provided array into a single String containing the provided list of elements. 3934 * 3935 * <p> 3936 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3937 * by empty strings. 3938 * </p> 3939 * 3940 * <pre> 3941 * StringUtils.join(null, *) = null 3942 * StringUtils.join([], *) = "" 3943 * StringUtils.join([null], *) = "" 3944 * StringUtils.join([true, false, true], ';') = "true;false;true" 3945 * </pre> 3946 * 3947 * @param array 3948 * the array of values to join together, may be null. 3949 * @param delimiter 3950 * the separator character to use. 3951 * @param startIndex 3952 * the first index to start joining from. It is an error to pass in a start index past the end of the 3953 * array. 3954 * @param endIndex 3955 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3956 * the array. 3957 * @return The joined String, {@code null} if null array input. 3958 * @since 3.12.0 3959 */ 3960 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3961 // See StringUtilsJoinBenchmark 3962 if (array == null) { 3963 return null; 3964 } 3965 checkFromToIndex(startIndex, endIndex, array.length); 3966 final int count = endIndex - startIndex; 3967 if (count <= 0) { 3968 return EMPTY; 3969 } 3970 final byte maxElementChars = 5; // "false" 3971 final StringBuilder stringBuilder = capacity(count, maxElementChars); 3972 stringBuilder.append(array[startIndex]); 3973 for (int i = startIndex + 1; i < endIndex; i++) { 3974 stringBuilder.append(delimiter).append(array[i]); 3975 } 3976 return stringBuilder.toString(); 3977 } 3978 3979 /** 3980 * Joins the elements of the provided array into a single String containing the provided list of elements. 3981 * 3982 * <p> 3983 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3984 * by empty strings. 3985 * </p> 3986 * 3987 * <pre> 3988 * StringUtils.join(null, *) = null 3989 * StringUtils.join([], *) = "" 3990 * StringUtils.join([null], *) = "" 3991 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3992 * StringUtils.join([1, 2, 3], null) = "123" 3993 * </pre> 3994 * 3995 * @param array 3996 * the array of values to join together, may be null. 3997 * @param delimiter 3998 * the separator character to use. 3999 * @return The joined String, {@code null} if null array input. 4000 * @since 3.2 4001 */ 4002 public static String join(final byte[] array, final char delimiter) { 4003 if (array == null) { 4004 return null; 4005 } 4006 return join(array, delimiter, 0, array.length); 4007 } 4008 4009 /** 4010 * Joins the elements of the provided array into a single String containing the provided list of elements. 4011 * 4012 * <p> 4013 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4014 * by empty strings. 4015 * </p> 4016 * 4017 * <pre> 4018 * StringUtils.join(null, *) = null 4019 * StringUtils.join([], *) = "" 4020 * StringUtils.join([null], *) = "" 4021 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4022 * StringUtils.join([1, 2, 3], null) = "123" 4023 * </pre> 4024 * 4025 * @param array 4026 * the array of values to join together, may be null. 4027 * @param delimiter 4028 * the separator character to use. 4029 * @param startIndex 4030 * the first index to start joining from. It is an error to pass in a start index past the end of the 4031 * array. 4032 * @param endIndex 4033 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4034 * the array. 4035 * @return The joined String, {@code null} if null array input. 4036 * @since 3.2 4037 */ 4038 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 4039 // See StringUtilsJoinBenchmark 4040 if (array == null) { 4041 return null; 4042 } 4043 checkFromToIndex(startIndex, endIndex, array.length); 4044 final int count = endIndex - startIndex; 4045 if (count <= 0) { 4046 return EMPTY; 4047 } 4048 final byte maxElementChars = 4; // "-128" 4049 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4050 stringBuilder.append(array[startIndex]); 4051 for (int i = startIndex + 1; i < endIndex; i++) { 4052 stringBuilder.append(delimiter).append(array[i]); 4053 } 4054 return stringBuilder.toString(); 4055 } 4056 4057 /** 4058 * Joins the elements of the provided array into a single String containing the provided list of elements. 4059 * 4060 * <p> 4061 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4062 * by empty strings. 4063 * </p> 4064 * 4065 * <pre> 4066 * StringUtils.join(null, *) = null 4067 * StringUtils.join([], *) = "" 4068 * StringUtils.join([null], *) = "" 4069 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4070 * StringUtils.join([1, 2, 3], null) = "123" 4071 * </pre> 4072 * 4073 * @param array 4074 * the array of values to join together, may be null. 4075 * @param delimiter 4076 * the separator character to use. 4077 * @return The joined String, {@code null} if null array input. 4078 * @since 3.2 4079 */ 4080 public static String join(final char[] array, final char delimiter) { 4081 if (array == null) { 4082 return null; 4083 } 4084 return join(array, delimiter, 0, array.length); 4085 } 4086 4087 /** 4088 * Joins the elements of the provided array into a single String containing the provided list of elements. 4089 * 4090 * <p> 4091 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4092 * by empty strings. 4093 * </p> 4094 * 4095 * <pre> 4096 * StringUtils.join(null, *) = null 4097 * StringUtils.join([], *) = "" 4098 * StringUtils.join([null], *) = "" 4099 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4100 * StringUtils.join([1, 2, 3], null) = "123" 4101 * </pre> 4102 * 4103 * @param array 4104 * the array of values to join together, may be null. 4105 * @param delimiter 4106 * the separator character to use. 4107 * @param startIndex 4108 * the first index to start joining from. It is an error to pass in a start index past the end of the 4109 * array. 4110 * @param endIndex 4111 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4112 * the array. 4113 * @return The joined String, {@code null} if null array input. 4114 * @since 3.2 4115 */ 4116 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4117 // See StringUtilsJoinBenchmark 4118 if (array == null) { 4119 return null; 4120 } 4121 checkFromToIndex(startIndex, endIndex, array.length); 4122 final int count = endIndex - startIndex; 4123 if (count <= 0) { 4124 return EMPTY; 4125 } 4126 final byte maxElementChars = 1; 4127 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4128 stringBuilder.append(array[startIndex]); 4129 for (int i = startIndex + 1; i < endIndex; i++) { 4130 stringBuilder.append(delimiter).append(array[i]); 4131 } 4132 return stringBuilder.toString(); 4133 } 4134 4135 /** 4136 * Joins the elements of the provided array into a single String containing the provided list of elements. 4137 * 4138 * <p> 4139 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4140 * by empty strings. 4141 * </p> 4142 * 4143 * <pre> 4144 * StringUtils.join(null, *) = null 4145 * StringUtils.join([], *) = "" 4146 * StringUtils.join([null], *) = "" 4147 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4148 * StringUtils.join([1, 2, 3], null) = "123" 4149 * </pre> 4150 * 4151 * @param array 4152 * the array of values to join together, may be null. 4153 * @param delimiter 4154 * the separator character to use. 4155 * @return The joined String, {@code null} if null array input. 4156 * @since 3.2 4157 */ 4158 public static String join(final double[] array, final char delimiter) { 4159 if (array == null) { 4160 return null; 4161 } 4162 return join(array, delimiter, 0, array.length); 4163 } 4164 4165 /** 4166 * Joins the elements of the provided array into a single String containing the provided list of elements. 4167 * 4168 * <p> 4169 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4170 * by empty strings. 4171 * </p> 4172 * 4173 * <pre> 4174 * StringUtils.join(null, *) = null 4175 * StringUtils.join([], *) = "" 4176 * StringUtils.join([null], *) = "" 4177 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4178 * StringUtils.join([1, 2, 3], null) = "123" 4179 * </pre> 4180 * 4181 * @param array 4182 * the array of values to join together, may be null. 4183 * @param delimiter 4184 * the separator character to use. 4185 * @param startIndex 4186 * the first index to start joining from. It is an error to pass in a start index past the end of the 4187 * array. 4188 * @param endIndex 4189 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4190 * the array. 4191 * @return The joined String, {@code null} if null array input. 4192 * @since 3.2 4193 */ 4194 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4195 // See StringUtilsJoinBenchmark 4196 if (array == null) { 4197 return null; 4198 } 4199 checkFromToIndex(startIndex, endIndex, array.length); 4200 final int count = endIndex - startIndex; 4201 if (count <= 0) { 4202 return EMPTY; 4203 } 4204 final byte maxElementChars = 22; // "1.7976931348623157E308" 4205 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4206 stringBuilder.append(array[startIndex]); 4207 for (int i = startIndex + 1; i < endIndex; i++) { 4208 stringBuilder.append(delimiter).append(array[i]); 4209 } 4210 return stringBuilder.toString(); 4211 } 4212 4213 /** 4214 * Joins the elements of the provided array into a single String containing the provided list of elements. 4215 * 4216 * <p> 4217 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4218 * by empty strings. 4219 * </p> 4220 * 4221 * <pre> 4222 * StringUtils.join(null, *) = null 4223 * StringUtils.join([], *) = "" 4224 * StringUtils.join([null], *) = "" 4225 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4226 * StringUtils.join([1, 2, 3], null) = "123" 4227 * </pre> 4228 * 4229 * @param array 4230 * the array of values to join together, may be null. 4231 * @param delimiter 4232 * the separator character to use. 4233 * @return The joined String, {@code null} if null array input 4234 * @since 3.2 4235 */ 4236 public static String join(final float[] array, final char delimiter) { 4237 if (array == null) { 4238 return null; 4239 } 4240 return join(array, delimiter, 0, array.length); 4241 } 4242 4243 /** 4244 * Joins the elements of the provided array into a single String containing the provided list of elements. 4245 * 4246 * <p> 4247 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4248 * by empty strings. 4249 * </p> 4250 * 4251 * <pre> 4252 * StringUtils.join(null, *) = null 4253 * StringUtils.join([], *) = "" 4254 * StringUtils.join([null], *) = "" 4255 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4256 * StringUtils.join([1, 2, 3], null) = "123" 4257 * </pre> 4258 * 4259 * @param array 4260 * the array of values to join together, may be null. 4261 * @param delimiter 4262 * the separator character to use. 4263 * @param startIndex 4264 * the first index to start joining from. It is an error to pass in a start index past the end of the 4265 * array. 4266 * @param endIndex 4267 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4268 * the array. 4269 * @return The joined String, {@code null} if null array input. 4270 * @since 3.2 4271 */ 4272 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4273 // See StringUtilsJoinBenchmark 4274 if (array == null) { 4275 return null; 4276 } 4277 checkFromToIndex(startIndex, endIndex, array.length); 4278 final int count = endIndex - startIndex; 4279 if (count <= 0) { 4280 return EMPTY; 4281 } 4282 final byte maxElementChars = 12; // "3.4028235E38" 4283 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4284 stringBuilder.append(array[startIndex]); 4285 for (int i = startIndex + 1; i < endIndex; i++) { 4286 stringBuilder.append(delimiter).append(array[i]); 4287 } 4288 return stringBuilder.toString(); 4289 } 4290 4291 /** 4292 * Joins the elements of the provided array into a single String containing the provided list of elements. 4293 * 4294 * <p> 4295 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4296 * by empty strings. 4297 * </p> 4298 * 4299 * <pre> 4300 * StringUtils.join(null, *) = null 4301 * StringUtils.join([], *) = "" 4302 * StringUtils.join([null], *) = "" 4303 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4304 * StringUtils.join([1, 2, 3], null) = "123" 4305 * </pre> 4306 * 4307 * @param array 4308 * the array of values to join together, may be null. 4309 * @param separator 4310 * the separator character to use. 4311 * @return The joined String, {@code null} if null array input. 4312 * @since 3.2 4313 */ 4314 public static String join(final int[] array, final char separator) { 4315 if (array == null) { 4316 return null; 4317 } 4318 return join(array, separator, 0, array.length); 4319 } 4320 4321 /** 4322 * Joins the elements of the provided array into a single String containing the provided list of elements. 4323 * 4324 * <p> 4325 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4326 * by empty strings. 4327 * </p> 4328 * 4329 * <pre> 4330 * StringUtils.join(null, *) = null 4331 * StringUtils.join([], *) = "" 4332 * StringUtils.join([null], *) = "" 4333 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4334 * StringUtils.join([1, 2, 3], null) = "123" 4335 * </pre> 4336 * 4337 * @param array 4338 * the array of values to join together, may be null. 4339 * @param delimiter 4340 * the separator character to use. 4341 * @param startIndex 4342 * the first index to start joining from. It is an error to pass in a start index past the end of the 4343 * array. 4344 * @param endIndex 4345 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4346 * the array. 4347 * @return The joined String, {@code null} if null array input. 4348 * @since 3.2 4349 */ 4350 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4351 // See StringUtilsJoinBenchmark 4352 if (array == null) { 4353 return null; 4354 } 4355 checkFromToIndex(startIndex, endIndex, array.length); 4356 final int count = endIndex - startIndex; 4357 if (count <= 0) { 4358 return EMPTY; 4359 } 4360 final byte maxElementChars = 11; // "-2147483648" 4361 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4362 stringBuilder.append(array[startIndex]); 4363 for (int i = startIndex + 1; i < endIndex; i++) { 4364 stringBuilder.append(delimiter).append(array[i]); 4365 } 4366 return stringBuilder.toString(); 4367 } 4368 4369 /** 4370 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4371 * 4372 * <p> 4373 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4374 * </p> 4375 * 4376 * <p> 4377 * See the examples here: {@link #join(Object[],char)}. 4378 * </p> 4379 * 4380 * @param iterable The {@link Iterable} providing the values to join together, may be null. 4381 * @param separator The separator character to use. 4382 * @return The joined String, {@code null} if null iterator input. 4383 * @since 2.3 4384 */ 4385 public static String join(final Iterable<?> iterable, final char separator) { 4386 return iterable != null ? join(iterable.iterator(), separator) : null; 4387 } 4388 4389 /** 4390 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4391 * 4392 * <p> 4393 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4394 * </p> 4395 * 4396 * <p> 4397 * See the examples here: {@link #join(Object[],String)}. 4398 * </p> 4399 * 4400 * @param iterable The {@link Iterable} providing the values to join together, may be null. 4401 * @param separator The separator character to use, null treated as "". 4402 * @return The joined String, {@code null} if null iterator input. 4403 * @since 2.3 4404 */ 4405 public static String join(final Iterable<?> iterable, final String separator) { 4406 return iterable != null ? join(iterable.iterator(), separator) : null; 4407 } 4408 4409 /** 4410 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4411 * 4412 * <p> 4413 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4414 * </p> 4415 * 4416 * <p> 4417 * See the examples here: {@link #join(Object[],char)}. 4418 * </p> 4419 * 4420 * @param iterator The {@link Iterator} of values to join together, may be null. 4421 * @param separator The separator character to use. 4422 * @return The joined String, {@code null} if null iterator input. 4423 * @since 2.0 4424 */ 4425 public static String join(final Iterator<?> iterator, final char separator) { 4426 // handle null, zero and one elements before building a buffer 4427 if (iterator == null) { 4428 return null; 4429 } 4430 if (!iterator.hasNext()) { 4431 return EMPTY; 4432 } 4433 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString)); 4434 } 4435 4436 /** 4437 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4438 * 4439 * <p> 4440 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4441 * </p> 4442 * 4443 * <p> 4444 * See the examples here: {@link #join(Object[],String)}. 4445 * </p> 4446 * 4447 * @param iterator The {@link Iterator} of values to join together, may be null. 4448 * @param separator The separator character to use, null treated as "". 4449 * @return The joined String, {@code null} if null iterator input. 4450 */ 4451 public static String join(final Iterator<?> iterator, final String separator) { 4452 // handle null, zero and one elements before building a buffer 4453 if (iterator == null) { 4454 return null; 4455 } 4456 if (!iterator.hasNext()) { 4457 return EMPTY; 4458 } 4459 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString)); 4460 } 4461 4462 /** 4463 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4464 * 4465 * <p> 4466 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4467 * </p> 4468 * 4469 * <pre> 4470 * StringUtils.join(null, *) = null 4471 * StringUtils.join([], *) = "" 4472 * StringUtils.join([null], *) = "" 4473 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4474 * StringUtils.join(["a", "b", "c"], null) = "abc" 4475 * StringUtils.join([null, "", "a"], ';') = ";;a" 4476 * </pre> 4477 * 4478 * @param list The {@link List} of values to join together, may be null. 4479 * @param separator The separator character to use. 4480 * @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. 4481 * @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. 4482 * @return The joined String, {@code null} if null list input. 4483 * @since 3.8 4484 */ 4485 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4486 if (list == null) { 4487 return null; 4488 } 4489 final int noOfItems = endIndex - startIndex; 4490 if (noOfItems <= 0) { 4491 return EMPTY; 4492 } 4493 final List<?> subList = list.subList(startIndex, endIndex); 4494 return join(subList.iterator(), separator); 4495 } 4496 4497 /** 4498 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4499 * 4500 * <p> 4501 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4502 * </p> 4503 * 4504 * <pre> 4505 * StringUtils.join(null, *) = null 4506 * StringUtils.join([], *) = "" 4507 * StringUtils.join([null], *) = "" 4508 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4509 * StringUtils.join(["a", "b", "c"], null) = "abc" 4510 * StringUtils.join([null, "", "a"], ';') = ";;a" 4511 * </pre> 4512 * 4513 * @param list The {@link List} of values to join together, may be null. 4514 * @param separator The separator character to use. 4515 * @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. 4516 * @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. 4517 * @return The joined String, {@code null} if null list input. 4518 * @since 3.8 4519 */ 4520 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4521 if (list == null) { 4522 return null; 4523 } 4524 final int noOfItems = endIndex - startIndex; 4525 if (noOfItems <= 0) { 4526 return EMPTY; 4527 } 4528 final List<?> subList = list.subList(startIndex, endIndex); 4529 return join(subList.iterator(), separator); 4530 } 4531 4532 /** 4533 * Joins the elements of the provided array into a single String containing the provided list of elements. 4534 * 4535 * <p> 4536 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4537 * by empty strings. 4538 * </p> 4539 * 4540 * <pre> 4541 * StringUtils.join(null, *) = null 4542 * StringUtils.join([], *) = "" 4543 * StringUtils.join([null], *) = "" 4544 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4545 * StringUtils.join([1, 2, 3], null) = "123" 4546 * </pre> 4547 * 4548 * @param array 4549 * the array of values to join together, may be null. 4550 * @param separator 4551 * the separator character to use. 4552 * @return The joined String, {@code null} if null array input. 4553 * @since 3.2 4554 */ 4555 public static String join(final long[] array, final char separator) { 4556 if (array == null) { 4557 return null; 4558 } 4559 return join(array, separator, 0, array.length); 4560 } 4561 4562 /** 4563 * Joins the elements of the provided array into a single String containing the provided list of elements. 4564 * 4565 * <p> 4566 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4567 * by empty strings. 4568 * </p> 4569 * 4570 * <pre> 4571 * StringUtils.join(null, *) = null 4572 * StringUtils.join([], *) = "" 4573 * StringUtils.join([null], *) = "" 4574 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4575 * StringUtils.join([1, 2, 3], null) = "123" 4576 * </pre> 4577 * 4578 * @param array 4579 * the array of values to join together, may be null. 4580 * @param delimiter 4581 * the separator character to use. 4582 * @param startIndex 4583 * the first index to start joining from. It is an error to pass in a start index past the end of the 4584 * array. 4585 * @param endIndex 4586 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4587 * the array. 4588 * @return The joined String, {@code null} if null array input. 4589 * @since 3.2 4590 */ 4591 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4592 // See StringUtilsJoinBenchmark 4593 if (array == null) { 4594 return null; 4595 } 4596 checkFromToIndex(startIndex, endIndex, array.length); 4597 final int count = endIndex - startIndex; 4598 if (count <= 0) { 4599 return EMPTY; 4600 } 4601 final byte maxElementChars = 20; // "-9223372036854775808" 4602 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4603 stringBuilder.append(array[startIndex]); 4604 for (int i = startIndex + 1; i < endIndex; i++) { 4605 stringBuilder.append(delimiter).append(array[i]); 4606 } 4607 return stringBuilder.toString(); 4608 } 4609 4610 /** 4611 * Joins the elements of the provided array into a single String containing the provided list of elements. 4612 * 4613 * <p> 4614 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4615 * </p> 4616 * 4617 * <pre> 4618 * StringUtils.join(null, *) = null 4619 * StringUtils.join([], *) = "" 4620 * StringUtils.join([null], *) = "" 4621 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4622 * StringUtils.join(["a", "b", "c"], null) = "abc" 4623 * StringUtils.join([null, "", "a"], ';') = ";;a" 4624 * </pre> 4625 * 4626 * @param array The array of values to join together, may be null. 4627 * @param delimiter The separator character to use. 4628 * @return The joined String, {@code null} if null array input. 4629 * @since 2.0 4630 */ 4631 public static String join(final Object[] array, final char delimiter) { 4632 if (array == null) { 4633 return null; 4634 } 4635 return join(array, delimiter, 0, array.length); 4636 } 4637 4638 /** 4639 * Joins the elements of the provided array into a single String containing the provided list of elements. 4640 * 4641 * <p> 4642 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4643 * </p> 4644 * 4645 * <pre> 4646 * StringUtils.join(null, *) = null 4647 * StringUtils.join([], *) = "" 4648 * StringUtils.join([null], *) = "" 4649 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4650 * StringUtils.join(["a", "b", "c"], null) = "abc" 4651 * StringUtils.join([null, "", "a"], ';') = ";;a" 4652 * </pre> 4653 * 4654 * @param array The array of values to join together, may be null. 4655 * @param delimiter The separator character to use. 4656 * @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. 4657 * @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. 4658 * @return The joined String, {@code null} if null array input. 4659 * @since 2.0 4660 */ 4661 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4662 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4663 } 4664 4665 /** 4666 * Joins the elements of the provided array into a single String containing the provided list of elements. 4667 * 4668 * <p> 4669 * 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 4670 * array are represented by empty strings. 4671 * </p> 4672 * 4673 * <pre> 4674 * StringUtils.join(null, *) = null 4675 * StringUtils.join([], *) = "" 4676 * StringUtils.join([null], *) = "" 4677 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4678 * StringUtils.join(["a", "b", "c"], null) = "abc" 4679 * StringUtils.join(["a", "b", "c"], "") = "abc" 4680 * StringUtils.join([null, "", "a"], ',') = ",,a" 4681 * </pre> 4682 * 4683 * @param array The array of values to join together, may be null. 4684 * @param delimiter The separator character to use, null treated as "". 4685 * @return The joined String, {@code null} if null array input. 4686 */ 4687 public static String join(final Object[] array, final String delimiter) { 4688 return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null; 4689 } 4690 4691 /** 4692 * Joins the elements of the provided array into a single String containing the provided list of elements. 4693 * 4694 * <p> 4695 * 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 4696 * array are represented by empty strings. 4697 * </p> 4698 * 4699 * <pre> 4700 * StringUtils.join(null, *, *, *) = null 4701 * StringUtils.join([], *, *, *) = "" 4702 * StringUtils.join([null], *, *, *) = "" 4703 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4704 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4705 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4706 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4707 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4708 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4709 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4710 * </pre> 4711 * 4712 * @param array The array of values to join together, may be null. 4713 * @param delimiter The separator character to use, null treated as "". 4714 * @param startIndex The first index to start joining from. 4715 * @param endIndex The index to stop joining from (exclusive). 4716 * @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 4717 * given by {@code endIndex - startIndex}. 4718 * @throws ArrayIndexOutOfBoundsException Thrown if<br> {@code startIndex < 0} or <br> {@code startIndex >= array.length()} or <br> {@code endIndex < 0} or 4719 * <br> {@code endIndex > array.length()}. 4720 */ 4721 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4722 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4723 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null; 4724 } 4725 4726 /** 4727 * Joins the elements of the provided array into a single String containing the provided list of elements. 4728 * 4729 * <p> 4730 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4731 * by empty strings. 4732 * </p> 4733 * 4734 * <pre> 4735 * StringUtils.join(null, *) = null 4736 * StringUtils.join([], *) = "" 4737 * StringUtils.join([null], *) = "" 4738 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4739 * StringUtils.join([1, 2, 3], null) = "123" 4740 * </pre> 4741 * 4742 * @param array 4743 * the array of values to join together, may be null. 4744 * @param delimiter 4745 * the separator character to use. 4746 * @return The joined String, {@code null} if null array input. 4747 * @since 3.2 4748 */ 4749 public static String join(final short[] array, final char delimiter) { 4750 if (array == null) { 4751 return null; 4752 } 4753 return join(array, delimiter, 0, array.length); 4754 } 4755 4756 /** 4757 * Joins the elements of the provided array into a single String containing the provided list of elements. 4758 * 4759 * <p> 4760 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4761 * by empty strings. 4762 * </p> 4763 * 4764 * <pre> 4765 * StringUtils.join(null, *) = null 4766 * StringUtils.join([], *) = "" 4767 * StringUtils.join([null], *) = "" 4768 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4769 * StringUtils.join([1, 2, 3], null) = "123" 4770 * </pre> 4771 * 4772 * @param array 4773 * the array of values to join together, may be null. 4774 * @param delimiter 4775 * the separator character to use. 4776 * @param startIndex 4777 * the first index to start joining from. It is an error to pass in a start index past the end of the 4778 * array. 4779 * @param endIndex 4780 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4781 * the array. 4782 * @return The joined String, {@code null} if null array input. 4783 * @since 3.2 4784 */ 4785 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4786 // See StringUtilsJoinBenchmark 4787 if (array == null) { 4788 return null; 4789 } 4790 checkFromToIndex(startIndex, endIndex, array.length); 4791 final int count = endIndex - startIndex; 4792 if (count <= 0) { 4793 return EMPTY; 4794 } 4795 final byte maxElementChars = 6; // "-32768" 4796 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4797 stringBuilder.append(array[startIndex]); 4798 for (int i = startIndex + 1; i < endIndex; i++) { 4799 stringBuilder.append(delimiter).append(array[i]); 4800 } 4801 return stringBuilder.toString(); 4802 } 4803 4804 /** 4805 * Joins the elements of the provided array into a single String containing the provided list of elements. 4806 * 4807 * <p> 4808 * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings. 4809 * </p> 4810 * 4811 * <pre> 4812 * StringUtils.join(null) = null 4813 * StringUtils.join([]) = "" 4814 * StringUtils.join([null]) = "" 4815 * StringUtils.join("a", "b", "c") = "abc" 4816 * StringUtils.join(null, "", "a") = "a" 4817 * </pre> 4818 * 4819 * @param <T> the specific type of values to join together. 4820 * @param elements The values to join together, may be null. 4821 * @return The joined String, {@code null} if null array input. 4822 * @since 2.0 4823 * @since 3.0 Changed signature to use varargs 4824 */ 4825 @SafeVarargs 4826 public static <T> String join(final T... elements) { 4827 return join(elements, null); 4828 } 4829 4830 /** 4831 * Joins the elements of the provided varargs into a single String containing the provided elements. 4832 * 4833 * <p> 4834 * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings (""). 4835 * </p> 4836 * 4837 * <pre> 4838 * StringUtils.joinWith(",", "a", "b") = "a,b" 4839 * StringUtils.joinWith(",", "a", "b","") = "a,b," 4840 * StringUtils.joinWith(",", "a", null, "b") = "a,,b" 4841 * StringUtils.joinWith(null, "a", "b") = "ab" 4842 * </pre> 4843 * 4844 * @param delimiter The separator character to use, null treated as "". 4845 * @param array The varargs providing the values to join together. {@code null} elements are treated as "". 4846 * @return The joined String. 4847 * @throws IllegalArgumentException Thrown if a null varargs is provided. 4848 * @since 3.5 4849 */ 4850 public static String joinWith(final String delimiter, final Object... array) { 4851 if (array == null) { 4852 throw new IllegalArgumentException("Object varargs must not be null"); 4853 } 4854 return join(array, delimiter); 4855 } 4856 4857 /** 4858 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible. 4859 * 4860 * <p> 4861 * A {@code null} CharSequence will return {@code -1}. 4862 * </p> 4863 * 4864 * <pre> 4865 * StringUtils.lastIndexOf(null, *) = -1 4866 * StringUtils.lastIndexOf(*, null) = -1 4867 * StringUtils.lastIndexOf("", "") = 0 4868 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4869 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4870 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4871 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4872 * </pre> 4873 * 4874 * @param seq The CharSequence to check, may be null. 4875 * @param searchSeq The CharSequence to find, may be null. 4876 * @return The last index of the search String, -1 if no match or {@code null} string input. 4877 * @since 2.0 4878 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4879 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}. 4880 */ 4881 @Deprecated 4882 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4883 return Strings.CS.lastIndexOf(seq, searchSeq); 4884 } 4885 4886 /** 4887 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible. 4888 * 4889 * <p> 4890 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4891 * 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 4892 * backwards; matches starting after the start position are ignored. 4893 * </p> 4894 * 4895 * <pre> 4896 * StringUtils.lastIndexOf(null, *, *) = -1 4897 * StringUtils.lastIndexOf(*, null, *) = -1 4898 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4899 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4900 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4901 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4902 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4903 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4904 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4905 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4906 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4907 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4908 * </pre> 4909 * 4910 * @param seq The CharSequence to check, may be null. 4911 * @param searchSeq The CharSequence to find, may be null. 4912 * @param startPos The start position, negative treated as zero. 4913 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} string input. 4914 * @since 2.0 4915 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4916 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}. 4917 */ 4918 @Deprecated 4919 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4920 return Strings.CS.lastIndexOf(seq, searchSeq, startPos); 4921 } 4922 4923 /** 4924 * 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 4925 * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that: 4926 * 4927 * <pre> 4928 * this.charAt(<em>k</em>) == searchChar 4929 * </pre> 4930 * 4931 * <p> 4932 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4933 * </p> 4934 * 4935 * <pre> 4936 * this.codePointAt(<em>k</em>) == searchChar 4937 * </pre> 4938 * 4939 * <p> 4940 * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4941 * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character. 4942 * </p> 4943 * 4944 * <pre> 4945 * StringUtils.lastIndexOf(null, *) = -1 4946 * StringUtils.lastIndexOf("", *) = -1 4947 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4948 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4949 * </pre> 4950 * 4951 * @param seq The {@link CharSequence} to check, may be null. 4952 * @param searchChar The character to find. 4953 * @return The last index of the search character, -1 if no match or {@code null} string input. 4954 * @since 2.0 4955 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4956 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4957 */ 4958 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4959 if (isEmpty(seq)) { 4960 return INDEX_NOT_FOUND; 4961 } 4962 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4963 } 4964 4965 /** 4966 * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of 4967 * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that: 4968 * 4969 * <pre> 4970 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4971 * </pre> 4972 * 4973 * <p> 4974 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4975 * </p> 4976 * 4977 * <pre> 4978 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4979 * </pre> 4980 * 4981 * <p> 4982 * 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 4983 * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The 4984 * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored. 4985 * </p> 4986 * 4987 * <p> 4988 * All indices are specified in {@code char} values (Unicode code units). 4989 * </p> 4990 * 4991 * <pre> 4992 * StringUtils.lastIndexOf(null, *, *) = -1 4993 * StringUtils.lastIndexOf("", *, *) = -1 4994 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4995 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4996 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4997 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4998 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4999 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 5000 * </pre> 5001 * 5002 * @param seq The CharSequence to check, may be null. 5003 * @param searchChar The character to find. 5004 * @param startPos The start position. 5005 * @return The last index of the search character (always ≤ startPos), -1 if no match or {@code null} string input. 5006 * @since 2.0 5007 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 5008 */ 5009 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 5010 if (isEmpty(seq)) { 5011 return INDEX_NOT_FOUND; 5012 } 5013 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 5014 } 5015 5016 /** 5017 * Finds the latest index of any substring in a set of potential substrings. 5018 * 5019 * <p> 5020 * 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 5021 * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses 5022 * {@link String#indexOf(String)} if possible 5023 * </p> 5024 * 5025 * <pre> 5026 * StringUtils.lastIndexOfAny(null, *) = -1 5027 * StringUtils.lastIndexOfAny(*, null) = -1 5028 * StringUtils.lastIndexOfAny(*, []) = -1 5029 * StringUtils.lastIndexOfAny(*, [null]) = -1 5030 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 5031 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 5032 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5033 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5034 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 5035 * </pre> 5036 * 5037 * @param str The CharSequence to check, may be null. 5038 * @param searchStrs The CharSequences to search for, may be null. 5039 * @return The last index of any of the CharSequences, -1 if no match. 5040 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 5041 */ 5042 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 5043 if (str == null || searchStrs == null) { 5044 return INDEX_NOT_FOUND; 5045 } 5046 int ret = INDEX_NOT_FOUND; 5047 int tmp; 5048 for (final CharSequence search : searchStrs) { 5049 if (search == null) { 5050 continue; 5051 } 5052 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 5053 if (tmp > ret) { 5054 ret = tmp; 5055 } 5056 } 5057 return ret; 5058 } 5059 5060 /** 5061 * Case insensitive find of the last index within a CharSequence. 5062 * 5063 * <p> 5064 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 5065 * the start position is negative. A start position greater than the string length searches the whole string. 5066 * </p> 5067 * 5068 * <pre> 5069 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5070 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5071 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5072 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5073 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5074 * </pre> 5075 * 5076 * @param str The CharSequence to check, may be null. 5077 * @param searchStr The CharSequence to find, may be null. 5078 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 5079 * @since 2.5 5080 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5081 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}. 5082 */ 5083 @Deprecated 5084 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5085 return Strings.CI.lastIndexOf(str, searchStr); 5086 } 5087 5088 /** 5089 * Case insensitive find of the last index within a CharSequence from the specified position. 5090 * 5091 * <p> 5092 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 5093 * 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 5094 * backwards; matches starting after the start position are ignored. 5095 * </p> 5096 * 5097 * <pre> 5098 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5099 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5100 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5101 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5102 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5103 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5104 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5105 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5106 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5107 * </pre> 5108 * 5109 * @param str The CharSequence to check, may be null. 5110 * @param searchStr The CharSequence to find, may be null. 5111 * @param startPos The start position. 5112 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} input. 5113 * @since 2.5 5114 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5115 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}. 5116 */ 5117 @Deprecated 5118 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 5119 return Strings.CI.lastIndexOf(str, searchStr, startPos); 5120 } 5121 5122 /** 5123 * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}. 5124 * 5125 * <p> 5126 * A {@code null} String will return {@code -1}. 5127 * </p> 5128 * 5129 * <pre> 5130 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5131 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5132 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5133 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5134 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5135 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5136 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5137 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5138 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5139 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5140 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5141 * </pre> 5142 * 5143 * <p> 5144 * Note that 'tail(CharSequence str, int n)' may be implemented as: 5145 * </p> 5146 * 5147 * <pre> 5148 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5149 * </pre> 5150 * 5151 * @param str The CharSequence to check, may be null. 5152 * @param searchStr The CharSequence to find, may be null. 5153 * @param ordinal The n-th last {@code searchStr} to find. 5154 * @return The n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5155 * @since 2.5 5156 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5157 */ 5158 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5159 return ordinalIndexOf(str, searchStr, ordinal, true); 5160 } 5161 5162 /** 5163 * Gets the leftmost {@code len} characters of a String. 5164 * 5165 * <p> 5166 * 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 5167 * if len is negative. 5168 * </p> 5169 * 5170 * <pre> 5171 * StringUtils.left(null, *) = null 5172 * StringUtils.left(*, -ve) = "" 5173 * StringUtils.left("", *) = "" 5174 * StringUtils.left("abc", 0) = "" 5175 * StringUtils.left("abc", 2) = "ab" 5176 * StringUtils.left("abc", 4) = "abc" 5177 * </pre> 5178 * 5179 * @param str The String to get the leftmost characters from, may be null. 5180 * @param len The length of the required String. 5181 * @return The leftmost characters, {@code null} if null String input. 5182 */ 5183 public static String left(final String str, final int len) { 5184 if (str == null) { 5185 return null; 5186 } 5187 if (len < 0) { 5188 return EMPTY; 5189 } 5190 if (str.length() <= len) { 5191 return str; 5192 } 5193 int cut = len; 5194 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 5195 if (splitsSurrogatePair(str, cut)) { 5196 cut--; 5197 } 5198 return str.substring(0, cut); 5199 } 5200 5201 /** 5202 * Left pad a String with spaces (' '). 5203 * 5204 * <p> 5205 * The String is padded to the size of {@code size}. 5206 * </p> 5207 * 5208 * <pre> 5209 * StringUtils.leftPad(null, *) = null 5210 * StringUtils.leftPad("", 3) = " " 5211 * StringUtils.leftPad("bat", 3) = "bat" 5212 * StringUtils.leftPad("bat", 5) = " bat" 5213 * StringUtils.leftPad("bat", 1) = "bat" 5214 * StringUtils.leftPad("bat", -1) = "bat" 5215 * </pre> 5216 * 5217 * @param str The String to pad out, may be null. 5218 * @param size The size to pad to. 5219 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5220 */ 5221 public static String leftPad(final String str, final int size) { 5222 return leftPad(str, size, ' '); 5223 } 5224 5225 /** 5226 * Left pad a String with a specified character. 5227 * 5228 * <p> 5229 * Pad to a size of {@code size}. 5230 * </p> 5231 * 5232 * <pre> 5233 * StringUtils.leftPad(null, *, *) = null 5234 * StringUtils.leftPad("", 3, 'z') = "zzz" 5235 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5236 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5237 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5238 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5239 * </pre> 5240 * 5241 * @param str The String to pad out, may be null. 5242 * @param size The size to pad to. 5243 * @param padChar The character to pad with. 5244 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5245 * @since 2.0 5246 */ 5247 public static String leftPad(final String str, final int size, final char padChar) { 5248 if (str == null || size <= str.length()) { 5249 return str; 5250 } 5251 final int pads = size - str.length(); 5252 if (pads <= 0) { 5253 return str; // returns original String when possible 5254 } 5255 if (pads > PAD_LIMIT) { 5256 return leftPad(str, size, String.valueOf(padChar)); 5257 } 5258 return repeat(padChar, pads).concat(str); 5259 } 5260 5261 /** 5262 * Left pad a String with a specified String. 5263 * 5264 * <p> 5265 * Pad to a size of {@code size}. If the requested padding length would split a Unicode surrogate pair in {@code padStr}, 5266 * the padding is shortened by one {@code char} to avoid introducing an unpaired surrogate by splitting the pair. In that case, the 5267 * returned String has a length of {@code size - 1}. 5268 * </p> 5269 * 5270 * <pre> 5271 * StringUtils.leftPad(null, *, *) = null 5272 * StringUtils.leftPad("", 3, "z") = "zzz" 5273 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5274 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5275 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5276 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5277 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5278 * StringUtils.leftPad("bat", 5, null) = " bat" 5279 * StringUtils.leftPad("bat", 5, "") = " bat" 5280 * StringUtils.leftPad("a", 2, "\uD83D\uDE00") = "a" 5281 * StringUtils.leftPad("a", 3, "\uD83D\uDE00") = "\uD83D\uDE00a" 5282 * </pre> 5283 * 5284 * @param str The String to pad out, may be null. 5285 * @param size The size to pad to. 5286 * @param padStr The String to pad with, null or empty treated as single space. 5287 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5288 */ 5289 public static String leftPad(final String str, final int size, String padStr) { 5290 if (str == null || size <= str.length()) { 5291 return str; 5292 } 5293 if (isEmpty(padStr)) { 5294 padStr = SPACE; 5295 } 5296 final int padLen = padStr.length(); 5297 final int strLen = str.length(); 5298 int pads = size - strLen; 5299 if (pads <= 0) { 5300 return str; // returns original String when possible 5301 } 5302 if (padLen == 1 && pads <= PAD_LIMIT) { 5303 return leftPad(str, size, padStr.charAt(0)); 5304 } 5305 // Keep the padding boundary off the middle of a surrogate pair to avoid introducing a lone surrogate. 5306 if (splitsSurrogatePair(padStr, pads % padLen)) { 5307 pads--; 5308 } 5309 if (pads <= 0) { 5310 return str; 5311 } 5312 if (pads == padLen) { 5313 return padStr.concat(str); 5314 } 5315 if (pads < padLen) { 5316 return padStr.substring(0, pads).concat(str); 5317 } 5318 final char[] padding = new char[pads]; 5319 final char[] padChars = padStr.toCharArray(); 5320 for (int i = 0; i < pads; i++) { 5321 padding[i] = padChars[i % padLen]; 5322 } 5323 return new String(padding).concat(str); 5324 } 5325 5326 /** 5327 * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}. 5328 * 5329 * @param cs A CharSequence or {@code null}. 5330 * @return CharSequence length or {@code 0} if the CharSequence is {@code null}. 5331 * @since 2.4 5332 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5333 */ 5334 public static int length(final CharSequence cs) { 5335 return cs == null ? 0 : cs.length(); 5336 } 5337 5338 /** 5339 * Converts a String to lower case as per {@link String#toLowerCase()}. 5340 * 5341 * <p> 5342 * A {@code null} input String returns {@code null}. 5343 * </p> 5344 * 5345 * <pre> 5346 * StringUtils.lowerCase(null) = null 5347 * StringUtils.lowerCase("") = "" 5348 * StringUtils.lowerCase("aBc") = "abc" 5349 * </pre> 5350 * 5351 * <p> 5352 * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale. 5353 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g. 5354 * {@link Locale#ENGLISH}). 5355 * </p> 5356 * 5357 * @param str The String to lower case, may be null. 5358 * @return The lower cased String, {@code null} if null String input. 5359 */ 5360 public static String lowerCase(final String str) { 5361 if (str == null) { 5362 return null; 5363 } 5364 return str.toLowerCase(); 5365 } 5366 5367 /** 5368 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5369 * 5370 * <p> 5371 * A {@code null} input String returns {@code null}. 5372 * </p> 5373 * 5374 * <pre> 5375 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5376 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5377 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5378 * </pre> 5379 * 5380 * @param str The String to lower case, may be null. 5381 * @param locale The locale that defines the case transformation rules, must not be null. 5382 * @return The lower cased String, {@code null} if null String input. 5383 * @since 2.5 5384 */ 5385 public static String lowerCase(final String str, final Locale locale) { 5386 if (str == null) { 5387 return null; 5388 } 5389 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5390 } 5391 5392 private static int[] matches(final CharSequence first, final CharSequence second) { 5393 final CharSequence max; 5394 final CharSequence min; 5395 if (first.length() > second.length()) { 5396 max = first; 5397 min = second; 5398 } else { 5399 max = second; 5400 min = first; 5401 } 5402 final int range = Math.max(max.length() / 2 - 1, 0); 5403 final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1); 5404 final boolean[] matchFlags = new boolean[max.length()]; 5405 int matches = 0; 5406 for (int mi = 0; mi < min.length(); mi++) { 5407 final char c1 = min.charAt(mi); 5408 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5409 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5410 matchIndexes[mi] = xi; 5411 matchFlags[xi] = true; 5412 matches++; 5413 break; 5414 } 5415 } 5416 } 5417 final char[] ms1 = new char[matches]; 5418 final char[] ms2 = new char[matches]; 5419 for (int i = 0, si = 0; i < min.length(); i++) { 5420 if (matchIndexes[i] != -1) { 5421 ms1[si] = min.charAt(i); 5422 si++; 5423 } 5424 } 5425 for (int i = 0, si = 0; i < max.length(); i++) { 5426 if (matchFlags[i]) { 5427 ms2[si] = max.charAt(i); 5428 si++; 5429 } 5430 } 5431 int transpositions = 0; 5432 for (int mi = 0; mi < ms1.length; mi++) { 5433 if (ms1[mi] != ms2[mi]) { 5434 transpositions++; 5435 } 5436 } 5437 int prefix = 0; 5438 for (int mi = 0; mi < min.length(); mi++) { 5439 if (first.charAt(mi) != second.charAt(mi)) { 5440 break; 5441 } 5442 prefix++; 5443 } 5444 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5445 } 5446 5447 /** 5448 * Gets {@code len} characters from the middle of a String. 5449 * 5450 * <p> 5451 * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null}, 5452 * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}. 5453 * </p> 5454 * 5455 * <pre> 5456 * StringUtils.mid(null, *, *) = null 5457 * StringUtils.mid(*, *, -ve) = "" 5458 * StringUtils.mid("", 0, *) = "" 5459 * StringUtils.mid("abc", 0, 2) = "ab" 5460 * StringUtils.mid("abc", 0, 4) = "abc" 5461 * StringUtils.mid("abc", 2, 4) = "c" 5462 * StringUtils.mid("abc", 4, 2) = "" 5463 * StringUtils.mid("abc", -2, 2) = "ab" 5464 * </pre> 5465 * 5466 * @param str The String to get the characters from, may be null. 5467 * @param pos The position to start from, negative treated as zero. 5468 * @param len The length of the required String. 5469 * @return The middle characters, {@code null} if null String input. 5470 */ 5471 public static String mid(final String str, int pos, final int len) { 5472 if (str == null) { 5473 return null; 5474 } 5475 if (len < 0 || pos > str.length()) { 5476 return EMPTY; 5477 } 5478 if (pos < 0) { 5479 pos = 0; 5480 } 5481 int start = pos; 5482 // keep the start off the middle of a surrogate pair so the result is never left holding a lone surrogate 5483 if (splitsSurrogatePair(str, start)) { 5484 start++; 5485 } 5486 if (str.length() - pos <= len) { 5487 return str.substring(start); 5488 } 5489 int end = pos + len; 5490 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 5491 if (splitsSurrogatePair(str, end)) { 5492 end--; 5493 } 5494 return str.substring(start, Math.max(start, end)); 5495 } 5496 5497 /** 5498 * Normalizes whitespace in a String. 5499 * 5500 * <p>Removes leading and trailing whitespace and replaces each remaining sequence of characters recognized by {@link Character#isWhitespace(char)} 5501 * with a single ordinary space ({@code U+0020}). This includes Unicode whitespace beyond the characters matched by the default regular expression 5502 * {@code \s}, such as EM SPACE ({@code U+2003}).</p> 5503 * 5504 * <p>Additionally, converts each non-breaking space ({@code U+00A0}) to an ordinary space, even though {@link Character#isWhitespace(char)} excludes it. 5505 * These conversions do not collapse adjacent spaces: for example, <code>"a\u00A0\u00A0b"</code> becomes {@code "a b"}. Finally, 5506 * {@link String#trim()} removes 5507 * leading and trailing characters whose values are at most {@code U+0020}, including converted non-breaking spaces. Other non-breaking spaces, such as 5508 * FIGURE SPACE ({@code U+2007}) and NARROW NO-BREAK SPACE ({@code U+202F}), are preserved.</p> 5509 * 5510 * <p>This method was inspired by XPath's 5511 * <a href="https://www.w3.org/TR/xpath/#function-normalize-space">normalize-space</a> function, but does not reproduce its behavior. 5512 * XPath normalizes only XML 5513 * whitespace ({@code U+0020}, {@code U+0009}, {@code U+000D}, and {@code U+000A}) and preserves non-breaking spaces. This method additionally normalizes 5514 * Java whitespace, converts {@code U+00A0}, and trims leading and trailing control characters as described above.</p> 5515 * 5516 * @param str The source String to normalize whitespaces from, may be null. 5517 * @return The modified string with whitespace normalized, {@code null} if null String input. 5518 * @see Character#isWhitespace(char) 5519 * @see #trim(String) 5520 * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5521 * @since 3.0 5522 */ 5523 public static String normalizeSpace(final String str) { 5524 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5525 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5526 if (isEmpty(str)) { 5527 return str; 5528 } 5529 final int size = str.length(); 5530 final char[] newChars = new char[size]; 5531 int count = 0; 5532 int whitespacesCount = 0; 5533 boolean startWhitespaces = true; 5534 for (int i = 0; i < size; i++) { 5535 final char actualChar = str.charAt(i); 5536 final boolean isWhitespace = Character.isWhitespace(actualChar); 5537 if (isWhitespace) { 5538 if (whitespacesCount == 0 && !startWhitespaces) { 5539 newChars[count++] = SPACE.charAt(0); 5540 } 5541 whitespacesCount++; 5542 } else { 5543 startWhitespaces = false; 5544 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5545 whitespacesCount = 0; 5546 } 5547 } 5548 if (startWhitespaces) { 5549 return EMPTY; 5550 } 5551 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5552 } 5553 5554 /** 5555 * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5556 * <p> 5557 * <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 5558 * (unless {@code searchStr} is an empty string, in which case the position is never incremented and {@code 0} is returned immediately). This means that 5559 * matches may overlap. 5560 * </p> 5561 * <p> 5562 * A {@code null} CharSequence will return {@code -1}. 5563 * </p> 5564 * 5565 * <pre> 5566 * StringUtils.ordinalIndexOf(null, *, *) = -1 5567 * StringUtils.ordinalIndexOf(*, null, *) = -1 5568 * StringUtils.ordinalIndexOf("", "", *) = 0 5569 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5570 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5571 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5572 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5573 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5574 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5575 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5576 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5577 * </pre> 5578 * 5579 * <p> 5580 * Matches may overlap: 5581 * </p> 5582 * 5583 * <pre> 5584 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5585 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5586 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5587 * 5588 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5589 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5590 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5591 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5592 * </pre> 5593 * 5594 * <p> 5595 * Note that 'head(CharSequence str, int n)' may be implemented as: 5596 * </p> 5597 * 5598 * <pre> 5599 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5600 * </pre> 5601 * 5602 * @param str The CharSequence to check, may be null. 5603 * @param searchStr The CharSequence to find, may be null. 5604 * @param ordinal The n-th {@code searchStr} to find. 5605 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5606 * @since 2.1 5607 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5608 */ 5609 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5610 return ordinalIndexOf(str, searchStr, ordinal, false); 5611 } 5612 5613 /** 5614 * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5615 * <p> 5616 * Note that matches may overlap. 5617 * <p> 5618 * 5619 * <p> 5620 * A {@code null} CharSequence will return {@code -1}. 5621 * </p> 5622 * 5623 * @param str The CharSequence to check, may be null. 5624 * @param searchStr The CharSequence to find, may be null. 5625 * @param ordinal The n-th {@code searchStr} to find, overlapping matches are allowed. 5626 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf(). 5627 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5628 */ 5629 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5630 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5631 if (str == null || searchStr == null || ordinal <= 0) { 5632 return INDEX_NOT_FOUND; 5633 } 5634 if (isEmpty(searchStr)) { 5635 return lastIndex ? str.length() : 0; 5636 } 5637 int found = 0; 5638 // set the initial index beyond the end of the string 5639 // this is to allow for the initial index decrement/increment 5640 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5641 do { 5642 if (lastIndex) { 5643 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5644 } else { 5645 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5646 } 5647 if (index < 0) { 5648 return index; 5649 } 5650 found++; 5651 } while (found < ordinal); 5652 return index; 5653 } 5654 5655 /** 5656 * Overlays part of a String with another String. 5657 * 5658 * <p> 5659 * 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 5660 * length. The start index is always the smaller of the two indices. 5661 * </p> 5662 * 5663 * <pre> 5664 * StringUtils.overlay(null, *, *, *) = null 5665 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5666 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5667 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5668 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5669 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5670 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5671 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5672 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5673 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5674 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5675 * </pre> 5676 * 5677 * @param str The String to do overlaying in, may be null. 5678 * @param overlay The String to overlay, may be null. 5679 * @param start The position to start overlaying at. 5680 * @param end The position to stop overlaying before. 5681 * @return overlaid String, {@code null} if null String input. 5682 * @since 2.0 5683 */ 5684 public static String overlay(final String str, String overlay, int start, int end) { 5685 if (str == null) { 5686 return null; 5687 } 5688 if (overlay == null) { 5689 overlay = EMPTY; 5690 } 5691 final int len = str.length(); 5692 if (start < 0) { 5693 start = 0; 5694 } 5695 if (start > len) { 5696 start = len; 5697 } 5698 if (end < 0) { 5699 end = 0; 5700 } 5701 if (end > len) { 5702 end = len; 5703 } 5704 if (start > end) { 5705 final int temp = start; 5706 start = end; 5707 end = temp; 5708 } 5709 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 5710 if (splitsSurrogatePair(str, start)) { 5711 start--; 5712 } 5713 if (splitsSurrogatePair(str, end)) { 5714 end++; 5715 } 5716 return str.substring(0, start) + overlay + str.substring(end); 5717 } 5718 5719 /** 5720 * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes. 5721 * 5722 * <pre> 5723 * StringUtils.prependIfMissing(null, null) = null 5724 * StringUtils.prependIfMissing("abc", null) = "abc" 5725 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5726 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5727 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5728 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5729 * </pre> 5730 * <p> 5731 * With additional prefixes, 5732 * </p> 5733 * 5734 * <pre> 5735 * StringUtils.prependIfMissing(null, null, null) = null 5736 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5737 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5738 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5739 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5740 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5741 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5742 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5743 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5744 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5745 * </pre> 5746 * 5747 * @param str The string. 5748 * @param prefix The prefix to prepend to the start of the string. 5749 * @param prefixes Additional prefixes that are valid. 5750 * @return A new String if prefix was prepended, the same string otherwise. 5751 * @since 3.2 5752 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence, 5753 * CharSequence...)}. 5754 */ 5755 @Deprecated 5756 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5757 return Strings.CS.prependIfMissing(str, prefix, prefixes); 5758 } 5759 5760 /** 5761 * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes. 5762 * 5763 * <pre> 5764 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5765 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5766 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5767 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5768 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5769 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5770 * </pre> 5771 * <p> 5772 * With additional prefixes, 5773 * </p> 5774 * 5775 * <pre> 5776 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5777 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5778 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5779 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5780 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5781 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5782 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5783 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5784 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5785 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5786 * </pre> 5787 * 5788 * @param str The string. 5789 * @param prefix The prefix to prepend to the start of the string. 5790 * @param prefixes Additional prefixes that are valid (optional). 5791 * @return A new String if prefix was prepended, the same string otherwise. 5792 * @since 3.2 5793 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence, 5794 * CharSequence...)}. 5795 */ 5796 @Deprecated 5797 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5798 return Strings.CI.prependIfMissing(str, prefix, prefixes); 5799 } 5800 5801 /** 5802 * Removes all occurrences of a character from within the source string. 5803 * 5804 * <p> 5805 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. 5806 * </p> 5807 * 5808 * <pre> 5809 * StringUtils.remove(null, *) = null 5810 * StringUtils.remove("", *) = "" 5811 * StringUtils.remove("queued", 'u') = "qeed" 5812 * StringUtils.remove("queued", 'z') = "queued" 5813 * </pre> 5814 * 5815 * @param str The source String to search, may be null. 5816 * @param remove The char to search for and remove, may be null. 5817 * @return The substring with the char removed if found, {@code null} if null String input. 5818 * @since 2.1 5819 */ 5820 public static String remove(final String str, final char remove) { 5821 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5822 return str; 5823 } 5824 final char[] chars = str.toCharArray(); 5825 int pos = 0; 5826 for (int i = 0; i < chars.length; i++) { 5827 if (chars[i] != remove) { 5828 chars[pos++] = chars[i]; 5829 } 5830 } 5831 return new String(chars, 0, pos); 5832 } 5833 5834 /** 5835 * Removes all occurrences of a substring from within the source string. 5836 * 5837 * <p> 5838 * 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 5839 * the source string. An empty ("") remove string will return the source string. 5840 * </p> 5841 * 5842 * <pre> 5843 * StringUtils.remove(null, *) = null 5844 * StringUtils.remove("", *) = "" 5845 * StringUtils.remove(*, null) = * 5846 * StringUtils.remove(*, "") = * 5847 * StringUtils.remove("queued", "ue") = "qd" 5848 * StringUtils.remove("queued", "zz") = "queued" 5849 * </pre> 5850 * 5851 * @param str The source String to search, may be null. 5852 * @param remove The String to search for and remove, may be null. 5853 * @return The substring with the string removed if found, {@code null} if null String input. 5854 * @since 2.1 5855 * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}. 5856 */ 5857 @Deprecated 5858 public static String remove(final String str, final String remove) { 5859 return Strings.CS.remove(str, remove); 5860 } 5861 5862 /** 5863 * Removes each substring of the text String that matches the given regular expression. 5864 * 5865 * This method is a {@code null} safe equivalent to: 5866 * <ul> 5867 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5868 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5869 * </ul> 5870 * 5871 * <p> 5872 * A {@code null} reference passed to this method is a no-op. 5873 * </p> 5874 * 5875 * <p> 5876 * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option 5877 * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 5878 * </p> 5879 * 5880 * <pre>{@code 5881 * StringUtils.removeAll(null, *) = null 5882 * StringUtils.removeAll("any", (String) null) = "any" 5883 * StringUtils.removeAll("any", "") = "any" 5884 * StringUtils.removeAll("any", ".*") = "" 5885 * StringUtils.removeAll("any", ".+") = "" 5886 * StringUtils.removeAll("abc", ".?") = "" 5887 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5888 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5889 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5890 * }</pre> 5891 * 5892 * @param text text to remove from, may be null. 5893 * @param regex The regular expression to which this string is to be matched. 5894 * @return The text with any removes processed, {@code null} if null String input. 5895 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 5896 * @see #replaceAll(String, String, String) 5897 * @see #removePattern(String, String) 5898 * @see String#replaceAll(String, String) 5899 * @see java.util.regex.Pattern 5900 * @see java.util.regex.Pattern#DOTALL 5901 * @since 3.5 5902 * @deprecated Use {@link RegExUtils#removeAll(String, String)}. 5903 */ 5904 @Deprecated 5905 public static String removeAll(final String text, final String regex) { 5906 return RegExUtils.removeAll(text, regex); 5907 } 5908 5909 /** 5910 * Removes a substring only if it is at the end of a source string, otherwise returns the source string. 5911 * 5912 * <p> 5913 * 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 5914 * the source string. 5915 * </p> 5916 * 5917 * <pre> 5918 * StringUtils.removeEnd(null, *) = null 5919 * StringUtils.removeEnd("", *) = "" 5920 * StringUtils.removeEnd(*, null) = * 5921 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5922 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5923 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5924 * StringUtils.removeEnd("abc", "") = "abc" 5925 * </pre> 5926 * 5927 * @param str The source String to search, may be null. 5928 * @param remove The String to search for and remove, may be null. 5929 * @return The substring with the string removed if found, {@code null} if null String input. 5930 * @since 2.1 5931 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}. 5932 */ 5933 @Deprecated 5934 public static String removeEnd(final String str, final String remove) { 5935 return Strings.CS.removeEnd(str, remove); 5936 } 5937 5938 /** 5939 * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string. 5940 * 5941 * <p> 5942 * 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 5943 * the source string. 5944 * </p> 5945 * 5946 * <pre> 5947 * StringUtils.removeEndIgnoreCase(null, *) = null 5948 * StringUtils.removeEndIgnoreCase("", *) = "" 5949 * StringUtils.removeEndIgnoreCase(*, null) = * 5950 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5951 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5952 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5953 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5954 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain" 5955 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain" 5956 * </pre> 5957 * 5958 * @param str The source String to search, may be null. 5959 * @param remove The String to search for (case-insensitive) and remove, may be null. 5960 * @return The substring with the string removed if found, {@code null} if null String input. 5961 * @since 2.4 5962 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}. 5963 */ 5964 @Deprecated 5965 public static String removeEndIgnoreCase(final String str, final String remove) { 5966 return Strings.CI.removeEnd(str, remove); 5967 } 5968 5969 /** 5970 * Removes the first substring of the text string that matches the given regular expression. 5971 * 5972 * This method is a {@code null} safe equivalent to: 5973 * <ul> 5974 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 5975 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 5976 * </ul> 5977 * 5978 * <p> 5979 * A {@code null} reference passed to this method is a no-op. 5980 * </p> 5981 * 5982 * <p> 5983 * 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 5984 * single-line mode in Perl. 5985 * </p> 5986 * 5987 * <pre>{@code 5988 * StringUtils.removeFirst(null, *) = null 5989 * StringUtils.removeFirst("any", (String) null) = "any" 5990 * StringUtils.removeFirst("any", "") = "any" 5991 * StringUtils.removeFirst("any", ".*") = "" 5992 * StringUtils.removeFirst("any", ".+") = "" 5993 * StringUtils.removeFirst("abc", ".?") = "bc" 5994 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5995 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5996 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5997 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5998 * }</pre> 5999 * 6000 * @param text text to remove from, may be null. 6001 * @param regex The regular expression to which this string is to be matched. 6002 * @return The text with the first replacement processed, {@code null} if null String input. 6003 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 6004 * @see #replaceFirst(String, String, String) 6005 * @see String#replaceFirst(String, String) 6006 * @see java.util.regex.Pattern 6007 * @see java.util.regex.Pattern#DOTALL 6008 * @since 3.5 6009 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String) RegExUtils.replaceFirst(String, String, EMPTY)}. 6010 */ 6011 @Deprecated 6012 public static String removeFirst(final String text, final String regex) { 6013 return replaceFirst(text, regex, EMPTY); 6014 } 6015 6016 /** 6017 * Case-insensitive removal of all occurrences of a substring from within the source string. 6018 * 6019 * <p> 6020 * 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 6021 * the source string. An empty ("") remove string will return the source string. 6022 * </p> 6023 * 6024 * <pre> 6025 * StringUtils.removeIgnoreCase(null, *) = null 6026 * StringUtils.removeIgnoreCase("", *) = "" 6027 * StringUtils.removeIgnoreCase(*, null) = * 6028 * StringUtils.removeIgnoreCase(*, "") = * 6029 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 6030 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 6031 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 6032 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 6033 * </pre> 6034 * 6035 * @param str The source String to search, may be null. 6036 * @param remove The String to search for (case-insensitive) and remove, may be null. 6037 * @return The substring with the string removed if found, {@code null} if null String input. 6038 * @since 3.5 6039 * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}. 6040 */ 6041 @Deprecated 6042 public static String removeIgnoreCase(final String str, final String remove) { 6043 return Strings.CI.remove(str, remove); 6044 } 6045 6046 /** 6047 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6048 * 6049 * This call is a {@code null} safe equivalent to: 6050 * <ul> 6051 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6052 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6053 * </ul> 6054 * 6055 * <p> 6056 * A {@code null} reference passed to this method is a no-op. 6057 * </p> 6058 * 6059 * <pre>{@code 6060 * StringUtils.removePattern(null, *) = null 6061 * StringUtils.removePattern("any", (String) null) = "any" 6062 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 6063 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 6064 * }</pre> 6065 * 6066 * @param source The source string. 6067 * @param regex The regular expression to which this string is to be matched. 6068 * @return The resulting {@link String}. 6069 * @see #replacePattern(String, String, String) 6070 * @see String#replaceAll(String, String) 6071 * @see Pattern#DOTALL 6072 * @since 3.2 6073 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6074 * @deprecated Use {@link RegExUtils#removePattern(CharSequence, String)}. 6075 */ 6076 @Deprecated 6077 public static String removePattern(final String source, final String regex) { 6078 return RegExUtils.removePattern(source, regex); 6079 } 6080 6081 /** 6082 * Removes a char only if it is at the beginning of a source string, otherwise returns the source string. 6083 * 6084 * <p> 6085 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. 6086 * </p> 6087 * 6088 * <pre> 6089 * StringUtils.removeStart(null, *) = null 6090 * StringUtils.removeStart("", *) = "" 6091 * StringUtils.removeStart("/path", '/') = "path" 6092 * StringUtils.removeStart("path", '/') = "path" 6093 * StringUtils.removeStart("path", '\0') = "path" 6094 * </pre> 6095 * 6096 * @param str The source String to search, may be null. 6097 * @param remove The char to search for and remove. 6098 * @return The substring with the char removed if found, {@code null} if null String input. 6099 * @since 3.13.0 6100 */ 6101 public static String removeStart(final String str, final char remove) { 6102 if (isEmpty(str)) { 6103 return str; 6104 } 6105 return str.charAt(0) == remove ? str.substring(1) : str; 6106 } 6107 6108 /** 6109 * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string. 6110 * 6111 * <p> 6112 * 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 6113 * the source string. 6114 * </p> 6115 * 6116 * <pre> 6117 * StringUtils.removeStart(null, *) = null 6118 * StringUtils.removeStart("", *) = "" 6119 * StringUtils.removeStart(*, null) = * 6120 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6121 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6122 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6123 * StringUtils.removeStart("abc", "") = "abc" 6124 * </pre> 6125 * 6126 * @param str The source String to search, may be null. 6127 * @param remove The String to search for and remove, may be null. 6128 * @return The substring with the string removed if found, {@code null} if null String input. 6129 * @since 2.1 6130 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}. 6131 */ 6132 @Deprecated 6133 public static String removeStart(final String str, final String remove) { 6134 return Strings.CS.removeStart(str, remove); 6135 } 6136 6137 /** 6138 * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string. 6139 * 6140 * <p> 6141 * 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 6142 * the source string. 6143 * </p> 6144 * 6145 * <pre> 6146 * StringUtils.removeStartIgnoreCase(null, *) = null 6147 * StringUtils.removeStartIgnoreCase("", *) = "" 6148 * StringUtils.removeStartIgnoreCase(*, null) = * 6149 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6150 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6151 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6152 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6153 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6154 * </pre> 6155 * 6156 * @param str The source String to search, may be null. 6157 * @param remove The String to search for (case-insensitive) and remove, may be null. 6158 * @return The substring with the string removed if found, {@code null} if null String input. 6159 * @since 2.4 6160 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}. 6161 */ 6162 @Deprecated 6163 public static String removeStartIgnoreCase(final String str, final String remove) { 6164 return Strings.CI.removeStart(str, remove); 6165 } 6166 6167 /** 6168 * Returns padding using the specified delimiter repeated to a given length. 6169 * 6170 * <pre> 6171 * StringUtils.repeat('e', 0) = "" 6172 * StringUtils.repeat('e', 3) = "eee" 6173 * StringUtils.repeat('e', -2) = "" 6174 * </pre> 6175 * 6176 * <p> 6177 * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6178 * 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 6179 * {@link #repeat(String, int)} instead. 6180 * </p> 6181 * 6182 * @param repeat character to repeat. 6183 * @param count number of times to repeat char, negative treated as zero. 6184 * @return String with repeated character. 6185 * @see #repeat(String, int) 6186 */ 6187 public static String repeat(final char repeat, final int count) { 6188 if (count <= 0) { 6189 return EMPTY; 6190 } 6191 return new String(ArrayFill.fill(new char[count], repeat)); 6192 } 6193 6194 /** 6195 * Repeats a String {@code repeat} times to form a new String. 6196 * 6197 * <pre> 6198 * StringUtils.repeat(null, 2) = null 6199 * StringUtils.repeat("", 0) = "" 6200 * StringUtils.repeat("", 2) = "" 6201 * StringUtils.repeat("a", 3) = "aaa" 6202 * StringUtils.repeat("ab", 2) = "abab" 6203 * StringUtils.repeat("a", -2) = "" 6204 * </pre> 6205 * 6206 * @param repeat The String to repeat, may be null. 6207 * @param count number of times to repeat str, negative treated as zero. 6208 * @return A new String consisting of the original String repeated, {@code null} if null String input. 6209 */ 6210 public static String repeat(final String repeat, final int count) { 6211 // Performance tuned for 2.0 (JDK1.4) 6212 if (repeat == null) { 6213 return null; 6214 } 6215 if (count <= 0) { 6216 return EMPTY; 6217 } 6218 final int inputLength = repeat.length(); 6219 if (count == 1 || inputLength == 0) { 6220 return repeat; 6221 } 6222 if (inputLength == 1 && count <= PAD_LIMIT) { 6223 return repeat(repeat.charAt(0), count); 6224 } 6225 final int outputLength; 6226 try { 6227 outputLength = Math.multiplyExact(inputLength, count); 6228 } catch (final Exception e) { 6229 throw new IllegalArgumentException("The requested result is too large for a String."); 6230 } 6231 switch (inputLength) { 6232 case 1: 6233 return repeat(repeat.charAt(0), count); 6234 case 2: 6235 final char ch0 = repeat.charAt(0); 6236 final char ch1 = repeat.charAt(1); 6237 final char[] output2 = new char[outputLength]; 6238 for (int i = count * 2 - 2; i >= 0; i--, i--) { 6239 output2[i] = ch0; 6240 output2[i + 1] = ch1; 6241 } 6242 return new String(output2); 6243 default: 6244 final StringBuilder buf = new StringBuilder(outputLength); 6245 for (int i = 0; i < count; i++) { 6246 buf.append(repeat); 6247 } 6248 return buf.toString(); 6249 } 6250 } 6251 6252 /** 6253 * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time. 6254 * 6255 * <pre> 6256 * StringUtils.repeat(null, null, 2) = null 6257 * StringUtils.repeat(null, "x", 2) = null 6258 * StringUtils.repeat("", null, 0) = "" 6259 * StringUtils.repeat("", "", 2) = "" 6260 * StringUtils.repeat("", "x", 3) = "xx" 6261 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6262 * </pre> 6263 * 6264 * @param repeat The String to repeat, may be null. 6265 * @param separator The String to inject, may be null. 6266 * @param count number of times to repeat str, negative treated as zero. 6267 * @return A new String consisting of the original String repeated, {@code null} if null String input. 6268 * @since 2.5 6269 */ 6270 public static String repeat(final String repeat, final String separator, final int count) { 6271 if (repeat == null || separator == null) { 6272 return repeat(repeat, count); 6273 } 6274 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6275 final String result = repeat(repeat + separator, count); 6276 return Strings.CS.removeEnd(result, separator); 6277 } 6278 6279 /** 6280 * Replaces all occurrences of a String within another String. 6281 * 6282 * <p> 6283 * A {@code null} reference passed to this method is a no-op. 6284 * </p> 6285 * 6286 * <pre> 6287 * StringUtils.replace(null, *, *) = null 6288 * StringUtils.replace("", *, *) = "" 6289 * StringUtils.replace("any", null, *) = "any" 6290 * StringUtils.replace("any", *, null) = "any" 6291 * StringUtils.replace("any", "", *) = "any" 6292 * StringUtils.replace("aba", "a", null) = "aba" 6293 * StringUtils.replace("aba", "a", "") = "b" 6294 * StringUtils.replace("aba", "a", "z") = "zbz" 6295 * </pre> 6296 * 6297 * @param text text to search and replace in, may be null. 6298 * @param searchString The String to search for, may be null. 6299 * @param replacement The String to replace it with, may be null. 6300 * @return The text with any replacements processed, {@code null} if null String input. 6301 * @see #replace(String text, String searchString, String replacement, int max) 6302 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}. 6303 */ 6304 @Deprecated 6305 public static String replace(final String text, final String searchString, final String replacement) { 6306 return Strings.CS.replace(text, searchString, replacement); 6307 } 6308 6309 /** 6310 * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6311 * 6312 * <p> 6313 * A {@code null} reference passed to this method is a no-op. 6314 * </p> 6315 * 6316 * <pre> 6317 * StringUtils.replace(null, *, *, *) = null 6318 * StringUtils.replace("", *, *, *) = "" 6319 * StringUtils.replace("any", null, *, *) = "any" 6320 * StringUtils.replace("any", *, null, *) = "any" 6321 * StringUtils.replace("any", "", *, *) = "any" 6322 * StringUtils.replace("any", *, *, 0) = "any" 6323 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6324 * StringUtils.replace("abaa", "a", "", -1) = "b" 6325 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6326 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6327 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6328 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6329 * </pre> 6330 * 6331 * @param text text to search and replace in, may be null. 6332 * @param searchString The String to search for, may be null. 6333 * @param replacement The String to replace it with, may be null. 6334 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6335 * @return The text with any replacements processed, {@code null} if null String input. 6336 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}. 6337 */ 6338 @Deprecated 6339 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6340 return Strings.CS.replace(text, searchString, replacement, max); 6341 } 6342 6343 /** 6344 * Replaces each substring of the text String that matches the given regular expression with the given replacement. 6345 * 6346 * This method is a {@code null} safe equivalent to: 6347 * <ul> 6348 * <li>{@code text.replaceAll(regex, replacement)}</li> 6349 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6350 * </ul> 6351 * 6352 * <p> 6353 * A {@code null} reference passed to this method is a no-op. 6354 * </p> 6355 * 6356 * <p> 6357 * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL 6358 * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 6359 * </p> 6360 * 6361 * <pre>{@code 6362 * StringUtils.replaceAll(null, *, *) = null 6363 * StringUtils.replaceAll("any", (String) null, *) = "any" 6364 * StringUtils.replaceAll("any", *, null) = "any" 6365 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6366 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6367 * StringUtils.replaceAll("", ".+", "zzz") = "" 6368 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6369 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6370 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6371 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6372 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6373 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6374 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6375 * }</pre> 6376 * 6377 * @param text text to search and replace in, may be null. 6378 * @param regex The regular expression to which this string is to be matched. 6379 * @param replacement The string to be substituted for each match. 6380 * @return The text with any replacements processed, {@code null} if null String input. 6381 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 6382 * @see #replacePattern(String, String, String) 6383 * @see String#replaceAll(String, String) 6384 * @see java.util.regex.Pattern 6385 * @see java.util.regex.Pattern#DOTALL 6386 * @since 3.5 6387 * @deprecated Use {@link RegExUtils#replaceAll(String, String, String)}. 6388 */ 6389 @Deprecated 6390 public static String replaceAll(final String text, final String regex, final String replacement) { 6391 return RegExUtils.replaceAll(text, regex, replacement); 6392 } 6393 6394 /** 6395 * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}. 6396 * 6397 * <p> 6398 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. 6399 * </p> 6400 * 6401 * <pre> 6402 * StringUtils.replaceChars(null, *, *) = null 6403 * StringUtils.replaceChars("", *, *) = "" 6404 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6405 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6406 * </pre> 6407 * 6408 * @param str String to replace characters in, may be null. 6409 * @param searchChar The character to search for, may be null. 6410 * @param replaceChar The character to replace, may be null. 6411 * @return modified String, {@code null} if null string input. 6412 * @since 2.0 6413 */ 6414 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6415 if (str == null) { 6416 return null; 6417 } 6418 return str.replace(searchChar, replaceChar); 6419 } 6420 6421 /** 6422 * Replaces multiple characters in a String in one go. This method can also be used to delete characters. 6423 * 6424 * <p> 6425 * For example: 6426 * </p> 6427 * <pre> 6428 * replaceChars("hello", "ho", "jy") = jelly. 6429 * </pre> 6430 * 6431 * <p> 6432 * 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 6433 * the input string. 6434 * </p> 6435 * 6436 * <p> 6437 * 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 6438 * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored. 6439 * </p> 6440 * 6441 * <pre> 6442 * StringUtils.replaceChars(null, *, *) = null 6443 * StringUtils.replaceChars("", *, *) = "" 6444 * StringUtils.replaceChars("abc", null, *) = "abc" 6445 * StringUtils.replaceChars("abc", "", *) = "abc" 6446 * StringUtils.replaceChars("abc", "b", null) = "ac" 6447 * StringUtils.replaceChars("abc", "b", "") = "ac" 6448 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6449 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6450 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6451 * </pre> 6452 * 6453 * @param str String to replace characters in, may be null. 6454 * @param searchChars A set of characters to search for, may be null. 6455 * @param replaceChars A set of characters to replace, may be null. 6456 * @return modified String, {@code null} if null string input. 6457 * @since 2.0 6458 */ 6459 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6460 if (isEmpty(str) || isEmpty(searchChars)) { 6461 return str; 6462 } 6463 replaceChars = ObjectUtils.toString(replaceChars); 6464 boolean modified = false; 6465 final int replaceCharsLength = replaceChars.length(); 6466 final int strLength = str.length(); 6467 final StringBuilder buf = new StringBuilder(strLength); 6468 for (int i = 0; i < strLength; i++) { 6469 final char ch = str.charAt(i); 6470 final int index = searchChars.indexOf(ch); 6471 if (index >= 0) { 6472 modified = true; 6473 if (index < replaceCharsLength) { 6474 buf.append(replaceChars.charAt(index)); 6475 } 6476 } else { 6477 buf.append(ch); 6478 } 6479 } 6480 if (modified) { 6481 return buf.toString(); 6482 } 6483 return str; 6484 } 6485 6486 /** 6487 * Replaces all occurrences of Strings within another String. 6488 * 6489 * <p> 6490 * 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 6491 * will not repeat. For repeating replaces, call the overloaded method. 6492 * </p> 6493 * 6494 * <pre> 6495 * StringUtils.replaceEach(null, *, *) = null 6496 * StringUtils.replaceEach("", *, *) = "" 6497 * StringUtils.replaceEach("aba", null, null) = "aba" 6498 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6499 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6500 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6501 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6502 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6503 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6504 * (example of how it does not repeat) 6505 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6506 * </pre> 6507 * 6508 * @param text text to search and replace in, no-op if null. 6509 * @param searchList The Strings to search for, no-op if null. 6510 * @param replacementList The Strings to replace them with, no-op if null. 6511 * @return The text with any replacements processed, {@code null} if null String input. 6512 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6513 * @since 2.4 6514 */ 6515 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6516 return replaceEachOnce(text, searchList, replacementList); 6517 } 6518 6519 /** 6520 * Replace all occurrences of Strings within another String, in a single pass. This is a private helper method for 6521 * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])} 6522 * 6523 * <p> 6524 * 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. 6525 * </p> 6526 * 6527 * <pre> 6528 * StringUtils.replaceEachOnce(null, *, *) = null 6529 * StringUtils.replaceEachOnce("", *, *) = "" 6530 * StringUtils.replaceEachOnce("aba", null, null) = "aba" 6531 * StringUtils.replaceEachOnce("aba", new String[0], null) = "aba" 6532 * StringUtils.replaceEachOnce("aba", null, new String[0]) = "aba" 6533 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, null) = "aba" 6534 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, new String[]{""}) = "b" 6535 * StringUtils.replaceEachOnce("aba", new String[]{null}, new String[]{"a"}) = "aba" 6536 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6537 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6538 * </pre> 6539 * 6540 * <p> 6541 * When no replacement is performed, the {@code text} argument is returned unchanged (same reference); callers rely on this to detect convergence. 6542 * </p> 6543 * 6544 * @param text text to search and replace in, no-op if null. 6545 * @param searchList The Strings to search for, no-op if null. 6546 * @param replacementList The Strings to replace them with, no-op if null. 6547 * @return The text with any replacements processed, {@code null} if null String input. 6548 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6549 * @since 2.4 6550 */ 6551 private static String replaceEachOnce(final String text, final String[] searchList, final String[] replacementList) { 6552 6553 // Performance note: This creates very few new objects (one major goal) 6554 // let me know if there are performance requests, we can create a harness to measure 6555 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) { 6556 return text; 6557 } 6558 6559 final int searchLength = searchList.length; 6560 final int replacementLength = replacementList.length; 6561 6562 // make sure lengths are ok, these need to be equal 6563 if (searchLength != replacementLength) { 6564 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6565 + searchLength 6566 + " vs " 6567 + replacementLength); 6568 } 6569 6570 // keep track of which still have matches 6571 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6572 6573 // index on index that the match was found 6574 int textIndex = -1; 6575 int replaceIndex = -1; 6576 int tempIndex; 6577 6578 // index of replace array that will replace the search string found 6579 // NOTE: logic duplicated below START 6580 for (int i = 0; i < searchLength; i++) { 6581 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6582 continue; 6583 } 6584 tempIndex = text.indexOf(searchList[i]); 6585 6586 // see if we need to keep searching for this 6587 if (tempIndex == -1) { 6588 noMoreMatchesForReplIndex[i] = true; 6589 } else if (textIndex == -1 || tempIndex < textIndex) { 6590 textIndex = tempIndex; 6591 replaceIndex = i; 6592 } 6593 } 6594 // NOTE: logic mostly below END 6595 6596 // no search strings found, we are done 6597 if (textIndex == -1) { 6598 return text; 6599 } 6600 6601 int start = 0; 6602 6603 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6604 int increase = 0; 6605 6606 // count the replacement text elements that are larger than their corresponding text being replaced 6607 for (int i = 0; i < searchList.length; i++) { 6608 if (searchList[i] == null || replacementList[i] == null) { 6609 continue; 6610 } 6611 final int greater = replacementList[i].length() - searchList[i].length(); 6612 if (greater > 0) { 6613 increase += 3 * greater; // assume 3 matches 6614 } 6615 } 6616 // have upper-bound at 20% increase, then let Java take over 6617 increase = Math.min(increase, text.length() / 5); 6618 6619 final StringBuilder buf = new StringBuilder(text.length() + increase); 6620 6621 while (textIndex != -1) { 6622 6623 for (int i = start; i < textIndex; i++) { 6624 buf.append(text.charAt(i)); 6625 } 6626 buf.append(replacementList[replaceIndex]); 6627 6628 start = textIndex + searchList[replaceIndex].length(); 6629 6630 textIndex = -1; 6631 replaceIndex = -1; 6632 // find the next earliest match 6633 // NOTE: logic mostly duplicated above START 6634 for (int i = 0; i < searchLength; i++) { 6635 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6636 continue; 6637 } 6638 tempIndex = text.indexOf(searchList[i], start); 6639 6640 // see if we need to keep searching for this 6641 if (tempIndex == -1) { 6642 noMoreMatchesForReplIndex[i] = true; 6643 } else if (textIndex == -1 || tempIndex < textIndex) { 6644 textIndex = tempIndex; 6645 replaceIndex = i; 6646 } 6647 } 6648 // NOTE: logic duplicated above END 6649 6650 } 6651 final int textLength = text.length(); 6652 for (int i = start; i < textLength; i++) { 6653 buf.append(text.charAt(i)); 6654 } 6655 return buf.toString(); 6656 } 6657 6658 /** 6659 * Replaces all occurrences of Strings within another String. 6660 * 6661 * <p> 6662 * 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. 6663 * </p> 6664 * 6665 * <pre> 6666 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6667 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6668 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6669 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6670 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6671 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6672 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6673 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6674 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6675 * (example of how it repeats) 6676 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6677 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = Throws {@link IllegalStateException} 6678 * </pre> 6679 * 6680 * @param text text to search and replace in, no-op if null. 6681 * @param searchList The Strings to search for, no-op if null. 6682 * @param replacementList The Strings to replace them with, no-op if null. 6683 * @return The text with any replacements processed, {@code null} if null String input. 6684 * @throws IllegalStateException Thrown if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6685 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6686 * @since 2.4 6687 */ 6688 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6689 // The iteration budget is a fixed constant, deliberately independent of the caller-supplied 6690 // searchList length: deriving the budget from the input would let the input size choose the 6691 // recursion depth/amplification (formerly a real StackOverflowError on large search lists). 6692 String result = text; 6693 for (int timeToLive = DEFAULT_TTL; timeToLive >= 0; timeToLive--) { 6694 final String next = replaceEachOnce(result, searchList, replacementList); 6695 if (next == result) { 6696 // No replacement was performed; converged. 6697 return result; 6698 } 6699 result = next; 6700 } 6701 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6702 "output of one loop is the input of another"); 6703 } 6704 6705 /** 6706 * Replaces the first substring of the text string that matches the given regular expression with the given replacement. 6707 * 6708 * This method is a {@code null} safe equivalent to: 6709 * <ul> 6710 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6711 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6712 * </ul> 6713 * 6714 * <p> 6715 * A {@code null} reference passed to this method is a no-op. 6716 * </p> 6717 * 6718 * <p> 6719 * 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 6720 * single-line mode in Perl. 6721 * </p> 6722 * 6723 * <pre>{@code 6724 * StringUtils.replaceFirst(null, *, *) = null 6725 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6726 * StringUtils.replaceFirst("any", *, null) = "any" 6727 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6728 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6729 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6730 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6731 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6732 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6733 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6734 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6735 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6736 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6737 * }</pre> 6738 * 6739 * @param text text to search and replace in, may be null. 6740 * @param regex The regular expression to which this string is to be matched. 6741 * @param replacement The string to be substituted for the first match. 6742 * @return The text with the first replacement processed, {@code null} if null String input. 6743 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 6744 * @see String#replaceFirst(String, String) 6745 * @see java.util.regex.Pattern 6746 * @see java.util.regex.Pattern#DOTALL 6747 * @since 3.5 6748 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String)}. 6749 */ 6750 @Deprecated 6751 public static String replaceFirst(final String text, final String regex, final String replacement) { 6752 return RegExUtils.replaceFirst(text, regex, replacement); 6753 } 6754 6755 /** 6756 * Case insensitively replaces all occurrences of a String within another String. 6757 * 6758 * <p> 6759 * A {@code null} reference passed to this method is a no-op. 6760 * </p> 6761 * 6762 * <pre> 6763 * StringUtils.replaceIgnoreCase(null, *, *) = null 6764 * StringUtils.replaceIgnoreCase("", *, *) = "" 6765 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6766 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6767 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6768 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6769 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6770 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6771 * </pre> 6772 * 6773 * @param text text to search and replace in, may be null. 6774 * @param searchString The String to search for (case-insensitive), may be null. 6775 * @param replacement The String to replace it with, may be null. 6776 * @return The text with any replacements processed, {@code null} if null String input. 6777 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6778 * @since 3.5 6779 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}. 6780 */ 6781 @Deprecated 6782 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6783 return Strings.CI.replace(text, searchString, replacement); 6784 } 6785 6786 /** 6787 * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6788 * 6789 * <p> 6790 * A {@code null} reference passed to this method is a no-op. 6791 * </p> 6792 * 6793 * <pre> 6794 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6795 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6796 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6797 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6798 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6799 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6800 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6801 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6802 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6803 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6804 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6805 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6806 * </pre> 6807 * 6808 * @param text text to search and replace in, may be null. 6809 * @param searchString The String to search for (case-insensitive), may be null. 6810 * @param replacement The String to replace it with, may be null. 6811 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6812 * @return The text with any replacements processed, {@code null} if null String input. 6813 * @since 3.5 6814 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}. 6815 */ 6816 @Deprecated 6817 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6818 return Strings.CI.replace(text, searchString, replacement, max); 6819 } 6820 6821 /** 6822 * Replaces a String with another String inside a larger String, once. 6823 * 6824 * <p> 6825 * A {@code null} reference passed to this method is a no-op. 6826 * </p> 6827 * 6828 * <pre> 6829 * StringUtils.replaceOnce(null, *, *) = null 6830 * StringUtils.replaceOnce("", *, *) = "" 6831 * StringUtils.replaceOnce("any", null, *) = "any" 6832 * StringUtils.replaceOnce("any", *, null) = "any" 6833 * StringUtils.replaceOnce("any", "", *) = "any" 6834 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6835 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6836 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6837 * </pre> 6838 * 6839 * @param text text to search and replace in, may be null. 6840 * @param searchString The String to search for, may be null. 6841 * @param replacement The String to replace with, may be null. 6842 * @return The text with any replacements processed, {@code null} if null String input. 6843 * @see #replace(String text, String searchString, String replacement, int max) 6844 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}. 6845 */ 6846 @Deprecated 6847 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6848 return Strings.CS.replaceOnce(text, searchString, replacement); 6849 } 6850 6851 /** 6852 * Case insensitively replaces a String with another String inside a larger String, once. 6853 * 6854 * <p> 6855 * A {@code null} reference passed to this method is a no-op. 6856 * </p> 6857 * 6858 * <pre> 6859 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6860 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6861 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6862 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6863 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6864 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6865 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6866 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6867 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6868 * </pre> 6869 * 6870 * @param text text to search and replace in, may be null. 6871 * @param searchString The String to search for (case-insensitive), may be null. 6872 * @param replacement The String to replace with, may be null. 6873 * @return The text with any replacements processed, {@code null} if null String input. 6874 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6875 * @since 3.5 6876 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}. 6877 */ 6878 @Deprecated 6879 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6880 return Strings.CI.replaceOnce(text, searchString, replacement); 6881 } 6882 6883 /** 6884 * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL} 6885 * option. DOTALL is also known as single-line mode in Perl. 6886 * 6887 * This call is a {@code null} safe equivalent to: 6888 * <ul> 6889 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6890 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6891 * </ul> 6892 * 6893 * <p> 6894 * A {@code null} reference passed to this method is a no-op. 6895 * </p> 6896 * 6897 * <pre>{@code 6898 * StringUtils.replacePattern(null, *, *) = null 6899 * StringUtils.replacePattern("any", (String) null, *) = "any" 6900 * StringUtils.replacePattern("any", *, null) = "any" 6901 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6902 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6903 * StringUtils.replacePattern("", ".+", "zzz") = "" 6904 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6905 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6906 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6907 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6908 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6909 * }</pre> 6910 * 6911 * @param source The source string. 6912 * @param regex The regular expression to which this string is to be matched. 6913 * @param replacement The string to be substituted for each match. 6914 * @return The resulting {@link String}. 6915 * @see #replaceAll(String, String, String) 6916 * @see String#replaceAll(String, String) 6917 * @see Pattern#DOTALL 6918 * @since 3.2 6919 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6920 * @deprecated Use {@link RegExUtils#replacePattern(CharSequence, String, String)}. 6921 */ 6922 @Deprecated 6923 public static String replacePattern(final String source, final String regex, final String replacement) { 6924 return RegExUtils.replacePattern(source, regex, replacement); 6925 } 6926 6927 /** 6928 * Reverses a String as per {@link StringBuilder#reverse()}. 6929 * 6930 * <p> 6931 * A {@code null} String returns {@code null}. 6932 * </p> 6933 * 6934 * <pre> 6935 * StringUtils.reverse(null) = null 6936 * StringUtils.reverse("") = "" 6937 * StringUtils.reverse("bat") = "tab" 6938 * </pre> 6939 * 6940 * @param str The String to reverse, may be null. 6941 * @return The reversed String, {@code null} if null String input. 6942 */ 6943 public static String reverse(final String str) { 6944 if (str == null) { 6945 return null; 6946 } 6947 return new StringBuilder(str).reverse().toString(); 6948 } 6949 6950 /** 6951 * Reverses a String that is delimited by a specific character. 6952 * 6953 * <p> 6954 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}). 6955 * </p> 6956 * 6957 * <pre> 6958 * StringUtils.reverseDelimited(null, *) = null 6959 * StringUtils.reverseDelimited("", *) = "" 6960 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 6961 * StringUtils.reverseDelimited("a.b.c", '.') = "c.b.a" 6962 * </pre> 6963 * 6964 * @param str The String to reverse, may be null. 6965 * @param separatorChar The separator character to use. 6966 * @return The reversed String, {@code null} if null String input. 6967 * @since 2.0 6968 */ 6969 public static String reverseDelimited(final String str, final char separatorChar) { 6970 final String[] strs = split(str, separatorChar); 6971 ArrayUtils.reverse(strs); 6972 return join(strs, separatorChar); 6973 } 6974 6975 /** 6976 * Gets the rightmost {@code len} characters of a String. 6977 * 6978 * <p> 6979 * 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 6980 * returned if len is negative. 6981 * </p> 6982 * 6983 * <pre> 6984 * StringUtils.right(null, *) = null 6985 * StringUtils.right(*, -ve) = "" 6986 * StringUtils.right("", *) = "" 6987 * StringUtils.right("abc", 0) = "" 6988 * StringUtils.right("abc", 2) = "bc" 6989 * StringUtils.right("abc", 4) = "abc" 6990 * </pre> 6991 * 6992 * @param str The String to get the rightmost characters from, may be null. 6993 * @param len The length of the required String. 6994 * @return The rightmost characters, {@code null} if null String input. 6995 */ 6996 public static String right(final String str, final int len) { 6997 if (str == null) { 6998 return null; 6999 } 7000 if (len < 0) { 7001 return EMPTY; 7002 } 7003 if (str.length() <= len) { 7004 return str; 7005 } 7006 int start = str.length() - len; 7007 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 7008 if (splitsSurrogatePair(str, start)) { 7009 start++; 7010 } 7011 return str.substring(start); 7012 } 7013 7014 /** 7015 * Right pad a String with spaces (' '). 7016 * 7017 * <p> 7018 * The String is padded to the size of {@code size}. 7019 * </p> 7020 * 7021 * <pre> 7022 * StringUtils.rightPad(null, *) = null 7023 * StringUtils.rightPad("", 3) = " " 7024 * StringUtils.rightPad("bat", 3) = "bat" 7025 * StringUtils.rightPad("bat", 5) = "bat " 7026 * StringUtils.rightPad("bat", 1) = "bat" 7027 * StringUtils.rightPad("bat", -1) = "bat" 7028 * </pre> 7029 * 7030 * @param str The String to pad out, may be null. 7031 * @param size The size to pad to. 7032 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7033 */ 7034 public static String rightPad(final String str, final int size) { 7035 return rightPad(str, size, ' '); 7036 } 7037 7038 /** 7039 * Right pad a String with a specified character. 7040 * 7041 * <p> 7042 * The String is padded to the size of {@code size}. 7043 * </p> 7044 * 7045 * <pre> 7046 * StringUtils.rightPad(null, *, *) = null 7047 * StringUtils.rightPad("", 3, 'z') = "zzz" 7048 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7049 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7050 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7051 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7052 * </pre> 7053 * 7054 * @param str The String to pad out, may be null. 7055 * @param size The size to pad to. 7056 * @param padChar The character to pad with. 7057 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7058 * @since 2.0 7059 */ 7060 public static String rightPad(final String str, final int size, final char padChar) { 7061 if (str == null || size <= str.length()) { 7062 return str; 7063 } 7064 final int pads = size - str.length(); 7065 if (pads <= 0) { 7066 return str; // returns original String when possible 7067 } 7068 if (pads > PAD_LIMIT) { 7069 return rightPad(str, size, String.valueOf(padChar)); 7070 } 7071 return str.concat(repeat(padChar, pads)); 7072 } 7073 7074 /** 7075 * Right pad a String with a specified String. 7076 * 7077 * <p> 7078 * The String is padded to the size of {@code size}. If the requested padding length would split a Unicode surrogate pair 7079 * in {@code padStr}, the padding is shortened by one {@code char} to avoid introducing an unpaired surrogate by splitting the pair. 7080 * In that case, the returned String has a length of {@code size - 1}. 7081 * </p> 7082 * 7083 * <pre> 7084 * StringUtils.rightPad(null, *, *) = null 7085 * StringUtils.rightPad("", 3, "z") = "zzz" 7086 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7087 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7088 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7089 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7090 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7091 * StringUtils.rightPad("bat", 5, null) = "bat " 7092 * StringUtils.rightPad("bat", 5, "") = "bat " 7093 * StringUtils.rightPad("a", 2, "\uD83D\uDE00") = "a" 7094 * StringUtils.rightPad("a", 3, "\uD83D\uDE00") = "a\uD83D\uDE00" 7095 * </pre> 7096 * 7097 * @param str The String to pad out, may be null. 7098 * @param size The size to pad to. 7099 * @param padStr The String to pad with, null or empty treated as single space. 7100 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7101 */ 7102 public static String rightPad(final String str, final int size, String padStr) { 7103 if (str == null || size <= str.length()) { 7104 return str; 7105 } 7106 if (isEmpty(padStr)) { 7107 padStr = SPACE; 7108 } 7109 final int padLen = padStr.length(); 7110 final int strLen = str.length(); 7111 int pads = size - strLen; 7112 if (pads <= 0) { 7113 return str; // returns original String when possible 7114 } 7115 if (padLen == 1 && pads <= PAD_LIMIT) { 7116 return rightPad(str, size, padStr.charAt(0)); 7117 } 7118 // Keep the padding boundary off the middle of a surrogate pair to avoid introducing a lone surrogate. 7119 if (splitsSurrogatePair(padStr, pads % padLen)) { 7120 pads--; 7121 } 7122 if (pads <= 0) { 7123 return str; 7124 } 7125 if (pads == padLen) { 7126 return str.concat(padStr); 7127 } 7128 if (pads < padLen) { 7129 return str.concat(padStr.substring(0, pads)); 7130 } 7131 final char[] padding = new char[pads]; 7132 final char[] padChars = padStr.toCharArray(); 7133 for (int i = 0; i < pads; i++) { 7134 padding[i] = padChars[i % padLen]; 7135 } 7136 return str.concat(new String(padding)); 7137 } 7138 7139 /** 7140 * Rotate (circular shift) a String of {@code shift} characters. 7141 * <ul> 7142 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7143 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7144 * </ul> 7145 * 7146 * <pre> 7147 * StringUtils.rotate(null, *) = null 7148 * StringUtils.rotate("", *) = "" 7149 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7150 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7151 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7152 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7153 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7154 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7155 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7156 * </pre> 7157 * 7158 * @param str The String to rotate, may be null. 7159 * @param shift number of time to shift (positive : right shift, negative : left shift). 7160 * @return The rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input. 7161 * @since 3.5 7162 */ 7163 public static String rotate(final String str, final int shift) { 7164 if (str == null) { 7165 return null; 7166 } 7167 final int strLen = str.length(); 7168 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7169 return str; 7170 } 7171 final StringBuilder builder = new StringBuilder(strLen); 7172 final int offset = -(shift % strLen); 7173 builder.append(substring(str, offset)); 7174 builder.append(substring(str, 0, offset)); 7175 return builder.toString(); 7176 } 7177 7178 /** 7179 * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 7180 * 7181 * <p> 7182 * 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 7183 * StrTokenizer class. 7184 * </p> 7185 * 7186 * <p> 7187 * A {@code null} input String returns {@code null}. 7188 * </p> 7189 * 7190 * <pre> 7191 * StringUtils.split(null) = null 7192 * StringUtils.split("") = [] 7193 * StringUtils.split("abc def") = ["abc", "def"] 7194 * StringUtils.split("abc def") = ["abc", "def"] 7195 * StringUtils.split(" abc ") = ["abc"] 7196 * </pre> 7197 * 7198 * @param str The String to parse, may be null. 7199 * @return An array of parsed Strings, {@code null} if null String input. 7200 */ 7201 public static String[] split(final String str) { 7202 return split(str, null, -1); 7203 } 7204 7205 /** 7206 * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer. 7207 * 7208 * <p> 7209 * 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 7210 * StrTokenizer class. 7211 * </p> 7212 * 7213 * <p> 7214 * A {@code null} input String returns {@code null}. 7215 * </p> 7216 * 7217 * <pre> 7218 * StringUtils.split(null, *) = null 7219 * StringUtils.split("", *) = [] 7220 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7221 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7222 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7223 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7224 * </pre> 7225 * 7226 * @param str The String to parse, may be null. 7227 * @param separatorChar The character used as the delimiter. 7228 * @return An array of parsed Strings, {@code null} if null String input. 7229 * @since 2.0 7230 */ 7231 public static String[] split(final String str, final char separatorChar) { 7232 return splitWorker(str, separatorChar, false); 7233 } 7234 7235 /** 7236 * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer. 7237 * 7238 * <p> 7239 * 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 7240 * StrTokenizer class. 7241 * </p> 7242 * 7243 * <p> 7244 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7245 * </p> 7246 * 7247 * <pre> 7248 * StringUtils.split(null, *) = null 7249 * StringUtils.split("", *) = [] 7250 * StringUtils.split("abc def", null) = ["abc", "def"] 7251 * StringUtils.split("abc def", " ") = ["abc", "def"] 7252 * StringUtils.split("abc def", " ") = ["abc", "def"] 7253 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7254 * </pre> 7255 * 7256 * @param str The String to parse, may be null. 7257 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7258 * @return An array of parsed Strings, {@code null} if null String input. 7259 */ 7260 public static String[] split(final String str, final String separatorChars) { 7261 return splitWorker(str, separatorChars, -1, false); 7262 } 7263 7264 /** 7265 * Splits the provided text into an array with a maximum length, separators specified. 7266 * 7267 * <p> 7268 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. 7269 * </p> 7270 * 7271 * <p> 7272 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7273 * </p> 7274 * 7275 * <p> 7276 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7277 * strings (including separator characters). 7278 * </p> 7279 * 7280 * <pre> 7281 * StringUtils.split(null, *, *) = null 7282 * StringUtils.split("", *, *) = [] 7283 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7284 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7285 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7286 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7287 * </pre> 7288 * 7289 * @param str The String to parse, may be null. 7290 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7291 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7292 * @return An array of parsed Strings, {@code null} if null String input. 7293 */ 7294 public static String[] split(final String str, final String separatorChars, final int max) { 7295 return splitWorker(str, separatorChars, max, false); 7296 } 7297 7298 /** 7299 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned 7300 * as complete tokens. 7301 * 7302 * <pre> 7303 * StringUtils.splitByCharacterType(null) = null 7304 * StringUtils.splitByCharacterType("") = [] 7305 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7306 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7307 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7308 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7309 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7310 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7311 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7312 * </pre> 7313 * 7314 * @param str The String to split, may be {@code null}. 7315 * @return An array of parsed Strings, {@code null} if null String input. 7316 * @see Character#getType(int) 7317 * @since 2.4 7318 */ 7319 public static String[] splitByCharacterType(final String str) { 7320 return splitByCharacterType(str, false); 7321 } 7322 7323 /** 7324 * 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 7325 * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@link Character#UPPERCASE_LETTER}, if any, 7326 * immediately preceding a token of type {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, 7327 * {@link Character#UPPERCASE_LETTER} token. 7328 * 7329 * @param str The String to split, may be {@code null}. 7330 * @param camelCase whether to use so-called "camel-case" for letter types. 7331 * @return An array of parsed Strings, {@code null} if null String input. 7332 * @since 2.4 7333 */ 7334 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7335 if (str == null) { 7336 return null; 7337 } 7338 if (str.isEmpty()) { 7339 return ArrayUtils.EMPTY_STRING_ARRAY; 7340 } 7341 final char[] c = str.toCharArray(); 7342 final List<String> list = new ArrayList<>(); 7343 int tokenStart = 0; 7344 int currentType = Character.getType(Character.codePointAt(c, tokenStart)); 7345 for (int pos = tokenStart + Character.charCount(Character.codePointAt(c, tokenStart)); pos < c.length;) { 7346 final int codePoint = Character.codePointAt(c, pos); 7347 final int type = Character.getType(codePoint); 7348 final int count = Character.charCount(codePoint); 7349 if (type == currentType) { 7350 pos += count; 7351 continue; 7352 } 7353 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7354 final int newTokenStart = pos - Character.charCount(Character.codePointBefore(c, pos)); 7355 if (newTokenStart != tokenStart) { 7356 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7357 tokenStart = newTokenStart; 7358 } 7359 } else { 7360 list.add(new String(c, tokenStart, pos - tokenStart)); 7361 tokenStart = pos; 7362 } 7363 currentType = type; 7364 pos += count; 7365 } 7366 list.add(new String(c, tokenStart, c.length - tokenStart)); 7367 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7368 } 7369 7370 /** 7371 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned 7372 * as complete tokens, with the following exception: the character of type {@link Character#UPPERCASE_LETTER}, if any, immediately preceding a token of type 7373 * {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@link Character#UPPERCASE_LETTER} token. 7374 * 7375 * <pre> 7376 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7377 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7378 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7379 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7380 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7381 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7382 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7383 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7384 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7385 * </pre> 7386 * 7387 * @param str The String to split, may be {@code null}. 7388 * @return An array of parsed Strings, {@code null} if null String input. 7389 * @see Character#getType(int) 7390 * @since 2.4 7391 */ 7392 public static String[] splitByCharacterTypeCamelCase(final String str) { 7393 return splitByCharacterType(str, true); 7394 } 7395 7396 /** 7397 * Splits the provided text into an array, separator string specified. 7398 * 7399 * <p> 7400 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7401 * </p> 7402 * 7403 * <p> 7404 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7405 * </p> 7406 * 7407 * <pre> 7408 * StringUtils.splitByWholeSeparator(null, *) = null 7409 * StringUtils.splitByWholeSeparator("", *) = [] 7410 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7411 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7412 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7413 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7414 * </pre> 7415 * 7416 * @param str The String to parse, may be null. 7417 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7418 * @return An array of parsed Strings, {@code null} if null String was input. 7419 */ 7420 public static String[] splitByWholeSeparator(final String str, final String separator) { 7421 return splitByWholeSeparatorWorker(str, separator, -1, false); 7422 } 7423 7424 /** 7425 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7426 * 7427 * <p> 7428 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7429 * </p> 7430 * 7431 * <p> 7432 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7433 * </p> 7434 * 7435 * <pre> 7436 * StringUtils.splitByWholeSeparator(null, *, *) = null 7437 * StringUtils.splitByWholeSeparator("", *, *) = [] 7438 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7439 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7440 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7441 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7442 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7443 * </pre> 7444 * 7445 * @param str The String to parse, may be null. 7446 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7447 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7448 * @return An array of parsed Strings, {@code null} if null String was input. 7449 */ 7450 public static String[] splitByWholeSeparator(final String str, final String separator, final int max) { 7451 return splitByWholeSeparatorWorker(str, separator, max, false); 7452 } 7453 7454 /** 7455 * Splits the provided text into an array, separator string specified. 7456 * 7457 * <p> 7458 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7459 * split use the StrTokenizer class. 7460 * </p> 7461 * 7462 * <p> 7463 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7464 * </p> 7465 * 7466 * <pre> 7467 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7468 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7469 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7470 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7471 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7472 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7473 * </pre> 7474 * 7475 * @param str The String to parse, may be null. 7476 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7477 * @return An array of parsed Strings, {@code null} if null String was input. 7478 * @since 2.4 7479 */ 7480 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7481 return splitByWholeSeparatorWorker(str, separator, -1, true); 7482 } 7483 7484 /** 7485 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7486 * 7487 * <p> 7488 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7489 * split use the StrTokenizer class. 7490 * </p> 7491 * 7492 * <p> 7493 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7494 * </p> 7495 * 7496 * <pre> 7497 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7498 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7499 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7500 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7501 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7502 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7503 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7504 * </pre> 7505 * 7506 * @param str The String to parse, may be null. 7507 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7508 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7509 * @return An array of parsed Strings, {@code null} if null String was input. 7510 * @since 2.4 7511 */ 7512 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7513 return splitByWholeSeparatorWorker(str, separator, max, true); 7514 } 7515 7516 /** 7517 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7518 * 7519 * @param str The String to parse, may be {@code null}. 7520 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7521 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7522 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7523 * one separator. 7524 * @return An array of parsed Strings, {@code null} if null String input. 7525 * @since 2.4 7526 */ 7527 private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) { 7528 if (str == null) { 7529 return null; 7530 } 7531 final int len = str.length(); 7532 if (len == 0) { 7533 return ArrayUtils.EMPTY_STRING_ARRAY; 7534 } 7535 if (separator == null || EMPTY.equals(separator)) { 7536 // Split on whitespace. 7537 return splitWorker(str, null, max, preserveAllTokens); 7538 } 7539 final int separatorLength = separator.length(); 7540 final ArrayList<String> substrings = new ArrayList<>(); 7541 int numberOfSubstrings = 0; 7542 int beg = 0; 7543 int end = 0; 7544 while (end < len) { 7545 end = str.indexOf(separator, beg); 7546 if (end > -1) { 7547 if (end > beg) { 7548 numberOfSubstrings += 1; 7549 if (numberOfSubstrings == max) { 7550 end = len; 7551 substrings.add(str.substring(beg)); 7552 } else { 7553 // The following is OK, because String.substring( beg, end ) excludes 7554 // the character at the position 'end'. 7555 substrings.add(str.substring(beg, end)); 7556 // Set the starting point for the next search. 7557 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7558 // which is the right calculation: 7559 beg = end + separatorLength; 7560 } 7561 } else { 7562 // We found a consecutive occurrence of the separator, so skip it. 7563 if (preserveAllTokens) { 7564 numberOfSubstrings += 1; 7565 if (numberOfSubstrings == max) { 7566 end = len; 7567 substrings.add(str.substring(beg)); 7568 } else { 7569 substrings.add(EMPTY); 7570 } 7571 } 7572 beg = end + separatorLength; 7573 } 7574 } else { 7575 // String.substring( beg ) goes from 'beg' to the end of the String. 7576 // beg == len means the String ended on a separator, so the trailing 7577 // token is empty and must be dropped unless empty tokens are preserved. 7578 if (preserveAllTokens || beg < len) { 7579 substrings.add(str.substring(beg)); 7580 } 7581 end = len; 7582 } 7583 } 7584 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7585 } 7586 7587 /** 7588 * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators. 7589 * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}. 7590 * 7591 * <p> 7592 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7593 * split use the StrTokenizer class. 7594 * </p> 7595 * 7596 * <p> 7597 * A {@code null} input String returns {@code null}. 7598 * </p> 7599 * 7600 * <pre> 7601 * StringUtils.splitPreserveAllTokens(null) = null 7602 * StringUtils.splitPreserveAllTokens("") = [] 7603 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7604 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7605 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7606 * </pre> 7607 * 7608 * @param str The String to parse, may be {@code null}. 7609 * @return An array of parsed Strings, {@code null} if null String input. 7610 * @since 2.1 7611 */ 7612 public static String[] splitPreserveAllTokens(final String str) { 7613 return splitWorker(str, null, -1, true); 7614 } 7615 7616 /** 7617 * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7618 * alternative to using StringTokenizer. 7619 * 7620 * <p> 7621 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7622 * split use the StrTokenizer class. 7623 * </p> 7624 * 7625 * <p> 7626 * A {@code null} input String returns {@code null}. 7627 * </p> 7628 * 7629 * <pre> 7630 * StringUtils.splitPreserveAllTokens(null, *) = null 7631 * StringUtils.splitPreserveAllTokens("", *) = [] 7632 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7633 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7634 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7635 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7636 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7637 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7638 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7639 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "a", "b", "c"] 7640 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", "a", "b", "c"] 7641 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", "a", "b", "c", ""] 7642 * </pre> 7643 * 7644 * @param str The String to parse, may be {@code null}. 7645 * @param separatorChar The character used as the delimiter, {@code null} splits on whitespace. 7646 * @return An array of parsed Strings, {@code null} if null String input. 7647 * @since 2.1 7648 */ 7649 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7650 return splitWorker(str, separatorChar, true); 7651 } 7652 7653 /** 7654 * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7655 * alternative to using StringTokenizer. 7656 * 7657 * <p> 7658 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7659 * split use the StrTokenizer class. 7660 * </p> 7661 * 7662 * <p> 7663 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7664 * </p> 7665 * 7666 * <pre> 7667 * StringUtils.splitPreserveAllTokens(null, *) = null 7668 * StringUtils.splitPreserveAllTokens("", *) = [] 7669 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7670 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7671 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", "def"] 7672 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7673 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7674 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7675 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", "cd", "ef"] 7676 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", "cd", "ef"] 7677 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", "cd", "ef"] 7678 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", "cd", "ef", ""] 7679 * </pre> 7680 * 7681 * @param str The String to parse, may be {@code null}. 7682 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7683 * @return An array of parsed Strings, {@code null} if null String input. 7684 * @since 2.1 7685 */ 7686 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7687 return splitWorker(str, separatorChars, -1, true); 7688 } 7689 7690 /** 7691 * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent 7692 * separators. 7693 * 7694 * <p> 7695 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are 7696 * treated as one separator. 7697 * </p> 7698 * 7699 * <p> 7700 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7701 * </p> 7702 * 7703 * <p> 7704 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7705 * strings (including separator characters). 7706 * </p> 7707 * 7708 * <pre> 7709 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7710 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7711 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7712 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7713 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7714 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7715 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7716 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7717 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7718 * </pre> 7719 * 7720 * @param str The String to parse, may be {@code null}. 7721 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7722 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7723 * @return An array of parsed Strings, {@code null} if null String input. 7724 * @since 2.1 7725 */ 7726 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7727 return splitWorker(str, separatorChars, max, true); 7728 } 7729 7730 /** 7731 * Tests whether a {@link String#substring} boundary at {@code index} would fall between the two halves of a surrogate pair, that is the char before 7732 * {@code index} is a high surrogate and the char at {@code index} is its low surrogate. Slicing there leaves a lone surrogate in the result. 7733 * 7734 * @param str The String being sliced. 7735 * @param index A candidate substring boundary, in {@code char} units. 7736 * @return whether slicing at {@code index} would split a surrogate pair. 7737 */ 7738 private static boolean splitsSurrogatePair(final String str, final int index) { 7739 return index > 0 && index < str.length() && Character.isHighSurrogate(str.charAt(index - 1)) && Character.isLowSurrogate(str.charAt(index)); 7740 } 7741 7742 /** 7743 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length. 7744 * 7745 * @param str The String to parse, may be {@code null}. 7746 * @param separatorChar The separate character. 7747 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7748 * one separator. 7749 * @return An array of parsed Strings, {@code null} if null String input. 7750 */ 7751 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7752 // Performance tuned for 2.0 (JDK1.4) 7753 if (str == null) { 7754 return null; 7755 } 7756 final int len = str.length(); 7757 if (len == 0) { 7758 return ArrayUtils.EMPTY_STRING_ARRAY; 7759 } 7760 final List<String> list = new ArrayList<>(); 7761 int i = 0; 7762 int start = 0; 7763 boolean match = false; 7764 boolean lastMatch = false; 7765 while (i < len) { 7766 if (str.charAt(i) == separatorChar) { 7767 if (match || preserveAllTokens) { 7768 list.add(str.substring(start, i)); 7769 match = false; 7770 lastMatch = true; 7771 } 7772 start = ++i; 7773 continue; 7774 } 7775 lastMatch = false; 7776 match = true; 7777 i++; 7778 } 7779 if (match || preserveAllTokens && lastMatch) { 7780 list.add(str.substring(start, i)); 7781 } 7782 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7783 } 7784 7785 /** 7786 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length. 7787 * 7788 * @param str The String to parse, may be {@code null}. 7789 * @param separatorChars The separate character. 7790 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7791 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7792 * one separator. 7793 * @return An array of parsed Strings, {@code null} if null String input. 7794 */ 7795 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7796 // Performance tuned for 2.0 (JDK1.4) 7797 // Direct code is quicker than StringTokenizer. 7798 // Also, StringTokenizer uses isSpace() not isWhitespace() 7799 if (str == null) { 7800 return null; 7801 } 7802 final int len = str.length(); 7803 if (len == 0) { 7804 return ArrayUtils.EMPTY_STRING_ARRAY; 7805 } 7806 final List<String> list = new ArrayList<>(); 7807 int sizePlus1 = 1; 7808 int i = 0; 7809 int start = 0; 7810 boolean match = false; 7811 boolean lastMatch = false; 7812 if (separatorChars == null) { 7813 // Null separator means use whitespace 7814 while (i < len) { 7815 if (Character.isWhitespace(str.charAt(i))) { 7816 if (match || preserveAllTokens) { 7817 lastMatch = true; 7818 if (sizePlus1++ == max) { 7819 i = len; 7820 lastMatch = false; 7821 } 7822 list.add(str.substring(start, i)); 7823 match = false; 7824 } 7825 start = ++i; 7826 continue; 7827 } 7828 lastMatch = false; 7829 match = true; 7830 i++; 7831 } 7832 } else if (separatorChars.length() == 1) { 7833 // Optimize 1 character case 7834 final char sep = separatorChars.charAt(0); 7835 while (i < len) { 7836 if (str.charAt(i) == sep) { 7837 if (match || preserveAllTokens) { 7838 lastMatch = true; 7839 if (sizePlus1++ == max) { 7840 i = len; 7841 lastMatch = false; 7842 } 7843 list.add(str.substring(start, i)); 7844 match = false; 7845 } 7846 start = ++i; 7847 continue; 7848 } 7849 lastMatch = false; 7850 match = true; 7851 i++; 7852 } 7853 } else { 7854 // standard case 7855 while (i < len) { 7856 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 7857 if (match || preserveAllTokens) { 7858 lastMatch = true; 7859 if (sizePlus1++ == max) { 7860 i = len; 7861 lastMatch = false; 7862 } 7863 list.add(str.substring(start, i)); 7864 match = false; 7865 } 7866 start = ++i; 7867 continue; 7868 } 7869 lastMatch = false; 7870 match = true; 7871 i++; 7872 } 7873 } 7874 if (match || preserveAllTokens && lastMatch) { 7875 list.add(str.substring(start, i)); 7876 } 7877 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7878 } 7879 7880 /** 7881 * Tests if a CharSequence starts with a specified prefix. 7882 * 7883 * <p> 7884 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 7885 * </p> 7886 * 7887 * <pre> 7888 * StringUtils.startsWith(null, null) = true 7889 * StringUtils.startsWith(null, "abc") = false 7890 * StringUtils.startsWith("abcdef", null) = false 7891 * StringUtils.startsWith("abcdef", "abc") = true 7892 * StringUtils.startsWith("ABCDEF", "abc") = false 7893 * </pre> 7894 * 7895 * @param str The CharSequence to check, may be null. 7896 * @param prefix The prefix to find, may be null. 7897 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}. 7898 * @see String#startsWith(String) 7899 * @since 2.4 7900 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 7901 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}. 7902 */ 7903 @Deprecated 7904 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7905 return Strings.CS.startsWith(str, prefix); 7906 } 7907 7908 /** 7909 * Tests if a CharSequence starts with any of the provided case-sensitive prefixes. 7910 * 7911 * <pre> 7912 * StringUtils.startsWithAny(null, null) = false 7913 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 7914 * StringUtils.startsWithAny("abcxyz", null) = false 7915 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 7916 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 7917 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7918 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 7919 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 7920 * </pre> 7921 * 7922 * @param sequence The CharSequence to check, may be null. 7923 * @param searchStrings The case-sensitive CharSequence prefixes, may be empty or contain {@code null}. 7924 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with 7925 * any of the provided case-sensitive {@code searchStrings}. 7926 * @see StringUtils#startsWith(CharSequence, CharSequence) 7927 * @since 2.5 7928 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 7929 * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)}. 7930 */ 7931 @Deprecated 7932 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 7933 return Strings.CS.startsWithAny(sequence, searchStrings); 7934 } 7935 7936 /** 7937 * Case-insensitive check if a CharSequence starts with a specified prefix. 7938 * 7939 * <p> 7940 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 7941 * </p> 7942 * 7943 * <pre> 7944 * StringUtils.startsWithIgnoreCase(null, null) = true 7945 * StringUtils.startsWithIgnoreCase(null, "abc") = false 7946 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 7947 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 7948 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 7949 * </pre> 7950 * 7951 * @param str The CharSequence to check, may be null. 7952 * @param prefix The prefix to find, may be null. 7953 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}. 7954 * @see String#startsWith(String) 7955 * @since 2.4 7956 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 7957 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}. 7958 */ 7959 @Deprecated 7960 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 7961 return Strings.CI.startsWith(str, prefix); 7962 } 7963 7964 /** 7965 * Strips whitespace from the start and end of a String. 7966 * 7967 * <p> 7968 * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 7969 * </p> 7970 * 7971 * <p> 7972 * A {@code null} input String returns {@code null}. 7973 * </p> 7974 * 7975 * <pre> 7976 * StringUtils.strip(null) = null 7977 * StringUtils.strip("") = "" 7978 * StringUtils.strip(" ") = "" 7979 * StringUtils.strip("abc") = "abc" 7980 * StringUtils.strip(" abc") = "abc" 7981 * StringUtils.strip("abc ") = "abc" 7982 * StringUtils.strip(" abc ") = "abc" 7983 * StringUtils.strip(" ab c ") = "ab c" 7984 * </pre> 7985 * 7986 * @param str The String to remove whitespace from, may be null. 7987 * @return The stripped String, {@code null} if null String input. 7988 */ 7989 public static String strip(final String str) { 7990 return strip(str, null); 7991 } 7992 7993 /** 7994 * 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 7995 * to be controlled. 7996 * 7997 * <p> 7998 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7999 * </p> 8000 * 8001 * <p> 8002 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use 8003 * {@link #strip(String)}. 8004 * </p> 8005 * 8006 * <pre> 8007 * StringUtils.strip(null, *) = null 8008 * StringUtils.strip("", *) = "" 8009 * StringUtils.strip("abc", null) = "abc" 8010 * StringUtils.strip(" abc", null) = "abc" 8011 * StringUtils.strip("abc ", null) = "abc" 8012 * StringUtils.strip(" abc ", null) = "abc" 8013 * StringUtils.strip(" abcyx", "xyz") = " abc" 8014 * </pre> 8015 * 8016 * @param str The String to remove characters from, may be null. 8017 * @param stripChars The characters to remove, null treated as whitespace. 8018 * @return The stripped String, {@code null} if null String input. 8019 */ 8020 public static String strip(String str, final String stripChars) { 8021 str = stripStart(str, stripChars); 8022 return stripEnd(str, stripChars); 8023 } 8024 8025 /** 8026 * Removes diacritics (~= accents) from a string. The case will not be altered. 8027 * <p> 8028 * For instance, 'à' will be replaced by 'a'. 8029 * </p> 8030 * <p> 8031 * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a> 8032 * </p> 8033 * <p> 8034 * Be aware that this NFKD compatibility decomposition can map non-letter compatibility forms (fullwidth, small-form, math-symbol variants of {@code <}, 8035 * {@code >}, {@code /}, and so on) to their ASCII counterparts. 8036 * </p> 8037 * 8038 * <pre> 8039 * StringUtils.stripAccents(null) = null 8040 * StringUtils.stripAccents("") = "" 8041 * StringUtils.stripAccents("control") = "control" 8042 * StringUtils.stripAccents("éclair") = "eclair" 8043 * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3") = "abc123" 8044 * StringUtils.stripAccents("\u00BC \u00BD \u00BE") = "1⁄4 1⁄2 3⁄4" 8045 * </pre> 8046 * <p> 8047 * See also <a href="https://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>. 8048 * </p> 8049 * 8050 * @param input String to be stripped. 8051 * @return input text with diacritics removed. 8052 * @since 3.0 8053 */ 8054 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: 8055 // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 8056 public static String stripAccents(final String input) { 8057 if (isEmpty(input)) { 8058 return input; 8059 } 8060 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD)); 8061 convertRemainingAccentCharacters(decomposed); 8062 final String stripped = STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 8063 return Normalizer.normalize(stripped, Normalizer.Form.NFC); 8064 } 8065 8066 /** 8067 * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}. 8068 * 8069 * <p> 8070 * 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 8071 * {@code null} array entry will be ignored. 8072 * </p> 8073 * 8074 * <pre> 8075 * StringUtils.stripAll(null) = null 8076 * StringUtils.stripAll([]) = [] 8077 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 8078 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 8079 * </pre> 8080 * 8081 * @param strs The array to remove whitespace from, may be null. 8082 * @return The stripped Strings, {@code null} if null array input. 8083 */ 8084 public static String[] stripAll(final String... strs) { 8085 return stripAll(strs, null); 8086 } 8087 8088 /** 8089 * Strips any of a set of characters from the start and end of every String in an array. 8090 * <p> 8091 * Whitespace is defined by {@link Character#isWhitespace(char)}. 8092 * </p> 8093 * 8094 * <p> 8095 * 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 8096 * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}. 8097 * </p> 8098 * 8099 * <pre> 8100 * StringUtils.stripAll(null, *) = null 8101 * StringUtils.stripAll([], *) = [] 8102 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 8103 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 8104 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 8105 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 8106 * </pre> 8107 * 8108 * @param strs The array to remove characters from, may be null. 8109 * @param stripChars The characters to remove, null treated as whitespace. 8110 * @return The stripped Strings, {@code null} if null array input. 8111 */ 8112 public static String[] stripAll(final String[] strs, final String stripChars) { 8113 final int strsLen = ArrayUtils.getLength(strs); 8114 if (strsLen == 0) { 8115 return strs; 8116 } 8117 return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars)); 8118 } 8119 8120 /** 8121 * Strips any of a set of characters from the end of a String. 8122 * 8123 * <p> 8124 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 8125 * </p> 8126 * 8127 * <p> 8128 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 8129 * </p> 8130 * 8131 * <p> 8132 * The characters in {@code stripChars} are treated individually, not as a suffix. To remove a suffix as a whole, 8133 * use {@link Strings#removeEnd(String, CharSequence)} on {@link Strings#CS} instead. 8134 * </p> 8135 * 8136 * <pre> 8137 * StringUtils.stripEnd(null, *) = null 8138 * StringUtils.stripEnd("", *) = "" 8139 * StringUtils.stripEnd("abc", "") = "abc" 8140 * StringUtils.stripEnd("abc", null) = "abc" 8141 * StringUtils.stripEnd(" abc", null) = " abc" 8142 * StringUtils.stripEnd("abc ", null) = "abc" 8143 * StringUtils.stripEnd(" abc ", null) = " abc" 8144 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 8145 * StringUtils.stripEnd("120.00", ".0") = "12" 8146 * StringUtils.stripEnd("85123116", "16") = "85123" 8147 * </pre> 8148 * 8149 * @param str The String to remove characters from, may be null. 8150 * @param stripChars The set of characters to remove, null treated as whitespace. 8151 * @return The stripped String, {@code null} if null String input. 8152 */ 8153 public static String stripEnd(final String str, final String stripChars) { 8154 int end = length(str); 8155 if (end == 0) { 8156 return str; 8157 } 8158 if (stripChars == null) { 8159 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 8160 end--; 8161 } 8162 } else if (stripChars.isEmpty()) { 8163 return str; 8164 } else { 8165 while (end != 0) { 8166 final int codePoint = str.codePointBefore(end); 8167 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) { 8168 break; 8169 } 8170 end -= Character.charCount(codePoint); 8171 } 8172 } 8173 return str.substring(0, end); 8174 } 8175 8176 /** 8177 * Strips any of a set of characters from the start of a String. 8178 * 8179 * <p> 8180 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 8181 * </p> 8182 * 8183 * <p> 8184 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 8185 * </p> 8186 * 8187 * <pre> 8188 * StringUtils.stripStart(null, *) = null 8189 * StringUtils.stripStart("", *) = "" 8190 * StringUtils.stripStart("abc", "") = "abc" 8191 * StringUtils.stripStart("abc", null) = "abc" 8192 * StringUtils.stripStart(" abc", null) = "abc" 8193 * StringUtils.stripStart("abc ", null) = "abc " 8194 * StringUtils.stripStart(" abc ", null) = "abc " 8195 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8196 * </pre> 8197 * 8198 * @param str The String to remove characters from, may be null. 8199 * @param stripChars The characters to remove, null treated as whitespace. 8200 * @return The stripped String, {@code null} if null String input. 8201 */ 8202 public static String stripStart(final String str, final String stripChars) { 8203 final int strLen = length(str); 8204 if (strLen == 0) { 8205 return str; 8206 } 8207 int start = 0; 8208 if (stripChars == null) { 8209 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8210 start++; 8211 } 8212 } else if (stripChars.isEmpty()) { 8213 return str; 8214 } else { 8215 while (start != strLen) { 8216 final int codePoint = str.codePointAt(start); 8217 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) { 8218 break; 8219 } 8220 start += Character.charCount(codePoint); 8221 } 8222 } 8223 return str.substring(start); 8224 } 8225 8226 /** 8227 * Strips whitespace from the start and end of a String returning an empty String if {@code null} input. 8228 * 8229 * <p> 8230 * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8231 * </p> 8232 * 8233 * <pre> 8234 * StringUtils.stripToEmpty(null) = "" 8235 * StringUtils.stripToEmpty("") = "" 8236 * StringUtils.stripToEmpty(" ") = "" 8237 * StringUtils.stripToEmpty("abc") = "abc" 8238 * StringUtils.stripToEmpty(" abc") = "abc" 8239 * StringUtils.stripToEmpty("abc ") = "abc" 8240 * StringUtils.stripToEmpty(" abc ") = "abc" 8241 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8242 * </pre> 8243 * 8244 * @param str The String to be stripped, may be null. 8245 * @return The trimmed String, or an empty String if {@code null} input. 8246 * @since 2.0 8247 */ 8248 public static String stripToEmpty(final String str) { 8249 return str == null ? EMPTY : strip(str, null); 8250 } 8251 8252 /** 8253 * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip. 8254 * 8255 * <p> 8256 * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8257 * </p> 8258 * 8259 * <pre> 8260 * StringUtils.stripToNull(null) = null 8261 * StringUtils.stripToNull("") = null 8262 * StringUtils.stripToNull(" ") = null 8263 * StringUtils.stripToNull("abc") = "abc" 8264 * StringUtils.stripToNull(" abc") = "abc" 8265 * StringUtils.stripToNull("abc ") = "abc" 8266 * StringUtils.stripToNull(" abc ") = "abc" 8267 * StringUtils.stripToNull(" ab c ") = "ab c" 8268 * </pre> 8269 * 8270 * @param str The String to be stripped, may be null. 8271 * @return The stripped String, {@code null} if whitespace, empty or null String input. 8272 * @since 2.0 8273 */ 8274 public static String stripToNull(String str) { 8275 if (str == null) { 8276 return null; 8277 } 8278 str = strip(str, null); 8279 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here 8280 } 8281 8282 /** 8283 * Gets a substring from the specified String avoiding exceptions. 8284 * 8285 * <p> 8286 * A negative start position can be used to start {@code n} characters from the end of the String. 8287 * </p> 8288 * 8289 * <p> 8290 * A {@code null} String will return {@code null}. An empty ("") String will return "". 8291 * </p> 8292 * 8293 * <pre> 8294 * StringUtils.substring(null, *) = null 8295 * StringUtils.substring("", *) = "" 8296 * StringUtils.substring("abc", 0) = "abc" 8297 * StringUtils.substring("abc", 2) = "c" 8298 * StringUtils.substring("abc", 4) = "" 8299 * StringUtils.substring("abc", -2) = "bc" 8300 * StringUtils.substring("abc", -4) = "abc" 8301 * </pre> 8302 * 8303 * @param str The String to get the substring from, may be null. 8304 * @param start The position to start from, negative means count back from the end of the String by this many characters. 8305 * @return substring from start position, {@code null} if null String input. 8306 */ 8307 public static String substring(final String str, int start) { 8308 if (str == null) { 8309 return null; 8310 } 8311 // handle negatives, which means last n characters 8312 if (start < 0) { 8313 start = str.length() + start; // remember start is negative 8314 } 8315 if (start < 0) { 8316 start = 0; 8317 } 8318 if (start > str.length()) { 8319 return EMPTY; 8320 } 8321 return str.substring(start); 8322 } 8323 8324 /** 8325 * Gets a substring from the specified String avoiding exceptions. 8326 * 8327 * <p> 8328 * A negative start position can be used to start/end {@code n} characters from the end of the String. 8329 * </p> 8330 * 8331 * <p> 8332 * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is 8333 * 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 8334 * relative to the end of the String. 8335 * </p> 8336 * 8337 * <p> 8338 * If {@code start} is not strictly to the left of {@code end}, "" is returned. 8339 * </p> 8340 * 8341 * <pre> 8342 * StringUtils.substring(null, *, *) = null 8343 * StringUtils.substring("", * , *) = ""; 8344 * StringUtils.substring("abc", 0, 2) = "ab" 8345 * StringUtils.substring("abc", 2, 0) = "" 8346 * StringUtils.substring("abc", 2, 4) = "c" 8347 * StringUtils.substring("abc", 4, 6) = "" 8348 * StringUtils.substring("abc", 2, 2) = "" 8349 * StringUtils.substring("abc", -2, -1) = "b" 8350 * StringUtils.substring("abc", -4, 2) = "ab" 8351 * </pre> 8352 * 8353 * @param str The String to get the substring from, may be null. 8354 * @param start The position to start from, negative means count back from the end of the String by this many characters. 8355 * @param end The position to end at (exclusive), negative means count back from the end of the String by this many characters. 8356 * @return substring from start position to end position, {@code null} if null String input. 8357 */ 8358 public static String substring(final String str, int start, int end) { 8359 if (str == null) { 8360 return null; 8361 } 8362 // handle negatives 8363 if (end < 0) { 8364 end = str.length() + end; // remember end is negative 8365 } 8366 if (start < 0) { 8367 start = str.length() + start; // remember start is negative 8368 } 8369 // check length next 8370 if (end > str.length()) { 8371 end = str.length(); 8372 } 8373 // if start is greater than end, return "" 8374 if (start > end) { 8375 return EMPTY; 8376 } 8377 if (start < 0) { 8378 start = 0; 8379 } 8380 if (end < 0) { 8381 end = 0; 8382 } 8383 return str.substring(start, end); 8384 } 8385 8386 /** 8387 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8388 * 8389 * <p> 8390 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8391 * </p> 8392 * 8393 * <p> 8394 * If nothing is found, the empty string is returned. 8395 * </p> 8396 * 8397 * <pre> 8398 * StringUtils.substringAfter(null, *) = null 8399 * StringUtils.substringAfter("", *) = "" 8400 * StringUtils.substringAfter("abc", 'a') = "bc" 8401 * StringUtils.substringAfter("abcba", 'b') = "cba" 8402 * StringUtils.substringAfter("abc", 'c') = "" 8403 * StringUtils.substringAfter("abc", 'd') = "" 8404 * StringUtils.substringAfter(" abc", 32) = "abc" 8405 * </pre> 8406 * 8407 * @param str The String to get a substring from, may be null. 8408 * @param find The character (Unicode code point) to find. 8409 * @return The substring after the first occurrence of the specified character, {@code null} if null String input. 8410 * @since 3.11 8411 */ 8412 public static String substringAfter(final String str, final int find) { 8413 if (isEmpty(str)) { 8414 return str; 8415 } 8416 final int pos = str.indexOf(find); 8417 if (pos == INDEX_NOT_FOUND) { 8418 return EMPTY; 8419 } 8420 return str.substring(pos + Character.charCount(find)); 8421 } 8422 8423 /** 8424 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8425 * 8426 * <p> 8427 * 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 8428 * empty string if the input string is not {@code null}. 8429 * </p> 8430 * 8431 * <p> 8432 * If nothing is found, the empty string is returned. 8433 * </p> 8434 * 8435 * <pre> 8436 * StringUtils.substringAfter(null, *) = null 8437 * StringUtils.substringAfter("", *) = "" 8438 * StringUtils.substringAfter(*, null) = "" 8439 * StringUtils.substringAfter("abc", "a") = "bc" 8440 * StringUtils.substringAfter("abcba", "b") = "cba" 8441 * StringUtils.substringAfter("abc", "c") = "" 8442 * StringUtils.substringAfter("abc", "d") = "" 8443 * StringUtils.substringAfter("abc", "") = "abc" 8444 * </pre> 8445 * 8446 * @param str The String to get a substring from, may be null. 8447 * @param find The String to find, may be null. 8448 * @return The substring after the first occurrence of the specified string, {@code null} if null String input. 8449 * @since 2.0 8450 */ 8451 public static String substringAfter(final String str, final String find) { 8452 if (isEmpty(str)) { 8453 return str; 8454 } 8455 if (find == null) { 8456 return EMPTY; 8457 } 8458 final int pos = str.indexOf(find); 8459 if (pos == INDEX_NOT_FOUND) { 8460 return EMPTY; 8461 } 8462 return str.substring(pos + find.length()); 8463 } 8464 8465 /** 8466 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8467 * 8468 * <p> 8469 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8470 * </p> 8471 * 8472 * <p> 8473 * If nothing is found, the empty string is returned. 8474 * </p> 8475 * 8476 * <pre> 8477 * StringUtils.substringAfterLast(null, *) = null 8478 * StringUtils.substringAfterLast("", *) = "" 8479 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8480 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8481 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8482 * StringUtils.substringAfterLast("abc", 'c') = "" 8483 * StringUtils.substringAfterLast("a", 'a') = "" 8484 * StringUtils.substringAfterLast("a", 'z') = "" 8485 * </pre> 8486 * 8487 * @param str The String to get a substring from, may be null. 8488 * @param find The character (Unicode code point) to find. 8489 * @return The substring after the last occurrence of the specified character, {@code null} if null String input. 8490 * @since 3.11 8491 */ 8492 public static String substringAfterLast(final String str, final int find) { 8493 if (isEmpty(str)) { 8494 return str; 8495 } 8496 final int pos = str.lastIndexOf(find); 8497 if (pos == INDEX_NOT_FOUND || pos == str.length() - Character.charCount(find)) { 8498 return EMPTY; 8499 } 8500 return str.substring(pos + Character.charCount(find)); 8501 } 8502 8503 /** 8504 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8505 * 8506 * <p> 8507 * 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 8508 * return the empty string if the input string is not {@code null}. 8509 * </p> 8510 * 8511 * <p> 8512 * If nothing is found, the empty string is returned. 8513 * </p> 8514 * 8515 * <pre> 8516 * StringUtils.substringAfterLast(null, *) = null 8517 * StringUtils.substringAfterLast("", *) = "" 8518 * StringUtils.substringAfterLast(*, "") = "" 8519 * StringUtils.substringAfterLast(*, null) = "" 8520 * StringUtils.substringAfterLast("abc", "a") = "bc" 8521 * StringUtils.substringAfterLast("abcba", "b") = "a" 8522 * StringUtils.substringAfterLast("abc", "c") = "" 8523 * StringUtils.substringAfterLast("a", "a") = "" 8524 * StringUtils.substringAfterLast("a", "z") = "" 8525 * </pre> 8526 * 8527 * @param str The String to get a substring from, may be null. 8528 * @param find The String to find, may be null. 8529 * @return The substring after the last occurrence of the specified string, {@code null} if null String input. 8530 * @since 2.0 8531 */ 8532 public static String substringAfterLast(final String str, final String find) { 8533 if (isEmpty(str)) { 8534 return str; 8535 } 8536 if (isEmpty(find)) { 8537 return EMPTY; 8538 } 8539 final int pos = str.lastIndexOf(find); 8540 if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) { 8541 return EMPTY; 8542 } 8543 return str.substring(pos + find.length()); 8544 } 8545 8546 /** 8547 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8548 * 8549 * <p> 8550 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8551 * </p> 8552 * 8553 * <p> 8554 * If nothing is found, the string input is returned. 8555 * </p> 8556 * 8557 * <pre> 8558 * StringUtils.substringBefore(null, *) = null 8559 * StringUtils.substringBefore("", *) = "" 8560 * StringUtils.substringBefore("abc", 'a') = "" 8561 * StringUtils.substringBefore("abcba", 'b') = "a" 8562 * StringUtils.substringBefore("abc", 'c') = "ab" 8563 * StringUtils.substringBefore("abc", 'd') = "abc" 8564 * </pre> 8565 * 8566 * @param str The String to get a substring from, may be null. 8567 * @param find The character (Unicode code point) to find. 8568 * @return The substring before the first occurrence of the specified character, {@code null} if null String input. 8569 * @since 3.12.0 8570 */ 8571 public static String substringBefore(final String str, final int find) { 8572 if (isEmpty(str)) { 8573 return str; 8574 } 8575 final int pos = str.indexOf(find); 8576 if (pos == INDEX_NOT_FOUND) { 8577 return str; 8578 } 8579 return str.substring(0, pos); 8580 } 8581 8582 /** 8583 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8584 * 8585 * <p> 8586 * 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 8587 * input string. 8588 * </p> 8589 * 8590 * <p> 8591 * If nothing is found, the string input is returned. 8592 * </p> 8593 * 8594 * <pre> 8595 * StringUtils.substringBefore(null, *) = null 8596 * StringUtils.substringBefore("", *) = "" 8597 * StringUtils.substringBefore("abc", "a") = "" 8598 * StringUtils.substringBefore("abcba", "b") = "a" 8599 * StringUtils.substringBefore("abc", "c") = "ab" 8600 * StringUtils.substringBefore("abc", "d") = "abc" 8601 * StringUtils.substringBefore("abc", "") = "" 8602 * StringUtils.substringBefore("abc", null) = "abc" 8603 * </pre> 8604 * 8605 * @param str The String to get a substring from, may be null. 8606 * @param find The String to find, may be null. 8607 * @return The substring before the first occurrence of the specified string, {@code null} if null String input. 8608 * @since 2.0 8609 */ 8610 public static String substringBefore(final String str, final String find) { 8611 if (isEmpty(str) || find == null) { 8612 return str; 8613 } 8614 if (find.isEmpty()) { 8615 return EMPTY; 8616 } 8617 final int pos = str.indexOf(find); 8618 if (pos == INDEX_NOT_FOUND) { 8619 return str; 8620 } 8621 return str.substring(0, pos); 8622 } 8623 8624 /** 8625 * Gets the substring before the last occurrence of a separator. The separator is not returned. 8626 * 8627 * <p> 8628 * 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 8629 * return the input string. 8630 * </p> 8631 * 8632 * <p> 8633 * If nothing is found, the string input is returned. 8634 * </p> 8635 * 8636 * <pre> 8637 * StringUtils.substringBeforeLast(null, *) = null 8638 * StringUtils.substringBeforeLast("", *) = "" 8639 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8640 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8641 * StringUtils.substringBeforeLast("a", "a") = "" 8642 * StringUtils.substringBeforeLast("a", "z") = "a" 8643 * StringUtils.substringBeforeLast("a", null) = "a" 8644 * StringUtils.substringBeforeLast("a", "") = "a" 8645 * </pre> 8646 * 8647 * @param str The String to get a substring from, may be null. 8648 * @param find The String to find, may be null. 8649 * @return The substring before the last occurrence of the specified string, {@code null} if null String input. 8650 * @since 2.0 8651 */ 8652 public static String substringBeforeLast(final String str, final String find) { 8653 if (isEmpty(str) || isEmpty(find)) { 8654 return str; 8655 } 8656 final int pos = str.lastIndexOf(find); 8657 if (pos == INDEX_NOT_FOUND) { 8658 return str; 8659 } 8660 return str.substring(0, pos); 8661 } 8662 8663 /** 8664 * Gets the String that is nested in between two instances of the same String. 8665 * 8666 * <p> 8667 * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}. 8668 * </p> 8669 * 8670 * <pre> 8671 * StringUtils.substringBetween(null, *) = null 8672 * StringUtils.substringBetween("", "") = "" 8673 * StringUtils.substringBetween("", "tag") = null 8674 * StringUtils.substringBetween("tagabctag", null) = null 8675 * StringUtils.substringBetween("tagabctag", "") = "" 8676 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8677 * </pre> 8678 * 8679 * @param str The String containing the substring, may be null. 8680 * @param tag The String before and after the substring, may be null. 8681 * @return The substring, {@code null} if no match. 8682 * @since 2.0 8683 */ 8684 public static String substringBetween(final String str, final String tag) { 8685 return substringBetween(str, tag, tag); 8686 } 8687 8688 /** 8689 * Gets the String that is nested in between two Strings. Only the first match is returned. 8690 * 8691 * <p> 8692 * 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 8693 * empty string. 8694 * </p> 8695 * 8696 * <pre> 8697 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8698 * StringUtils.substringBetween(null, *, *) = null 8699 * StringUtils.substringBetween(*, null, *) = null 8700 * StringUtils.substringBetween(*, *, null) = null 8701 * StringUtils.substringBetween("", "", "") = "" 8702 * StringUtils.substringBetween("", "", "]") = null 8703 * StringUtils.substringBetween("", "[", "]") = null 8704 * StringUtils.substringBetween("yabcz", "", "") = "" 8705 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8706 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8707 * </pre> 8708 * 8709 * @param str The String containing the substring, may be null. 8710 * @param open The String before the substring, may be null. 8711 * @param close The String after the substring, may be null. 8712 * @return The substring, {@code null} if no match. 8713 * @since 2.0 8714 */ 8715 public static String substringBetween(final String str, final String open, final String close) { 8716 if (!ObjectUtils.allNotNull(str, open, close)) { 8717 return null; 8718 } 8719 final int start = str.indexOf(open); 8720 if (start != INDEX_NOT_FOUND) { 8721 final int end = str.indexOf(close, start + open.length()); 8722 if (end != INDEX_NOT_FOUND) { 8723 return str.substring(start + open.length(), end); 8724 } 8725 } 8726 return null; 8727 } 8728 8729 /** 8730 * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array. 8731 * 8732 * <p> 8733 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns 8734 * {@code null} (no match). 8735 * </p> 8736 * 8737 * <pre> 8738 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8739 * StringUtils.substringsBetween(null, *, *) = null 8740 * StringUtils.substringsBetween(*, null, *) = null 8741 * StringUtils.substringsBetween(*, *, null) = null 8742 * StringUtils.substringsBetween("", "[", "]") = [] 8743 * </pre> 8744 * 8745 * @param str The String containing the substrings, null returns null, empty returns empty. 8746 * @param open The String identifying the start of the substring, empty returns null. 8747 * @param close The String identifying the end of the substring, empty returns null. 8748 * @return A String Array of substrings, or {@code null} if no match. 8749 * @since 2.3 8750 */ 8751 public static String[] substringsBetween(final String str, final String open, final String close) { 8752 if (str == null || isEmpty(open) || isEmpty(close)) { 8753 return null; 8754 } 8755 final int strLen = str.length(); 8756 if (strLen == 0) { 8757 return ArrayUtils.EMPTY_STRING_ARRAY; 8758 } 8759 final int closeLen = close.length(); 8760 final int openLen = open.length(); 8761 final List<String> list = new ArrayList<>(); 8762 int pos = 0; 8763 while (pos < strLen - closeLen) { 8764 int start = str.indexOf(open, pos); 8765 if (start < 0) { 8766 break; 8767 } 8768 start += openLen; 8769 final int end = str.indexOf(close, start); 8770 if (end < 0) { 8771 break; 8772 } 8773 list.add(str.substring(start, end)); 8774 pos = end + closeLen; 8775 } 8776 if (list.isEmpty()) { 8777 return null; 8778 } 8779 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8780 } 8781 8782 /** 8783 * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case. 8784 * 8785 * <ul> 8786 * <li>Upper case character converts to Lower case</li> 8787 * <li>Title case character converts to Lower case</li> 8788 * <li>Lower case character converts to Upper case</li> 8789 * </ul> 8790 * 8791 * <p> 8792 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}. 8793 * </p> 8794 * 8795 * <pre> 8796 * StringUtils.swapCase(null) = null 8797 * StringUtils.swapCase("") = "" 8798 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8799 * </pre> 8800 * 8801 * <p> 8802 * 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 8803 * functionality is available in org.apache.commons.lang3.text.WordUtils. 8804 * </p> 8805 * 8806 * @param str The String to swap case, may be null. 8807 * @return The changed String, {@code null} if null String input. 8808 */ 8809 public static String swapCase(final String str) { 8810 if (isEmpty(str)) { 8811 return str; 8812 } 8813 final int strLen = str.length(); 8814 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8815 int outOffset = 0; 8816 for (int i = 0; i < strLen;) { 8817 final int oldCodepoint = str.codePointAt(i); 8818 final int newCodePoint; 8819 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8820 newCodePoint = Character.toLowerCase(oldCodepoint); 8821 } else if (Character.isLowerCase(oldCodepoint)) { 8822 newCodePoint = Character.toUpperCase(oldCodepoint); 8823 } else { 8824 newCodePoint = oldCodepoint; 8825 } 8826 newCodePoints[outOffset++] = newCodePoint; 8827 i += Character.charCount(newCodePoint); 8828 } 8829 return new String(newCodePoints, 0, outOffset); 8830 } 8831 8832 /** 8833 * Converts a {@link CharSequence} into an array of code points. 8834 * 8835 * <p> 8836 * 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 8837 * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is. 8838 * </p> 8839 * 8840 * <pre> 8841 * StringUtils.toCodePoints(null) = null 8842 * StringUtils.toCodePoints("") = [] // empty array 8843 * </pre> 8844 * 8845 * @param cs The character sequence to convert. 8846 * @return An array of code points. 8847 * @since 3.6 8848 */ 8849 public static int[] toCodePoints(final CharSequence cs) { 8850 if (cs == null) { 8851 return null; 8852 } 8853 if (isEmpty(cs)) { 8854 return ArrayUtils.EMPTY_INT_ARRAY; 8855 } 8856 return cs.toString().codePoints().toArray(); 8857 } 8858 8859 /** 8860 * Converts a {@code byte[]} to a String using the specified character encoding. 8861 * 8862 * @param bytes The byte array to read from. 8863 * @param charset The encoding to use, if null then use the platform default. 8864 * @return A new String. 8865 * @throws NullPointerException Thrown if {@code bytes} is null. 8866 * @since 3.2 8867 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8868 */ 8869 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8870 return new String(bytes, Charsets.toCharset(charset)); 8871 } 8872 8873 /** 8874 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8875 * 8876 * @param source A source String or null. 8877 * @return The given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8878 * @since 3.10 8879 */ 8880 public static String toRootLowerCase(final String source) { 8881 return source == null ? null : source.toLowerCase(Locale.ROOT); 8882 } 8883 8884 /** 8885 * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8886 * 8887 * @param source A source String or null. 8888 * @return The given source String as an upper-case using the {@link Locale#ROOT} locale or null. 8889 * @since 3.10 8890 */ 8891 public static String toRootUpperCase(final String source) { 8892 return source == null ? null : source.toUpperCase(Locale.ROOT); 8893 } 8894 8895 /** 8896 * Converts a {@code byte[]} to a String using the specified character encoding. 8897 * 8898 * @param bytes The byte array to read from. 8899 * @param charsetName The encoding to use, if null then use the platform default. 8900 * @return A new String. 8901 * @throws NullPointerException Thrown if the input is null. 8902 * @since 3.1 8903 * @deprecated Use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code. 8904 */ 8905 @Deprecated 8906 public static String toString(final byte[] bytes, final String charsetName) { 8907 return new String(bytes, Charsets.toCharset(charsetName)); 8908 } 8909 8910 /** 8911 * Removes control characters plus space (char <= 32) from both ends of this String, handling {@code null} by returning {@code null}. 8912 * 8913 * <p> 8914 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #strip(String)}. 8915 * </p> 8916 * 8917 * <p> 8918 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8919 * </p> 8920 * 8921 * <pre> 8922 * StringUtils.trim(null) = null 8923 * StringUtils.trim("") = "" 8924 * StringUtils.trim(" ") = "" 8925 * StringUtils.trim("abc") = "abc" 8926 * StringUtils.trim(" abc ") = "abc" 8927 * </pre> 8928 * 8929 * @param str The String to be trimmed, may be null. 8930 * @return The trimmed string, {@code null} if null String input. 8931 */ 8932 public static String trim(final String str) { 8933 return str == null ? null : str.trim(); 8934 } 8935 8936 /** 8937 * Removes {@link CharUtils#isAsciiControl(char) ASCII control characters} (char <= 31 or char == 127) from both ends of this String, handling 8938 * {@code null} by returning {@code null}. 8939 * 8940 * <p> 8941 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8942 * </p> 8943 * 8944 * <pre>{@code 8945 * StringUtils.trimAsciiControl(null) = null 8946 * StringUtils.trimAsciiControl("") = "" 8947 * StringUtils.trimAsciiControl("abc\u0000") = "abc" 8948 * StringUtils.trimAsciiControl("abc") = "abc" 8949 * StringUtils.trimAsciiControl(" abc ") = " abc " 8950 * }</pre> 8951 * 8952 * @param str The String to be trimmed, may be null. 8953 * @return The trimmed string, {@code null} if null String input. 8954 * @since 3.21.0 8955 */ 8956 public static String trimAsciiControl(final String str) { 8957 if (str == null) { 8958 return null; 8959 } 8960 int len = str.length(); 8961 int st = 0; 8962 while (st < len && CharUtils.isAsciiControl(str.charAt(st))) { 8963 st++; 8964 } 8965 while (st < len && CharUtils.isAsciiControl(str.charAt(len - 1))) { 8966 len--; 8967 } 8968 return st > 0 || len < str.length() ? str.substring(st, len) : str; 8969 } 8970 8971 /** 8972 * 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 8973 * it is {@code null}. 8974 * 8975 * <p> 8976 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToEmpty(String)}. 8977 * </p> 8978 * 8979 * <pre> 8980 * StringUtils.trimToEmpty(null) = "" 8981 * StringUtils.trimToEmpty("") = "" 8982 * StringUtils.trimToEmpty(" ") = "" 8983 * StringUtils.trimToEmpty("abc") = "abc" 8984 * StringUtils.trimToEmpty(" abc ") = "abc" 8985 * </pre> 8986 * 8987 * @param str The String to be trimmed, may be null. 8988 * @return The trimmed String, or an empty String if {@code null} input. 8989 * @since 2.0 8990 */ 8991 public static String trimToEmpty(final String str) { 8992 return str == null ? EMPTY : str.trim(); 8993 } 8994 8995 /** 8996 * 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 8997 * {@code null}. 8998 * 8999 * <p> 9000 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToNull(String)}. 9001 * </p> 9002 * 9003 * <pre> 9004 * StringUtils.trimToNull(null) = null 9005 * StringUtils.trimToNull("") = null 9006 * StringUtils.trimToNull(" ") = null 9007 * StringUtils.trimToNull("abc") = "abc" 9008 * StringUtils.trimToNull(" abc ") = "abc" 9009 * </pre> 9010 * 9011 * @param str The String to be trimmed, may be null. 9012 * @return The trimmed String, {@code null} if only chars <= 32, empty or null String input. 9013 * @since 2.0 9014 */ 9015 public static String trimToNull(final String str) { 9016 final String ts = trim(str); 9017 return isEmpty(ts) ? null : ts; 9018 } 9019 9020 /** 9021 * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for". 9022 * 9023 * <p> 9024 * Specifically: 9025 * </p> 9026 * <ul> 9027 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 9028 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 9029 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 9030 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 9031 * </ul> 9032 * 9033 * <pre> 9034 * StringUtils.truncate(null, 0) = null 9035 * StringUtils.truncate(null, 2) = null 9036 * StringUtils.truncate("", 4) = "" 9037 * StringUtils.truncate("abcdefg", 4) = "abcd" 9038 * StringUtils.truncate("abcdefg", 6) = "abcdef" 9039 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 9040 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 9041 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 9042 * </pre> 9043 * 9044 * @param str The String to truncate, may be null. 9045 * @param maxWidth maximum length of result String, must be non-negative. 9046 * @return truncated String, {@code null} if null String input. 9047 * @throws IllegalArgumentException Thrown if {@code maxWidth} is less than {@code 0}. 9048 * @since 3.5 9049 */ 9050 public static String truncate(final String str, final int maxWidth) { 9051 return truncate(str, 0, maxWidth); 9052 } 9053 9054 /** 9055 * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all". 9056 * 9057 * <p> 9058 * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset. 9059 * </p> 9060 * 9061 * <p> 9062 * Specifically: 9063 * </p> 9064 * <ul> 9065 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 9066 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 9067 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 9068 * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 9069 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 9070 * </ul> 9071 * 9072 * <pre> 9073 * StringUtils.truncate(null, 0, 0) = null 9074 * StringUtils.truncate(null, 2, 4) = null 9075 * StringUtils.truncate("", 0, 10) = "" 9076 * StringUtils.truncate("", 2, 10) = "" 9077 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 9078 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 9079 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 9080 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 9081 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 9082 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 9083 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 9084 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 9085 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 9086 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 9087 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 9088 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 9089 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 9090 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 9091 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 9092 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 9093 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 9094 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 9095 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 9096 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 9097 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 9098 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 9099 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 9100 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 9101 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 9102 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 9103 * </pre> 9104 * 9105 * @param str The String to truncate, may be null. 9106 * @param offset left edge of source String. 9107 * @param maxWidth maximum length of result String, must be non-negative. 9108 * @return truncated String, {@code null} if null String input. 9109 * @throws IllegalArgumentException Thrown if {@code offset} or {@code maxWidth} is less than {@code 0}. 9110 * @since 3.5 9111 */ 9112 public static String truncate(final String str, final int offset, final int maxWidth) { 9113 if (offset < 0) { 9114 throw new IllegalArgumentException("offset cannot be negative"); 9115 } 9116 if (maxWidth < 0) { 9117 throw new IllegalArgumentException("maxWidth cannot be negative"); 9118 } 9119 if (str == null) { 9120 return null; 9121 } 9122 final int len = str.length(); 9123 int start = Math.min(offset, len); 9124 int end = Math.min(offset > len - maxWidth ? len : offset + maxWidth, len); 9125 // keep both edges off the middle of a surrogate pair so the result is never left holding a lone surrogate 9126 if (splitsSurrogatePair(str, start)) { 9127 start++; 9128 } 9129 if (splitsSurrogatePair(str, end)) { 9130 end--; 9131 } 9132 return str.substring(start, Math.max(start, end)); 9133 } 9134 9135 /** 9136 * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed. 9137 * 9138 * <p> 9139 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}. 9140 * </p> 9141 * 9142 * <pre> 9143 * StringUtils.uncapitalize(null) = null 9144 * StringUtils.uncapitalize("") = "" 9145 * StringUtils.uncapitalize("cat") = "cat" 9146 * StringUtils.uncapitalize("Cat") = "cat" 9147 * StringUtils.uncapitalize("CAT") = "cAT" 9148 * </pre> 9149 * 9150 * @param str The String to uncapitalize, may be null. 9151 * @return The uncapitalized String, {@code null} if null String input. 9152 * @see org.apache.commons.text.WordUtils#uncapitalize(String) 9153 * @see #capitalize(String) 9154 * @since 2.0 9155 */ 9156 public static String uncapitalize(final String str) { 9157 final int strLen = length(str); 9158 if (strLen == 0) { 9159 return str; 9160 } 9161 final int firstCodePoint = str.codePointAt(0); 9162 final int newCodePoint = Character.toLowerCase(firstCodePoint); 9163 if (firstCodePoint == newCodePoint) { 9164 // already uncapitalized 9165 return str; 9166 } 9167 final int[] newCodePoints = str.codePoints().toArray(); 9168 newCodePoints[0] = newCodePoint; // copy the first code point 9169 return new String(newCodePoints, 0, newCodePoints.length); 9170 } 9171 9172 /** 9173 * Unwraps a given string from a character. 9174 * 9175 * <pre> 9176 * StringUtils.unwrap(null, null) = null 9177 * StringUtils.unwrap(null, '\0') = null 9178 * StringUtils.unwrap(null, '1') = null 9179 * StringUtils.unwrap("a", 'a') = "a" 9180 * StringUtils.unwrap("aa", 'a') = "" 9181 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 9182 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 9183 * StringUtils.unwrap("A", '#') = "A" 9184 * StringUtils.unwrap("#A", '#') = "#A" 9185 * StringUtils.unwrap("A#", '#') = "A#" 9186 * </pre> 9187 * 9188 * @param str The String to be unwrapped, can be null. 9189 * @param wrapChar The character used to unwrap. 9190 * @return unwrapped String or the original string if it is not quoted properly with the wrapChar. 9191 * @since 3.6 9192 */ 9193 public static String unwrap(final String str, final char wrapChar) { 9194 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 9195 return str; 9196 } 9197 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 9198 final int startIndex = 0; 9199 final int endIndex = str.length() - 1; 9200 return str.substring(startIndex + 1, endIndex); 9201 } 9202 return str; 9203 } 9204 9205 /** 9206 * Unwraps a given string from another string. 9207 * 9208 * <pre> 9209 * StringUtils.unwrap(null, null) = null 9210 * StringUtils.unwrap(null, "") = null 9211 * StringUtils.unwrap(null, "1") = null 9212 * StringUtils.unwrap("a", "a") = "a" 9213 * StringUtils.unwrap("aa", "a") = "" 9214 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 9215 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 9216 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 9217 * StringUtils.unwrap("A", "#") = "A" 9218 * StringUtils.unwrap("#A", "#") = "#A" 9219 * StringUtils.unwrap("A#", "#") = "A#" 9220 * </pre> 9221 * 9222 * @param str The String to be unwrapped, can be null. 9223 * @param wrapToken The String used to unwrap. 9224 * @return unwrapped String or the original string if it is not quoted properly with the wrapToken. 9225 * @since 3.6 9226 */ 9227 public static String unwrap(final String str, final String wrapToken) { 9228 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) { 9229 return str; 9230 } 9231 if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) { 9232 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken)); 9233 } 9234 return str; 9235 } 9236 9237 /** 9238 * Converts a String to upper case as per {@link String#toUpperCase()}. 9239 * 9240 * <p> 9241 * A {@code null} input String returns {@code null}. 9242 * </p> 9243 * 9244 * <pre> 9245 * StringUtils.upperCase(null) = null 9246 * StringUtils.upperCase("") = "" 9247 * StringUtils.upperCase("aBc") = "ABC" 9248 * </pre> 9249 * 9250 * <p> 9251 * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale. 9252 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g. 9253 * {@link Locale#ENGLISH}). 9254 * </p> 9255 * 9256 * @param str The String to upper case, may be null. 9257 * @return The upper-cased String, {@code null} if null String input. 9258 */ 9259 public static String upperCase(final String str) { 9260 if (str == null) { 9261 return null; 9262 } 9263 return str.toUpperCase(); 9264 } 9265 9266 /** 9267 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}. 9268 * 9269 * <p> 9270 * A {@code null} input String returns {@code null}. 9271 * </p> 9272 * 9273 * <pre> 9274 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9275 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9276 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9277 * </pre> 9278 * 9279 * @param str The String to upper case, may be null. 9280 * @param locale The locale that defines the case transformation rules, must not be null. 9281 * @return The upper-cased String, {@code null} if null String input. 9282 * @since 2.5 9283 */ 9284 public static String upperCase(final String str, final Locale locale) { 9285 if (str == null) { 9286 return null; 9287 } 9288 return str.toUpperCase(LocaleUtils.toLocale(locale)); 9289 } 9290 9291 /** 9292 * Returns the string representation of the {@code char} array or null. 9293 * 9294 * @param value The character array. 9295 * @return A String or null. 9296 * @see String#valueOf(char[]) 9297 * @since 3.9 9298 */ 9299 public static String valueOf(final char[] value) { 9300 return value == null ? null : String.valueOf(value); 9301 } 9302 9303 /** 9304 * Wraps a string with a char. 9305 * 9306 * <pre> 9307 * StringUtils.wrap(null, *) = null 9308 * StringUtils.wrap("", *) = "" 9309 * StringUtils.wrap("ab", '\0') = "ab" 9310 * StringUtils.wrap("ab", 'x') = "xabx" 9311 * StringUtils.wrap("ab", '\'') = "'ab'" 9312 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9313 * </pre> 9314 * 9315 * @param str The string to be wrapped, may be {@code null}. 9316 * @param wrapWith The char that will wrap {@code str}. 9317 * @return The wrapped string, or {@code null} if {@code str == null}. 9318 * @since 3.4 9319 */ 9320 public static String wrap(final String str, final char wrapWith) { 9321 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9322 return str; 9323 } 9324 return wrapWith + str + wrapWith; 9325 } 9326 9327 /** 9328 * Wraps a String with another String. 9329 * 9330 * <p> 9331 * A {@code null} input String returns {@code null}. 9332 * </p> 9333 * 9334 * <pre> 9335 * StringUtils.wrap(null, *) = null 9336 * StringUtils.wrap("", *) = "" 9337 * StringUtils.wrap("ab", null) = "ab" 9338 * StringUtils.wrap("ab", "x") = "xabx" 9339 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9340 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9341 * StringUtils.wrap("ab", "'") = "'ab'" 9342 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9343 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9344 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9345 * </pre> 9346 * 9347 * @param str The String to be wrapper, may be null. 9348 * @param wrapWith The String that will wrap str. 9349 * @return wrapped String, {@code null} if null String input. 9350 * @since 3.4 9351 */ 9352 public static String wrap(final String str, final String wrapWith) { 9353 if (isEmpty(str) || isEmpty(wrapWith)) { 9354 return str; 9355 } 9356 return wrapWith.concat(str).concat(wrapWith); 9357 } 9358 9359 /** 9360 * Wraps a string with a char if that char is missing from the start or end of the given string. 9361 * 9362 * <p> 9363 * A new {@link String} will not be created if {@code str} is already wrapped. 9364 * </p> 9365 * 9366 * <pre> 9367 * StringUtils.wrapIfMissing(null, *) = null 9368 * StringUtils.wrapIfMissing("", *) = "" 9369 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9370 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9371 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9372 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9373 * StringUtils.wrapIfMissing("/", '/') = "/" 9374 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9375 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9376 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9377 * </pre> 9378 * 9379 * @param str The string to be wrapped, may be {@code null}. 9380 * @param wrapWith The char that will wrap {@code str}. 9381 * @return The wrapped string, or {@code null} if {@code str == null}. 9382 * @since 3.5 9383 */ 9384 public static String wrapIfMissing(final String str, final char wrapWith) { 9385 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9386 return str; 9387 } 9388 final boolean wrapStart = str.charAt(0) != wrapWith; 9389 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9390 if (!wrapStart && !wrapEnd) { 9391 return str; 9392 } 9393 final StringBuilder builder = new StringBuilder(str.length() + 2); 9394 if (wrapStart) { 9395 builder.append(wrapWith); 9396 } 9397 builder.append(str); 9398 if (wrapEnd) { 9399 builder.append(wrapWith); 9400 } 9401 return builder.toString(); 9402 } 9403 9404 /** 9405 * Wraps a string with a string if that string is missing from the start or end of the given string. 9406 * 9407 * <p> 9408 * A new {@link String} will not be created if {@code str} is already wrapped. 9409 * </p> 9410 * 9411 * <pre> 9412 * StringUtils.wrapIfMissing(null, *) = null 9413 * StringUtils.wrapIfMissing("", *) = "" 9414 * StringUtils.wrapIfMissing("ab", null) = "ab" 9415 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9416 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9417 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9418 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9419 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9420 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9421 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9422 * StringUtils.wrapIfMissing("/", "/") = "/" 9423 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9424 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9425 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9426 * </pre> 9427 * 9428 * @param str The string to be wrapped, may be {@code null}. 9429 * @param wrapWith The string that will wrap {@code str}. 9430 * @return The wrapped string, or {@code null} if {@code str == null}. 9431 * @since 3.5 9432 */ 9433 public static String wrapIfMissing(final String str, final String wrapWith) { 9434 if (isEmpty(str) || isEmpty(wrapWith)) { 9435 return str; 9436 } 9437 final boolean wrapStart = !str.startsWith(wrapWith); 9438 final boolean wrapEnd = !str.endsWith(wrapWith); 9439 if (!wrapStart && !wrapEnd) { 9440 return str; 9441 } 9442 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9443 if (wrapStart) { 9444 builder.append(wrapWith); 9445 } 9446 builder.append(str); 9447 if (wrapEnd) { 9448 builder.append(wrapWith); 9449 } 9450 return builder.toString(); 9451 } 9452 9453 /** 9454 * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}. 9455 * 9456 * <p> 9457 * This constructor is public to permit tools that require a JavaBean instance to operate. 9458 * </p> 9459 * 9460 * @deprecated TODO Make private in 4.0. 9461 */ 9462 @Deprecated 9463 public StringUtils() { 9464 // empty 9465 } 9466 9467}