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>LeftPad/RightPad/Center/Repeat</strong> 076 * - pads a String</li> 077 * <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong> 078 * - changes the case of a String</li> 079 * <li><strong>CountMatches</strong> 080 * - counts the number of occurrences of one String in another</li> 081 * <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong> 082 * - checks the characters in a String</li> 083 * <li><strong>DefaultString</strong> 084 * - protects against a null input String</li> 085 * <li><strong>Rotate</strong> 086 * - rotate (circular shift) a String</li> 087 * <li><strong>Reverse/ReverseDelimited</strong> 088 * - reverses a String</li> 089 * <li><strong>Abbreviate</strong> 090 * - abbreviates a string using ellipses or another given String</li> 091 * <li><strong>Difference</strong> 092 * - compares Strings and reports on their differences</li> 093 * <li><strong>LevenshteinDistance</strong> 094 * - the number of changes needed to change one String into another</li> 095 * </ul> 096 * 097 * <p> 098 * The {@link StringUtils} class defines certain words related to 099 * String handling. 100 * </p> 101 * 102 * <ul> 103 * <li>null - {@code null}</li> 104 * <li>empty - a zero-length string ({@code ""})</li> 105 * <li>space - the space character ({@code ' '}, char 32)</li> 106 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 107 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 108 * </ul> 109 * 110 * <p> 111 * {@link StringUtils} handles {@code null} input Strings quietly. 112 * That is to say that a {@code null} input will return {@code null}. 113 * Where a {@code boolean} or {@code int} is being returned 114 * details vary by method. 115 * </p> 116 * 117 * <p> 118 * A side effect of the {@code null} handling is that a 119 * {@link NullPointerException} should be considered a bug in 120 * {@link StringUtils}. 121 * </p> 122 * 123 * <p> 124 * Methods in this class include sample code in their Javadoc comments to explain their operation. 125 * The symbol {@code *} is used to indicate any input including {@code null}. 126 * </p> 127 * 128 * <p> 129 * #ThreadSafe# 130 * </p> 131 * 132 * @see String 133 * @since 1.0 134 */ 135//@Immutable 136public class StringUtils { 137 138 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 139 // Whitespace: 140 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 141 // where WHITESPACE is a string of all whitespace characters 142 // 143 // Character access: 144 // String.charAt(n) versus toCharArray(), then array[n] 145 // String.charAt(n) is about 15% worse for a 10K string 146 // They are about equal for a length 50 string 147 // String.charAt(n) is about 4 times better for a length 3 string 148 // String.charAt(n) is best bet overall 149 // 150 // Append: 151 // String.concat about twice as fast as StringBuffer.append 152 // (not sure who tested this) 153 154 /** 155 * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 '…', this isn't it. 156 */ 157 private static final String ELLIPSIS3 = "..."; 158 159 /** 160 * A String for a space character. 161 * 162 * @since 3.2 163 */ 164 public static final String SPACE = " "; 165 166 /** 167 * The empty String {@code ""}. 168 * 169 * @since 2.0 170 */ 171 public static final String EMPTY = ""; 172 173 /** 174 * The null String {@code null}. Package-private only. 175 */ 176 static final String NULL = null; 177 178 /** 179 * A String for linefeed LF ("\n"). 180 * 181 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 182 * for Character and String Literals</a> 183 * @since 3.2 184 */ 185 public static final String LF = "\n"; 186 187 /** 188 * A String for carriage return CR ("\r"). 189 * 190 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 191 * for Character and String Literals</a> 192 * @since 3.2 193 */ 194 public static final String CR = "\r"; 195 196 /** 197 * Represents a failed index search. 198 * 199 * @since 2.1 200 */ 201 public static final int INDEX_NOT_FOUND = -1; 202 203 /** 204 * The maximum size to which the padding constant(s) can expand. 205 */ 206 private static final int PAD_LIMIT = 8192; 207 208 /** 209 * The default maximum depth at which recursive replacement will continue until no further search replacements are possible. 210 */ 211 private static final int DEFAULT_TTL = 5; 212 213 /** 214 * Pattern used in {@link #stripAccents(String)}. 215 */ 216 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 217 218 /** 219 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "Now is the time for..." 220 * 221 * <p> 222 * Specifically: 223 * </p> 224 * <ul> 225 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 226 * <li>Else abbreviate it to {@code (substring(str, 0, max - 3) + "...")}.</li> 227 * <li>If {@code maxWidth} is less than {@code 4}, throw an {@link IllegalArgumentException}.</li> 228 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 229 * </ul> 230 * 231 * <pre> 232 * StringUtils.abbreviate(null, *) = null 233 * StringUtils.abbreviate("", 4) = "" 234 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 235 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 236 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 237 * StringUtils.abbreviate("abcdefg", 4) = "a..." 238 * StringUtils.abbreviate("abcdefg", 3) = Throws {@link IllegalArgumentException}. 239 * </pre> 240 * 241 * @param str The String to check, may be null. 242 * @param maxWidth maximum length of result String, must be at least 4. 243 * @return abbreviated String, {@code null} if null String input. 244 * @throws IllegalArgumentException Thrown if the width is too small. 245 * @since 2.0 246 */ 247 public static String abbreviate(final String str, final int maxWidth) { 248 return abbreviate(str, ELLIPSIS3, 0, maxWidth); 249 } 250 251 /** 252 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "...is the time for...". 253 * 254 * <p> 255 * Works like {@code abbreviate(String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to be the 256 * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result. 257 * </p> 258 * <p> 259 * In no case will it return a String of length greater than {@code maxWidth}. 260 * </p> 261 * 262 * <pre> 263 * StringUtils.abbreviate(null, *, *) = null 264 * StringUtils.abbreviate("", 0, 4) = "" 265 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 266 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 267 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 268 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 269 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 270 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 271 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 272 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 273 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 274 * StringUtils.abbreviate("abcdefghij", 0, 3) = Throws {@link IllegalArgumentException}. 275 * StringUtils.abbreviate("abcdefghij", 5, 6) = Throws {@link IllegalArgumentException}. 276 * </pre> 277 * 278 * @param str The String to check, may be null. 279 * @param offset left edge of source String. 280 * @param maxWidth maximum length of result String, must be at least 4. 281 * @return abbreviated String, {@code null} if null String input. 282 * @throws IllegalArgumentException Thrown if the width is too small. 283 * @since 2.0 284 */ 285 public static String abbreviate(final String str, final int offset, final int maxWidth) { 286 return abbreviate(str, ELLIPSIS3, offset, maxWidth); 287 } 288 289 /** 290 * Abbreviates a String using another given String as replacement marker. This will convert "Now is the time for all good men" into "Now is the time for..." 291 * when "..." is the replacement marker. 292 * 293 * <p> 294 * Specifically: 295 * </p> 296 * <ul> 297 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 298 * <li>Else abbreviate it to {@code (substring(str, 0, max - abbrevMarker.length) + abbrevMarker)}.</li> 299 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li> 300 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 301 * </ul> 302 * 303 * <pre> 304 * StringUtils.abbreviate(null, "...", *) = null 305 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 306 * StringUtils.abbreviate("", "...", 4) = "" 307 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 308 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 309 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 310 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 311 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 312 * StringUtils.abbreviate("abcdefg", "..", 2) = Throws {@link IllegalArgumentException}. 313 * StringUtils.abbreviate("abcdefg", "...", 3) = Throws {@link IllegalArgumentException}. 314 * </pre> 315 * 316 * @param str The String to check, may be null. 317 * @param abbrevMarker The String used as replacement marker. 318 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}. 319 * @return abbreviated String, {@code null} if null String input. 320 * @throws IllegalArgumentException Thrown if the width is too small. 321 * @since 3.6 322 */ 323 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 324 return abbreviate(str, abbrevMarker, 0, maxWidth); 325 } 326 327 /** 328 * Abbreviates a String using a given replacement marker. This will convert "Now is the time for all good men" into "...is the time for..." when "..." is 329 * the replacement marker. 330 * <p> 331 * Works like {@code abbreviate(String, String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to 332 * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result. 333 * </p> 334 * <p> 335 * In no case will it return a String of length greater than {@code maxWidth}. 336 * </p> 337 * 338 * <pre> 339 * StringUtils.abbreviate(null, null, *, *) = null 340 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 341 * StringUtils.abbreviate("", "...", 0, 4) = "" 342 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 343 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 344 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 345 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 346 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 347 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 348 * StringUtils.abbreviate("abcdefghijklmno", "…", 6, 10) = "…ghijklmno" 349 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 350 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 351 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 352 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = Throws {@link IllegalArgumentException}. 353 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = Throws {@link IllegalArgumentException}. 354 * </pre> 355 * 356 * @param str The String to check, may be null. 357 * @param abbrevMarker The String used as replacement marker, for example "...", or Unicode HORIZONTAL ELLIPSIS, U+2026 '…'. 358 * @param offset left edge of source String. 359 * @param maxWidth maximum length of result String, must be at least 4. 360 * @return abbreviated String, {@code null} if null String input. 361 * @throws IllegalArgumentException Thrown if the width is too small. 362 * @since 3.6 363 */ 364 public static String abbreviate(final String str, String abbrevMarker, final int offset, final int maxWidth) { 365 if (isEmpty(str)) { 366 return str; 367 } 368 if (abbrevMarker == null) { 369 abbrevMarker = EMPTY; 370 } 371 final int abbrevMarkerLength = abbrevMarker.length(); 372 final int minAbbrevWidth = abbrevMarkerLength + 1; 373 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 374 375 if (maxWidth < minAbbrevWidth) { 376 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 377 } 378 final int strLen = str.length(); 379 if (strLen <= maxWidth) { 380 return str; 381 } 382 if (strLen - offset <= maxWidth - abbrevMarkerLength) { 383 int tailStart = strLen - (maxWidth - abbrevMarkerLength); 384 if (splitsSurrogatePair(str, tailStart)) { 385 tailStart++; 386 } 387 return abbrevMarker + str.substring(tailStart); 388 } 389 if (offset <= abbrevMarkerLength + 1) { 390 int headEnd = maxWidth - abbrevMarkerLength; 391 if (splitsSurrogatePair(str, headEnd)) { 392 headEnd--; 393 } 394 return str.substring(0, headEnd) + abbrevMarker; 395 } 396 if (maxWidth < minAbbrevWidthOffset) { 397 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 398 } 399 int from = offset; 400 if (splitsSurrogatePair(str, from)) { 401 from++; 402 } 403 return abbrevMarker + abbreviate(str.substring(from), abbrevMarker, maxWidth - abbrevMarkerLength); 404 } 405 406 /** 407 * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String. 408 * 409 * <p> 410 * This abbreviation only occurs if the following criteria is met: 411 * </p> 412 * <ul> 413 * <li>Neither the String for abbreviation nor the replacement String are null or empty</li> 414 * <li>The length to truncate to is less than the length of the supplied String</li> 415 * <li>The length to truncate to is greater than 0</li> 416 * <li>The abbreviated String will have enough room for the length supplied replacement String and the first and last characters of the supplied String for 417 * abbreviation</li> 418 * </ul> 419 * <p> 420 * Otherwise, the returned String will be the same as the supplied String for abbreviation. 421 * </p> 422 * 423 * <pre> 424 * StringUtils.abbreviateMiddle(null, null, 0) = null 425 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 426 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 427 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 428 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 429 * </pre> 430 * 431 * @param str The String to abbreviate, may be null. 432 * @param middle The String to replace the middle characters with, may be null. 433 * @param length The length to abbreviate {@code str} to. 434 * @return The abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 435 * @since 2.5 436 */ 437 public static String abbreviateMiddle(final String str, final String middle, final int length) { 438 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) { 439 return str; 440 } 441 final int targetString = length - middle.length(); 442 int startOffset = targetString / 2 + targetString % 2; 443 int endOffset = str.length() - targetString / 2; 444 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 445 if (splitsSurrogatePair(str, startOffset)) { 446 startOffset--; 447 } 448 if (splitsSurrogatePair(str, endOffset)) { 449 endOffset++; 450 } 451 return str.substring(0, startOffset) + middle + str.substring(endOffset); 452 } 453 454 /** 455 * Appends the suffix to the end of the string if the string does not already end with any of the suffixes. 456 * 457 * <pre> 458 * StringUtils.appendIfMissing(null, null) = null 459 * StringUtils.appendIfMissing("abc", null) = "abc" 460 * StringUtils.appendIfMissing("", "xyz") = "xyz" 461 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 462 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 463 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 464 * </pre> 465 * <p> 466 * With additional suffixes, 467 * </p> 468 * 469 * <pre> 470 * StringUtils.appendIfMissing(null, null, null) = null 471 * StringUtils.appendIfMissing("abc", null, null) = "abc" 472 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 473 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 474 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 475 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 476 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 477 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 478 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 479 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 480 * </pre> 481 * 482 * @param str The string. 483 * @param suffix The suffix to append to the end of the string. 484 * @param suffixes Additional suffixes that are valid terminators. 485 * @return A new String if suffix was appended, the same string otherwise. 486 * @since 3.2 487 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}. 488 */ 489 @Deprecated 490 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 491 return Strings.CS.appendIfMissing(str, suffix, suffixes); 492 } 493 494 /** 495 * Appends the suffix to the end of the string if the string does not 496 * already end, case-insensitive, with any of the suffixes. 497 * 498 * <pre> 499 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 500 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 501 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 502 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 503 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 504 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 505 * </pre> 506 * <p> 507 * With additional suffixes, 508 * </p> 509 * <pre> 510 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 511 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 512 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 513 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 514 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 515 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 516 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 517 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 518 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 519 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 520 * </pre> 521 * 522 * @param str The string. 523 * @param suffix The suffix to append to the end of the string. 524 * @param suffixes Additional suffixes that are valid terminators. 525 * @return A new String if suffix was appended, the same string otherwise. 526 * @since 3.2 527 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}. 528 */ 529 @Deprecated 530 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 531 return Strings.CI.appendIfMissing(str, suffix, suffixes); 532 } 533 534 /** 535 * Computes the capacity required for a StringBuilder to hold {@code items} of {@code maxElementChars} characters plus the separators between them. The 536 * separator is assumed to be 1 character. 537 * 538 * @param count The number of items. 539 * @param maxElementChars The maximum number of characters per item. 540 * @return A StringBuilder with the appropriate capacity. 541 */ 542 private static StringBuilder capacity(final int count, final byte maxElementChars) { 543 return new StringBuilder(count * maxElementChars + count - 1); 544 } 545 546 /** 547 * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed. 548 * 549 * <p> 550 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}. 551 * </p> 552 * 553 * <pre> 554 * StringUtils.capitalize(null) = null 555 * StringUtils.capitalize("") = "" 556 * StringUtils.capitalize("cat") = "Cat" 557 * StringUtils.capitalize("cAt") = "CAt" 558 * StringUtils.capitalize("'cat'") = "'cat'" 559 * </pre> 560 * 561 * @param str The String to capitalize, may be null. 562 * @return The capitalized String, {@code null} if null String input. 563 * @see org.apache.commons.text.WordUtils#capitalize(String) 564 * @see #uncapitalize(String) 565 * @since 2.0 566 */ 567 public static String capitalize(final String str) { 568 if (isEmpty(str)) { 569 return str; 570 } 571 final int firstCodepoint = str.codePointAt(0); 572 final int newCodePoint = Character.toTitleCase(firstCodepoint); 573 if (firstCodepoint == newCodePoint) { 574 // already capitalized 575 return str; 576 } 577 final int[] newCodePoints = str.codePoints().toArray(); 578 newCodePoints[0] = newCodePoint; // copy the first code point 579 return new String(newCodePoints, 0, newCodePoints.length); 580 } 581 582 /** 583 * Centers a String in a larger String of size {@code size} using the space character (' '). 584 * 585 * <p> 586 * If the size is less than the String length, the original String is returned. A {@code null} String returns {@code null}. A negative size is treated as 587 * zero. 588 * </p> 589 * 590 * <p> 591 * Equivalent to {@code center(str, size, " ")}. 592 * </p> 593 * 594 * <pre> 595 * StringUtils.center(null, *) = null 596 * StringUtils.center("", 4) = " " 597 * StringUtils.center("ab", -1) = "ab" 598 * StringUtils.center("ab", 4) = " ab " 599 * StringUtils.center("abcd", 2) = "abcd" 600 * StringUtils.center("a", 4) = " a " 601 * </pre> 602 * 603 * @param str The String to center, may be null. 604 * @param size The int size of new String, negative treated as zero. 605 * @return centered String, {@code null} if null String input. 606 */ 607 public static String center(final String str, final int size) { 608 return center(str, size, ' '); 609 } 610 611 /** 612 * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with. 613 * 614 * <p> 615 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero. 616 * </p> 617 * 618 * <pre> 619 * StringUtils.center(null, *, *) = null 620 * StringUtils.center("", 4, ' ') = " " 621 * StringUtils.center("ab", -1, ' ') = "ab" 622 * StringUtils.center("ab", 4, ' ') = " ab " 623 * StringUtils.center("abcd", 2, ' ') = "abcd" 624 * StringUtils.center("a", 4, ' ') = " a " 625 * StringUtils.center("a", 4, 'y') = "yayy" 626 * </pre> 627 * 628 * @param str The String to center, may be null. 629 * @param size The int size of new String, negative treated as zero. 630 * @param padChar The character to pad the new String with. 631 * @return centered String, {@code null} if null String input. 632 * @since 2.0 633 */ 634 public static String center(String str, final int size, final char padChar) { 635 if (str == null || size <= 0) { 636 return str; 637 } 638 final int strLen = str.length(); 639 final int pads = size - strLen; 640 if (pads <= 0) { 641 return str; 642 } 643 str = leftPad(str, strLen + pads / 2, padChar); 644 return rightPad(str, size, padChar); 645 } 646 647 /** 648 * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with. 649 * 650 * <p> 651 * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero. 652 * </p> 653 * 654 * <pre> 655 * StringUtils.center(null, *, *) = null 656 * StringUtils.center("", 4, " ") = " " 657 * StringUtils.center("ab", -1, " ") = "ab" 658 * StringUtils.center("ab", 4, " ") = " ab " 659 * StringUtils.center("abcd", 2, " ") = "abcd" 660 * StringUtils.center("a", 4, " ") = " a " 661 * StringUtils.center("a", 4, "yz") = "yayz" 662 * StringUtils.center("abc", 7, null) = " abc " 663 * StringUtils.center("abc", 7, "") = " abc " 664 * </pre> 665 * 666 * @param str The String to center, may be null. 667 * @param size The int size of new String, negative treated as zero. 668 * @param padStr The String to pad the new String with, must not be null or empty. 669 * @return centered String, {@code null} if null String input. 670 * @throws IllegalArgumentException Thrown if padStr is {@code null} or empty. 671 */ 672 public static String center(String str, final int size, String padStr) { 673 if (str == null || size <= 0) { 674 return str; 675 } 676 if (isEmpty(padStr)) { 677 padStr = SPACE; 678 } 679 final int strLen = str.length(); 680 final int pads = size - strLen; 681 if (pads <= 0) { 682 return str; 683 } 684 str = leftPad(str, strLen + pads / 2, padStr); 685 return rightPad(str, size, padStr); 686 } 687 688 private static void checkFromToIndex(final int startIndex, final int endIndex, final int length) { 689 if (startIndex < 0) { 690 throw new ArrayIndexOutOfBoundsException(startIndex); 691 } 692 if (endIndex > length) { 693 throw new ArrayIndexOutOfBoundsException(endIndex); 694 } 695 } 696 697 /** 698 * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is "{@code \n}", "{@code \r}", or 699 * "{@code \r\n}". 700 * 701 * <p> 702 * NOTE: This method changed in 2.0. It now more closely matches Perl chomp. 703 * </p> 704 * 705 * <pre> 706 * StringUtils.chomp(null) = null 707 * StringUtils.chomp("") = "" 708 * StringUtils.chomp("abc \r") = "abc " 709 * StringUtils.chomp("abc\n") = "abc" 710 * StringUtils.chomp("abc\r\n") = "abc" 711 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 712 * StringUtils.chomp("abc\n\r") = "abc\n" 713 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 714 * StringUtils.chomp("\r") = "" 715 * StringUtils.chomp("\n") = "" 716 * StringUtils.chomp("\r\n") = "" 717 * </pre> 718 * 719 * @param str The String to chomp a newline from, may be null. 720 * @return String without newline, {@code null} if null String input. 721 */ 722 public static String chomp(final String str) { 723 if (isEmpty(str)) { 724 return str; 725 } 726 if (str.length() == 1) { 727 final char ch = str.charAt(0); 728 if (ch == CharUtils.CR || ch == CharUtils.LF) { 729 return EMPTY; 730 } 731 return str; 732 } 733 int lastIdx = str.length() - 1; 734 final char last = str.charAt(lastIdx); 735 if (last == CharUtils.LF) { 736 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 737 lastIdx--; 738 } 739 } else if (last != CharUtils.CR) { 740 lastIdx++; 741 } 742 return str.substring(0, lastIdx); 743 } 744 745 /** 746 * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone. 747 * 748 * <p> 749 * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use 750 * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}. 751 * </p> 752 * 753 * <pre> 754 * StringUtils.chomp(null, *) = null 755 * StringUtils.chomp("", *) = "" 756 * StringUtils.chomp("foobar", "bar") = "foo" 757 * StringUtils.chomp("foobar", "baz") = "foobar" 758 * StringUtils.chomp("foo", "foo") = "" 759 * StringUtils.chomp("foo ", "foo") = "foo " 760 * StringUtils.chomp(" foo", "foo") = " " 761 * StringUtils.chomp("foo", "foooo") = "foo" 762 * StringUtils.chomp("foo", "") = "foo" 763 * StringUtils.chomp("foo", null) = "foo" 764 * </pre> 765 * 766 * @param str The String to chomp from, may be null. 767 * @param separator separator String, may be null. 768 * @return String without trailing separator, {@code null} if null String input. 769 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead. 770 */ 771 @Deprecated 772 public static String chomp(final String str, final String separator) { 773 return Strings.CS.removeEnd(str, separator); 774 } 775 776 /** 777 * Removes the last character from a String. 778 * 779 * <p> 780 * If the String ends in {@code \r\n}, then remove both of them. 781 * </p> 782 * 783 * <pre> 784 * StringUtils.chop(null) = null 785 * StringUtils.chop("") = "" 786 * StringUtils.chop("abc \r") = "abc " 787 * StringUtils.chop("abc\n") = "abc" 788 * StringUtils.chop("abc\r\n") = "abc" 789 * StringUtils.chop("abc") = "ab" 790 * StringUtils.chop("abc\nabc") = "abc\nab" 791 * StringUtils.chop("a") = "" 792 * StringUtils.chop("\r") = "" 793 * StringUtils.chop("\n") = "" 794 * StringUtils.chop("\r\n") = "" 795 * </pre> 796 * 797 * @param str The String to chop last character from, may be null. 798 * @return String without last character, {@code null} if null String input. 799 */ 800 public static String chop(final String str) { 801 if (str == null) { 802 return null; 803 } 804 final int strLen = str.length(); 805 if (strLen < 2) { 806 return EMPTY; 807 } 808 final int lastIdx = strLen - 1; 809 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 810 if (splitsSurrogatePair(str, lastIdx)) { 811 return str.substring(0, lastIdx - 1); 812 } 813 final String ret = str.substring(0, lastIdx); 814 final char last = str.charAt(lastIdx); 815 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 816 return ret.substring(0, lastIdx - 1); 817 } 818 return ret; 819 } 820 821 /** 822 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 823 * <ul> 824 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 825 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 826 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 827 * </ul> 828 * 829 * <p> 830 * This is a {@code null} safe version of: 831 * </p> 832 * 833 * <pre> 834 * str1.compareTo(str2) 835 * </pre> 836 * 837 * <p> 838 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. 839 * </p> 840 * 841 * <pre>{@code 842 * StringUtils.compare(null, null) = 0 843 * StringUtils.compare(null , "a") < 0 844 * StringUtils.compare("a", null) > 0 845 * StringUtils.compare("abc", "abc") = 0 846 * StringUtils.compare("a", "b") < 0 847 * StringUtils.compare("b", "a") > 0 848 * StringUtils.compare("a", "B") > 0 849 * StringUtils.compare("ab", "abc") < 0 850 * }</pre> 851 * 852 * @param str1 The String to compare from. 853 * @param str2 The String to compare to. 854 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2}. 855 * @see #compare(String, String, boolean) 856 * @see String#compareTo(String) 857 * @since 3.5 858 * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}. 859 */ 860 @Deprecated 861 public static int compare(final String str1, final String str2) { 862 return Strings.CS.compare(str1, str2); 863 } 864 865 /** 866 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 867 * <ul> 868 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 869 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 870 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 871 * </ul> 872 * 873 * <p> 874 * This is a {@code null} safe version of : 875 * </p> 876 * 877 * <pre> 878 * str1.compareTo(str2) 879 * </pre> 880 * 881 * <p> 882 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. 883 * </p> 884 * 885 * <pre>{@code 886 * StringUtils.compare(null, null, *) = 0 887 * StringUtils.compare(null , "a", true) < 0 888 * StringUtils.compare(null , "a", false) > 0 889 * StringUtils.compare("a", null, true) > 0 890 * StringUtils.compare("a", null, false) < 0 891 * StringUtils.compare("abc", "abc", *) = 0 892 * StringUtils.compare("a", "b", *) < 0 893 * StringUtils.compare("b", "a", *) > 0 894 * StringUtils.compare("a", "B", *) > 0 895 * StringUtils.compare("ab", "abc", *) < 0 896 * }</pre> 897 * 898 * @param str1 The String to compare from. 899 * @param str2 The String to compare to. 900 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 901 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}. 902 * @see String#compareTo(String) 903 * @since 3.5 904 */ 905 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 906 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 907 return 0; 908 } 909 if (str1 == null) { 910 return nullIsLess ? -1 : 1; 911 } 912 if (str2 == null) { 913 return nullIsLess ? 1 : -1; 914 } 915 return str1.compareTo(str2); 916 } 917 918 /** 919 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 920 * <ul> 921 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 922 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 923 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 924 * </ul> 925 * 926 * <p> 927 * This is a {@code null} safe version of: 928 * </p> 929 * 930 * <pre> 931 * str1.compareToIgnoreCase(str2) 932 * </pre> 933 * 934 * <p> 935 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive. 936 * </p> 937 * 938 * <pre>{@code 939 * StringUtils.compareIgnoreCase(null, null) = 0 940 * StringUtils.compareIgnoreCase(null , "a") < 0 941 * StringUtils.compareIgnoreCase("a", null) > 0 942 * StringUtils.compareIgnoreCase("abc", "abc") = 0 943 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 944 * StringUtils.compareIgnoreCase("a", "b") < 0 945 * StringUtils.compareIgnoreCase("b", "a") > 0 946 * StringUtils.compareIgnoreCase("a", "B") < 0 947 * StringUtils.compareIgnoreCase("A", "b") < 0 948 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 949 * }</pre> 950 * 951 * @param str1 The String to compare from. 952 * @param str2 The String to compare to. 953 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 954 * @see #compareIgnoreCase(String, String, boolean) 955 * @see String#compareToIgnoreCase(String) 956 * @since 3.5 957 * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}. 958 */ 959 @Deprecated 960 public static int compareIgnoreCase(final String str1, final String str2) { 961 return Strings.CI.compare(str1, str2); 962 } 963 964 /** 965 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 966 * <ul> 967 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 968 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 969 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 970 * </ul> 971 * 972 * <p> 973 * This is a {@code null} safe version of : 974 * </p> 975 * <pre> 976 * str1.compareToIgnoreCase(str2) 977 * </pre> 978 * 979 * <p> 980 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case 981 * insensitive. 982 * </p> 983 * 984 * <pre>{@code 985 * StringUtils.compareIgnoreCase(null, null, *) = 0 986 * StringUtils.compareIgnoreCase(null , "a", true) < 0 987 * StringUtils.compareIgnoreCase(null , "a", false) > 0 988 * StringUtils.compareIgnoreCase("a", null, true) > 0 989 * StringUtils.compareIgnoreCase("a", null, false) < 0 990 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 991 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 992 * StringUtils.compareIgnoreCase("a", "b", *) < 0 993 * StringUtils.compareIgnoreCase("b", "a", *) > 0 994 * StringUtils.compareIgnoreCase("a", "B", *) < 0 995 * StringUtils.compareIgnoreCase("A", "b", *) < 0 996 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 997 * }</pre> 998 * 999 * @param str1 The String to compare from. 1000 * @param str2 The String to compare to. 1001 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 1002 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 1003 * @see String#compareToIgnoreCase(String) 1004 * @since 3.5 1005 */ 1006 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 1007 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 1008 return 0; 1009 } 1010 if (str1 == null) { 1011 return nullIsLess ? -1 : 1; 1012 } 1013 if (str2 == null) { 1014 return nullIsLess ? 1 : -1; 1015 } 1016 return str1.compareToIgnoreCase(str2); 1017 } 1018 1019 /** 1020 * Tests if CharSequence contains a search CharSequence, handling {@code null}. 1021 * This method uses {@link String#indexOf(String)} if possible. 1022 * 1023 * <p> 1024 * A {@code null} CharSequence will return {@code false}. 1025 * </p> 1026 * 1027 * <pre> 1028 * StringUtils.contains(null, *) = false 1029 * StringUtils.contains(*, null) = false 1030 * StringUtils.contains("", "") = true 1031 * StringUtils.contains("abc", "") = true 1032 * StringUtils.contains("abc", "a") = true 1033 * StringUtils.contains("abc", "z") = false 1034 * </pre> 1035 * 1036 * @param seq The CharSequence to check, may be null 1037 * @param searchSeq The CharSequence to find, may be null 1038 * @return true if the CharSequence contains the search CharSequence, 1039 * false if not or {@code null} string input 1040 * @since 2.0 1041 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 1042 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}. 1043 */ 1044 @Deprecated 1045 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 1046 return Strings.CS.contains(seq, searchSeq); 1047 } 1048 1049 /** 1050 * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible. 1051 * 1052 * <p> 1053 * A {@code null} or empty ("") CharSequence will return {@code false}. 1054 * </p> 1055 * 1056 * <pre> 1057 * StringUtils.contains(null, *) = false 1058 * StringUtils.contains("", *) = false 1059 * StringUtils.contains("abc", 'a') = true 1060 * StringUtils.contains("abc", 'z') = false 1061 * </pre> 1062 * 1063 * @param seq The CharSequence to check, may be null 1064 * @param searchChar The character to find 1065 * @return true if the CharSequence contains the search character, false if not or {@code null} string input 1066 * @since 2.0 1067 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1068 */ 1069 public static boolean contains(final CharSequence seq, final int searchChar) { 1070 if (isEmpty(seq)) { 1071 return false; 1072 } 1073 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1074 } 1075 1076 /** 1077 * Tests if the CharSequence contains any character in the given set of characters. 1078 * 1079 * <p> 1080 * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}. 1081 * </p> 1082 * 1083 * <pre> 1084 * StringUtils.containsAny(null, *) = false 1085 * StringUtils.containsAny("", *) = false 1086 * StringUtils.containsAny(*, null) = false 1087 * StringUtils.containsAny(*, []) = false 1088 * StringUtils.containsAny("zzabyycdxx", 'z', 'a') = true 1089 * StringUtils.containsAny("zzabyycdxx", 'b', 'y') = true 1090 * StringUtils.containsAny("zzabyycdxx", 'z', 'y') = true 1091 * StringUtils.containsAny("aba", 'z]) = false 1092 * </pre> 1093 * 1094 * @param cs The CharSequence to check, may be null. 1095 * @param searchChars The chars to search for, may be null. 1096 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input. 1097 * @since 2.4 1098 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1099 */ 1100 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1101 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1102 return false; 1103 } 1104 final int csLength = cs.length(); 1105 final int searchLength = searchChars.length; 1106 final int csLast = csLength - 1; 1107 final int searchLast = searchLength - 1; 1108 for (int i = 0; i < csLength; i++) { 1109 final char ch = cs.charAt(i); 1110 for (int j = 0; j < searchLength; j++) { 1111 if (searchChars[j] == ch) { 1112 if (Character.isHighSurrogate(ch) 1113 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 1114 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 1115 return true; 1116 } 1117 } 1118 } 1119 } 1120 return false; 1121 } 1122 1123 /** 1124 * Tests if the CharSequence contains any character in the given set of characters. 1125 * 1126 * <p> 1127 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}. 1128 * </p> 1129 * 1130 * <pre> 1131 * StringUtils.containsAny(null, *) = false 1132 * StringUtils.containsAny("", *) = false 1133 * StringUtils.containsAny(*, null) = false 1134 * StringUtils.containsAny(*, "") = false 1135 * StringUtils.containsAny("zzabyycdxx", "za") = true 1136 * StringUtils.containsAny("zzabyycdxx", "by") = true 1137 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1138 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1139 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1140 * StringUtils.containsAny("aba", "z") = false 1141 * </pre> 1142 * 1143 * @param cs The CharSequence to check, may be null. 1144 * @param searchChars The chars to search for, may be null. 1145 * @return The {@code true} if any of the chars are found, {@code false} if no match or null input. 1146 * @since 2.4 1147 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1148 */ 1149 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1150 if (searchChars == null) { 1151 return false; 1152 } 1153 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1154 } 1155 1156 /** 1157 * Tests if the CharSequence contains any of the CharSequences in the given array. 1158 * 1159 * <p> 1160 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1161 * return {@code false}. 1162 * </p> 1163 * 1164 * <pre> 1165 * StringUtils.containsAny(null, *) = false 1166 * StringUtils.containsAny("", *) = false 1167 * StringUtils.containsAny(*, null) = false 1168 * StringUtils.containsAny(*, []) = false 1169 * StringUtils.containsAny("abcd", "ab", null) = true 1170 * StringUtils.containsAny("abcd", "ab", "cd") = true 1171 * StringUtils.containsAny("abc", "d", "abc") = true 1172 * </pre> 1173 * 1174 * @param cs The CharSequence to check, may be null. 1175 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1176 * null as well. 1177 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise. 1178 * @since 3.4 1179 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}. 1180 */ 1181 @Deprecated 1182 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1183 return Strings.CS.containsAny(cs, searchCharSequences); 1184 } 1185 1186 /** 1187 * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case. 1188 * 1189 * <p> 1190 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1191 * return {@code false}. 1192 * </p> 1193 * 1194 * <pre> 1195 * StringUtils.containsAny(null, *) = false 1196 * StringUtils.containsAny("", *) = false 1197 * StringUtils.containsAny(*, null) = false 1198 * StringUtils.containsAny(*, []) = false 1199 * StringUtils.containsAny("abcd", "ab", null) = true 1200 * StringUtils.containsAny("abcd", "ab", "cd") = true 1201 * StringUtils.containsAny("abc", "d", "abc") = true 1202 * StringUtils.containsAny("abc", "D", "ABC") = true 1203 * StringUtils.containsAny("ABC", "d", "abc") = true 1204 * </pre> 1205 * 1206 * @param cs The CharSequence to check, may be null. 1207 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1208 * null as well. 1209 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1210 * @since 3.12.0 1211 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}. 1212 */ 1213 @Deprecated 1214 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) { 1215 return Strings.CI.containsAny(cs, searchCharSequences); 1216 } 1217 1218 /** 1219 * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by 1220 * {@link String#equalsIgnoreCase(String)}. 1221 * 1222 * <p> 1223 * A {@code null} CharSequence will return {@code false}. 1224 * </p> 1225 * 1226 * <pre> 1227 * StringUtils.containsIgnoreCase(null, *) = false 1228 * StringUtils.containsIgnoreCase(*, null) = false 1229 * StringUtils.containsIgnoreCase("", "") = true 1230 * StringUtils.containsIgnoreCase("abc", "") = true 1231 * StringUtils.containsIgnoreCase("abc", "a") = true 1232 * StringUtils.containsIgnoreCase("abc", "z") = false 1233 * StringUtils.containsIgnoreCase("abc", "A") = true 1234 * StringUtils.containsIgnoreCase("abc", "Z") = false 1235 * </pre> 1236 * 1237 * @param str The CharSequence to check, may be null. 1238 * @param searchStr The CharSequence to find, may be null. 1239 * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input. 1240 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence). 1241 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}. 1242 */ 1243 @Deprecated 1244 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1245 return Strings.CI.contains(str, searchStr); 1246 } 1247 1248 /** 1249 * Tests that the CharSequence does not contain certain characters. 1250 * 1251 * <p> 1252 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0) 1253 * always returns true. 1254 * </p> 1255 * 1256 * <pre> 1257 * StringUtils.containsNone(null, *) = true 1258 * StringUtils.containsNone(*, null) = true 1259 * StringUtils.containsNone("", *) = true 1260 * StringUtils.containsNone("ab", '') = true 1261 * StringUtils.containsNone("abab", 'x', 'y', 'z') = true 1262 * StringUtils.containsNone("ab1", 'x', 'y', 'z') = true 1263 * StringUtils.containsNone("abz", 'x', 'y', 'z') = false 1264 * </pre> 1265 * 1266 * @param cs The CharSequence to check, may be null. 1267 * @param searchChars An array of invalid chars, may be null. 1268 * @return true if it contains none of the invalid chars, or is null. 1269 * @since 2.0 1270 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1271 */ 1272 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1273 if (cs == null || searchChars == null) { 1274 return true; 1275 } 1276 final int csLen = cs.length(); 1277 final int csLast = csLen - 1; 1278 final int searchLen = searchChars.length; 1279 final int searchLast = searchLen - 1; 1280 for (int i = 0; i < csLen; i++) { 1281 final char ch = cs.charAt(i); 1282 for (int j = 0; j < searchLen; j++) { 1283 if (searchChars[j] == ch) { 1284 if (Character.isHighSurrogate(ch) 1285 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 1286 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 1287 return false; 1288 } 1289 } 1290 } 1291 } 1292 return true; 1293 } 1294 1295 /** 1296 * Tests that the CharSequence does not contain certain characters. 1297 * 1298 * <p> 1299 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always 1300 * returns true. 1301 * </p> 1302 * 1303 * <pre> 1304 * StringUtils.containsNone(null, *) = true 1305 * StringUtils.containsNone(*, null) = true 1306 * StringUtils.containsNone("", *) = true 1307 * StringUtils.containsNone("ab", "") = true 1308 * StringUtils.containsNone("abab", "xyz") = true 1309 * StringUtils.containsNone("ab1", "xyz") = true 1310 * StringUtils.containsNone("abz", "xyz") = false 1311 * </pre> 1312 * 1313 * @param cs The CharSequence to check, may be null. 1314 * @param invalidChars A String of invalid chars, may be null. 1315 * @return true if it contains none of the invalid chars, or is null. 1316 * @since 2.0 1317 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1318 */ 1319 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1320 if (invalidChars == null) { 1321 return true; 1322 } 1323 return containsNone(cs, invalidChars.toCharArray()); 1324 } 1325 1326 /** 1327 * Tests if the CharSequence contains only certain characters. 1328 * 1329 * <p> 1330 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0) 1331 * always returns {@code true}. 1332 * </p> 1333 * 1334 * <pre> 1335 * StringUtils.containsOnly(null, *) = false 1336 * StringUtils.containsOnly(*, null) = false 1337 * StringUtils.containsOnly("", *) = true 1338 * StringUtils.containsOnly("ab", '') = false 1339 * StringUtils.containsOnly("abab", 'a', 'b', 'c') = true 1340 * StringUtils.containsOnly("ab1", 'a', 'b', 'c') = false 1341 * StringUtils.containsOnly("abz", 'a', 'b', 'c') = false 1342 * </pre> 1343 * 1344 * @param cs The String to check, may be null. 1345 * @param valid An array of valid chars, may be null. 1346 * @return true if it only contains valid chars and is non-null. 1347 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1348 */ 1349 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1350 // All these pre-checks are to maintain API with an older version 1351 if (valid == null || cs == null) { 1352 return false; 1353 } 1354 if (isEmpty(cs)) { 1355 return true; 1356 } 1357 if (valid.length == 0) { 1358 return false; 1359 } 1360 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1361 } 1362 1363 /** 1364 * Tests if the CharSequence contains only certain characters. 1365 * 1366 * <p> 1367 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0) 1368 * always returns {@code true}. 1369 * </p> 1370 * 1371 * <pre> 1372 * StringUtils.containsOnly(null, *) = false 1373 * StringUtils.containsOnly(*, null) = false 1374 * StringUtils.containsOnly("", *) = true 1375 * StringUtils.containsOnly("ab", "") = false 1376 * StringUtils.containsOnly("abab", "abc") = true 1377 * StringUtils.containsOnly("ab1", "abc") = false 1378 * StringUtils.containsOnly("abz", "abc") = false 1379 * </pre> 1380 * 1381 * @param cs The CharSequence to check, may be null. 1382 * @param validChars A String of valid chars, may be null. 1383 * @return true if it only contains valid chars and is non-null. 1384 * @since 2.0 1385 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1386 */ 1387 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1388 if (cs == null || validChars == null) { 1389 return false; 1390 } 1391 return containsOnly(cs, validChars.toCharArray()); 1392 } 1393 1394 /** 1395 * Tests whether the given CharSequence contains any whitespace characters. 1396 * 1397 * <p> 1398 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1399 * </p> 1400 * 1401 * <pre> 1402 * StringUtils.containsWhitespace(null) = false 1403 * StringUtils.containsWhitespace("") = false 1404 * StringUtils.containsWhitespace("ab") = false 1405 * StringUtils.containsWhitespace(" ab") = true 1406 * StringUtils.containsWhitespace("a b") = true 1407 * StringUtils.containsWhitespace("ab ") = true 1408 * </pre> 1409 * 1410 * @param seq The CharSequence to check (may be {@code null}). 1411 * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character. 1412 * @since 3.0 1413 */ 1414 public static boolean containsWhitespace(final CharSequence seq) { 1415 if (isEmpty(seq)) { 1416 return false; 1417 } 1418 final int strLen = seq.length(); 1419 for (int i = 0; i < strLen; i++) { 1420 if (Character.isWhitespace(seq.charAt(i))) { 1421 return true; 1422 } 1423 } 1424 return false; 1425 } 1426 1427 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1428 for (int i = 0; i < decomposed.length(); i++) { 1429 final char charAt = decomposed.charAt(i); 1430 switch (charAt) { 1431 case '\u0141': 1432 decomposed.setCharAt(i, 'L'); 1433 break; 1434 case '\u0142': 1435 decomposed.setCharAt(i, 'l'); 1436 break; 1437 // D with stroke 1438 case '\u0110': 1439 // LATIN CAPITAL LETTER D WITH STROKE 1440 decomposed.setCharAt(i, 'D'); 1441 break; 1442 case '\u0111': 1443 // LATIN SMALL LETTER D WITH STROKE 1444 decomposed.setCharAt(i, 'd'); 1445 break; 1446 // I with bar 1447 case '\u0197': 1448 decomposed.setCharAt(i, 'I'); 1449 break; 1450 case '\u0268': 1451 decomposed.setCharAt(i, 'i'); 1452 break; 1453 case '\u1D7B': 1454 decomposed.setCharAt(i, 'I'); 1455 break; 1456 case '\u1DA4': 1457 decomposed.setCharAt(i, 'i'); 1458 break; 1459 case '\u1DA7': 1460 decomposed.setCharAt(i, 'I'); 1461 break; 1462 // U with bar 1463 case '\u0244': 1464 // LATIN CAPITAL LETTER U BAR 1465 decomposed.setCharAt(i, 'U'); 1466 break; 1467 case '\u0289': 1468 // LATIN SMALL LETTER U BAR 1469 decomposed.setCharAt(i, 'u'); 1470 break; 1471 case '\u1D7E': 1472 // LATIN SMALL CAPITAL LETTER U WITH STROKE 1473 decomposed.setCharAt(i, 'U'); 1474 break; 1475 case '\u1DB6': 1476 // MODIFIER LETTER SMALL U BAR 1477 decomposed.setCharAt(i, 'u'); 1478 break; 1479 // T with stroke 1480 case '\u0166': 1481 // LATIN CAPITAL LETTER T WITH STROKE 1482 decomposed.setCharAt(i, 'T'); 1483 break; 1484 case '\u0167': 1485 // LATIN SMALL LETTER T WITH STROKE 1486 decomposed.setCharAt(i, 't'); 1487 break; 1488 default: 1489 break; 1490 } 1491 } 1492 } 1493 1494 /** 1495 * Counts how many times the char appears in the given string. 1496 * 1497 * <p> 1498 * A {@code null} or empty ("") String input returns {@code 0}. 1499 * </p> 1500 * 1501 * <pre> 1502 * StringUtils.countMatches(null, *) = 0 1503 * StringUtils.countMatches("", *) = 0 1504 * StringUtils.countMatches("abba", 0) = 0 1505 * StringUtils.countMatches("abba", 'a') = 2 1506 * StringUtils.countMatches("abba", 'b') = 2 1507 * StringUtils.countMatches("abba", 'x') = 0 1508 * </pre> 1509 * 1510 * @param str The CharSequence to check, may be null. 1511 * @param ch The char to count. 1512 * @return The number of occurrences, 0 if the CharSequence is {@code null}. 1513 * @since 3.4 1514 */ 1515 public static int countMatches(final CharSequence str, final char ch) { 1516 if (isEmpty(str)) { 1517 return 0; 1518 } 1519 int count = 0; 1520 // We could also call str.toCharArray() for faster lookups but that would generate more garbage. 1521 for (int i = 0; i < str.length(); i++) { 1522 if (ch == str.charAt(i)) { 1523 count++; 1524 } 1525 } 1526 return count; 1527 } 1528 1529 /** 1530 * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches. 1531 * 1532 * <p> 1533 * A {@code null} or empty ("") String input returns {@code 0}. 1534 * </p> 1535 * 1536 * <pre> 1537 * StringUtils.countMatches(null, *) = 0 1538 * StringUtils.countMatches("", *) = 0 1539 * StringUtils.countMatches("abba", null) = 0 1540 * StringUtils.countMatches("abba", "") = 0 1541 * StringUtils.countMatches("abba", "a") = 2 1542 * StringUtils.countMatches("abba", "ab") = 1 1543 * StringUtils.countMatches("abba", "xxx") = 0 1544 * StringUtils.countMatches("ababa", "aba") = 1 1545 * </pre> 1546 * 1547 * @param str The CharSequence to check, may be null. 1548 * @param sub The substring to count, may be null. 1549 * @return The number of occurrences, 0 if either CharSequence is {@code null}. 1550 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1551 */ 1552 public static int countMatches(final CharSequence str, final CharSequence sub) { 1553 if (isEmpty(str) || isEmpty(sub)) { 1554 return 0; 1555 } 1556 int count = 0; 1557 int idx = 0; 1558 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1559 count++; 1560 idx += sub.length(); 1561 } 1562 return count; 1563 } 1564 1565 /** 1566 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1567 * {@code null}), the value of {@code defaultStr}. 1568 * 1569 * <p> 1570 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1571 * </p> 1572 * 1573 * <pre> 1574 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1575 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1576 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1577 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1578 * StringUtils.defaultIfBlank("", null) = null 1579 * </pre> 1580 * 1581 * @param <T> the specific kind of CharSequence. 1582 * @param str The CharSequence to check, may be null. 1583 * @param defaultStr The default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1584 * {@code null}); may be null. 1585 * @return The passed in CharSequence, or the default. 1586 * @see StringUtils#defaultString(String, String) 1587 * @see #isBlank(CharSequence) 1588 */ 1589 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1590 return isBlank(str) ? defaultStr : str; 1591 } 1592 1593 /** 1594 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}. 1595 * 1596 * <pre> 1597 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1598 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1599 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1600 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1601 * StringUtils.defaultIfEmpty("", null) = null 1602 * </pre> 1603 * 1604 * @param <T> the specific kind of CharSequence. 1605 * @param str The CharSequence to check, may be null. 1606 * @param defaultStr The default CharSequence to return if the input is empty ("") or {@code null}, may be null. 1607 * @return The passed in CharSequence, or the default. 1608 * @see StringUtils#defaultString(String, String) 1609 */ 1610 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1611 return isEmpty(str) ? defaultStr : str; 1612 } 1613 1614 /** 1615 * Returns either the passed in String, or if the String is {@code null}, an empty String (""). 1616 * 1617 * <pre> 1618 * StringUtils.defaultString(null) = "" 1619 * StringUtils.defaultString("") = "" 1620 * StringUtils.defaultString("bat") = "bat" 1621 * </pre> 1622 * 1623 * @param str The String to check, may be null. 1624 * @return The passed in String, or the empty String if it was {@code null}. 1625 * @see Objects#toString(Object, String) 1626 * @see String#valueOf(Object) 1627 */ 1628 public static String defaultString(final String str) { 1629 return Objects.toString(str, EMPTY); 1630 } 1631 1632 /** 1633 * Returns either the given String, or if the String is {@code null}, {@code nullDefault}. 1634 * 1635 * <pre> 1636 * StringUtils.defaultString(null, "NULL") = "NULL" 1637 * StringUtils.defaultString("", "NULL") = "" 1638 * StringUtils.defaultString("bat", "NULL") = "bat" 1639 * </pre> 1640 * <p> 1641 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}: 1642 * </p> 1643 * 1644 * <pre> 1645 * Objects.toString(null, "NULL") = "NULL" 1646 * Objects.toString("", "NULL") = "" 1647 * Objects.toString("bat", "NULL") = "bat" 1648 * </pre> 1649 * 1650 * @param str The String to check, may be null. 1651 * @param nullDefault The default String to return if the input is {@code null}, may be null. 1652 * @return The passed in String, or the default if it was {@code null}. 1653 * @see Objects#toString(Object, String) 1654 * @see String#valueOf(Object) 1655 * @deprecated Use {@link Objects#toString(Object, String)}. 1656 */ 1657 @Deprecated 1658 public static String defaultString(final String str, final String nullDefault) { 1659 return Objects.toString(str, nullDefault); 1660 } 1661 1662 /** 1663 * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}. 1664 * 1665 * <pre> 1666 * StringUtils.deleteWhitespace(null) = null 1667 * StringUtils.deleteWhitespace("") = "" 1668 * StringUtils.deleteWhitespace("abc") = "abc" 1669 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1670 * </pre> 1671 * 1672 * @param str The String to delete whitespace from, may be null. 1673 * @return The String without whitespaces, {@code null} if null String input. 1674 */ 1675 public static String deleteWhitespace(final String str) { 1676 if (isEmpty(str)) { 1677 return str; 1678 } 1679 final int sz = str.length(); 1680 final char[] chs = new char[sz]; 1681 int count = 0; 1682 for (int i = 0; i < sz; i++) { 1683 if (!Character.isWhitespace(str.charAt(i))) { 1684 chs[count++] = str.charAt(i); 1685 } 1686 } 1687 if (count == sz) { 1688 return str; 1689 } 1690 if (count == 0) { 1691 return EMPTY; 1692 } 1693 return new String(chs, 0, count); 1694 } 1695 1696 /** 1697 * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's 1698 * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c". 1699 * 1700 * <p> 1701 * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}. 1702 * </p> 1703 * 1704 * <pre> 1705 * StringUtils.difference(null, null) = null 1706 * StringUtils.difference("", "") = "" 1707 * StringUtils.difference("", "abc") = "abc" 1708 * StringUtils.difference("abc", "") = "" 1709 * StringUtils.difference("abc", "abc") = "" 1710 * StringUtils.difference("abc", "ab") = "" 1711 * StringUtils.difference("ab", "abxyz") = "xyz" 1712 * StringUtils.difference("abcde", "abxyz") = "xyz" 1713 * StringUtils.difference("abcde", "xyz") = "xyz" 1714 * </pre> 1715 * 1716 * @param str1 The first String, may be null. 1717 * @param str2 The second String, may be null. 1718 * @return The portion of str2 where it differs from str1; returns the empty String if they are equal. 1719 * @see #indexOfDifference(CharSequence,CharSequence) 1720 * @since 2.0 1721 */ 1722 public static String difference(final String str1, final String str2) { 1723 if (str1 == null) { 1724 return str2; 1725 } 1726 if (str2 == null) { 1727 return str1; 1728 } 1729 final int at = indexOfDifference(str1, str2); 1730 if (at == INDEX_NOT_FOUND) { 1731 return EMPTY; 1732 } 1733 return str2.substring(at); 1734 } 1735 1736 /** 1737 * Tests if a CharSequence ends with a specified suffix. 1738 * 1739 * <p> 1740 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 1741 * </p> 1742 * 1743 * <pre> 1744 * StringUtils.endsWith(null, null) = true 1745 * StringUtils.endsWith(null, "def") = false 1746 * StringUtils.endsWith("abcdef", null) = false 1747 * StringUtils.endsWith("abcdef", "def") = true 1748 * StringUtils.endsWith("ABCDEF", "def") = false 1749 * StringUtils.endsWith("ABCDEF", "cde") = false 1750 * StringUtils.endsWith("ABCDEF", "") = true 1751 * </pre> 1752 * 1753 * @param str The CharSequence to check, may be null. 1754 * @param suffix The suffix to find, may be null. 1755 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}. 1756 * @see String#endsWith(String) 1757 * @since 2.4 1758 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1759 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}. 1760 */ 1761 @Deprecated 1762 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1763 return Strings.CS.endsWith(str, suffix); 1764 } 1765 1766 /** 1767 * Tests if a CharSequence ends with any of the provided case-sensitive suffixes. 1768 * 1769 * <pre> 1770 * StringUtils.endsWithAny(null, null) = false 1771 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1772 * StringUtils.endsWithAny("abcxyz", null) = false 1773 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1774 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1775 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1776 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1777 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1778 * </pre> 1779 * 1780 * @param sequence The CharSequence to check, may be null. 1781 * @param searchStrings The case-sensitive CharSequences to find, may be empty or contain {@code null}. 1782 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} ends in any 1783 * of the provided case-sensitive {@code searchStrings}. 1784 * @see StringUtils#endsWith(CharSequence, CharSequence) 1785 * @since 3.0 1786 * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}. 1787 */ 1788 @Deprecated 1789 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1790 return Strings.CS.endsWithAny(sequence, searchStrings); 1791 } 1792 1793 /** 1794 * Case-insensitive check if a CharSequence ends with a specified suffix. 1795 * 1796 * <p> 1797 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 1798 * </p> 1799 * 1800 * <pre> 1801 * StringUtils.endsWithIgnoreCase(null, null) = true 1802 * StringUtils.endsWithIgnoreCase(null, "def") = false 1803 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1804 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1805 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1806 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1807 * </pre> 1808 * 1809 * @param str The CharSequence to check, may be null 1810 * @param suffix The suffix to find, may be null 1811 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null} 1812 * @see String#endsWith(String) 1813 * @since 2.4 1814 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1815 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)}. 1816 */ 1817 @Deprecated 1818 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1819 return Strings.CI.endsWith(str, suffix); 1820 } 1821 1822 /** 1823 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters. 1824 * 1825 * <p> 1826 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>. 1827 * </p> 1828 * 1829 * <pre> 1830 * StringUtils.equals(null, null) = true 1831 * StringUtils.equals(null, "abc") = false 1832 * StringUtils.equals("abc", null) = false 1833 * StringUtils.equals("abc", "abc") = true 1834 * StringUtils.equals("abc", "ABC") = false 1835 * </pre> 1836 * 1837 * @param cs1 The first CharSequence, may be {@code null}. 1838 * @param cs2 The second CharSequence, may be {@code null}. 1839 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}. 1840 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1841 * @see Object#equals(Object) 1842 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1843 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}. 1844 */ 1845 @Deprecated 1846 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1847 return Strings.CS.equals(cs1, cs2); 1848 } 1849 1850 /** 1851 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the 1852 * {@code searchStrings}. 1853 * 1854 * <pre> 1855 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1856 * StringUtils.equalsAny(null, null, null) = true 1857 * StringUtils.equalsAny(null, "abc", "def") = false 1858 * StringUtils.equalsAny("abc", null, "def") = false 1859 * StringUtils.equalsAny("abc", "abc", "def") = true 1860 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1861 * </pre> 1862 * 1863 * @param string to compare, may be {@code null}. 1864 * @param searchStrings A vararg of strings, may be {@code null}. 1865 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is 1866 * null or contains no matches. 1867 * @since 3.5 1868 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}. 1869 */ 1870 @Deprecated 1871 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1872 return Strings.CS.equalsAny(string, searchStrings); 1873 } 1874 1875 /** 1876 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1877 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1878 * 1879 * <pre> 1880 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1881 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1882 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1883 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1884 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1885 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1886 * </pre> 1887 * 1888 * @param string to compare, may be {@code null}. 1889 * @param searchStrings A vararg of strings, may be {@code null}. 1890 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1891 * {@code false} if {@code searchStrings} is null or contains no matches. 1892 * @since 3.5 1893 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI.equalsAny(CharSequence, CharSequence...)}. 1894 */ 1895 @Deprecated 1896 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) { 1897 return Strings.CI.equalsAny(string, searchStrings); 1898 } 1899 1900 /** 1901 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case. 1902 * 1903 * <p> 1904 * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>. 1905 * </p> 1906 * 1907 * <pre> 1908 * StringUtils.equalsIgnoreCase(null, null) = true 1909 * StringUtils.equalsIgnoreCase(null, "abc") = false 1910 * StringUtils.equalsIgnoreCase("abc", null) = false 1911 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1912 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1913 * </pre> 1914 * 1915 * @param cs1 The first CharSequence, may be {@code null}. 1916 * @param cs2 The second CharSequence, may be {@code null}. 1917 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}. 1918 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1919 * @see #equals(CharSequence, CharSequence) 1920 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}. 1921 */ 1922 @Deprecated 1923 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1924 return Strings.CI.equals(cs1, cs2); 1925 } 1926 1927 /** 1928 * Returns the first value in the array which is not empty (""), {@code null} or whitespace only. 1929 * 1930 * <p> 1931 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1932 * </p> 1933 * 1934 * <p> 1935 * If all values are blank or the array is {@code null} or empty then {@code null} is returned. 1936 * </p> 1937 * 1938 * <pre> 1939 * StringUtils.firstNonBlank(null, null, null) = null 1940 * StringUtils.firstNonBlank(null, "", " ") = null 1941 * StringUtils.firstNonBlank("abc") = "abc" 1942 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1943 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1944 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1945 * StringUtils.firstNonBlank() = null 1946 * </pre> 1947 * 1948 * @param <T> the specific kind of CharSequence. 1949 * @param values The values to test, may be {@code null} or empty. 1950 * @return The first value from {@code values} which is not blank, or {@code null} if there are no non-blank values. 1951 * @since 3.8 1952 */ 1953 @SafeVarargs 1954 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1955 if (values != null) { 1956 for (final T val : values) { 1957 if (isNotBlank(val)) { 1958 return val; 1959 } 1960 } 1961 } 1962 return null; 1963 } 1964 1965 /** 1966 * Returns the first value in the array which is not empty. 1967 * 1968 * <p> 1969 * If all values are empty or the array is {@code null} or empty then {@code null} is returned. 1970 * </p> 1971 * 1972 * <pre> 1973 * StringUtils.firstNonEmpty(null, null, null) = null 1974 * StringUtils.firstNonEmpty(null, null, "") = null 1975 * StringUtils.firstNonEmpty(null, "", " ") = " " 1976 * StringUtils.firstNonEmpty("abc") = "abc" 1977 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1978 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1979 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1980 * StringUtils.firstNonEmpty() = null 1981 * </pre> 1982 * 1983 * @param <T> the specific kind of CharSequence. 1984 * @param values The values to test, may be {@code null} or empty. 1985 * @return The first value from {@code values} which is not empty, or {@code null} if there are no non-empty values. 1986 * @since 3.8 1987 */ 1988 @SafeVarargs 1989 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1990 if (values != null) { 1991 for (final T val : values) { 1992 if (isNotEmpty(val)) { 1993 return val; 1994 } 1995 } 1996 } 1997 return null; 1998 } 1999 2000 /** 2001 * Gets the bytes of the string using {@link String#getBytes(Charset)}, handling {@code null} safely. 2002 * 2003 * @param string input string. 2004 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 2005 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 2006 * @see String#getBytes(Charset) 2007 * @since 3.10 2008 */ 2009 public static byte[] getBytes(final String string, final Charset charset) { 2010 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 2011 } 2012 2013 /** 2014 * Gets the bytes of the string using {@link String#getBytes(String)}, handling {@code null} safely. 2015 * 2016 * @param string input string. 2017 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 2018 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 2019 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 2020 * @see String#getBytes(String) 2021 * @since 3.10 2022 */ 2023 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 2024 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 2025 } 2026 2027 /** 2028 * Gets the initial sequence of characters common to all strings in the array. 2029 * 2030 * <p> 2031 * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -> "i am a "} 2032 * </p> 2033 * 2034 * <pre> 2035 * StringUtils.getCommonPrefix(null) = "" 2036 * StringUtils.getCommonPrefix(new String[] {}) = "" 2037 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 2038 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 2039 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 2040 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 2041 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 2042 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 2043 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 2044 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 2045 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 2046 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 2047 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 2048 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 2049 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2050 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2051 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2052 * </pre> 2053 * 2054 * @param strs array of String objects, entries may be null. 2055 * @return The initial sequence of characters that are common to all Strings in the array; empty String if the array is null, the elements are all null or 2056 * if there is no common prefix. 2057 * @since 2.4 2058 */ 2059 public static String getCommonPrefix(final String... strs) { 2060 if (ArrayUtils.isEmpty(strs)) { 2061 return EMPTY; 2062 } 2063 final int smallestIndexOfDiff = indexOfDifference(strs); 2064 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2065 // all strings were identical 2066 if (strs[0] == null) { 2067 return EMPTY; 2068 } 2069 return strs[0]; 2070 } 2071 if (smallestIndexOfDiff == 0) { 2072 // there were no common initial characters 2073 return EMPTY; 2074 } 2075 // we found a common initial character sequence 2076 return strs[0].substring(0, smallestIndexOfDiff); 2077 } 2078 2079 /** 2080 * Gets the Unicode digits in {@code str}, concatenated in their original order. 2081 * 2082 * <p> 2083 * An empty ("") String will be returned if no digits are found in {@code str}. 2084 * </p> 2085 * 2086 * <pre> 2087 * StringUtils.getDigits(null) = null 2088 * StringUtils.getDigits("") = "" 2089 * StringUtils.getDigits("abc") = "" 2090 * StringUtils.getDigits("1000$") = "1000" 2091 * StringUtils.getDigits("1123~45") = "112345" 2092 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2093 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2094 * </pre> 2095 * 2096 * @param str The String to extract digits from, may be null. 2097 * @return String with only digits, or an empty ("") String if no digits are found, or {@code null} String if {@code str} is null. 2098 * @since 3.6 2099 */ 2100 public static String getDigits(final String str) { 2101 if (isEmpty(str)) { 2102 return str; 2103 } 2104 final int len = str.length(); 2105 final char[] buffer = new char[len]; 2106 int count = 0; 2107 2108 for (int i = 0; i < len;) { 2109 final int codePoint = str.codePointAt(i); 2110 if (Character.isDigit(codePoint)) { 2111 count += Character.toChars(codePoint, buffer, count); 2112 } 2113 i += Character.charCount(codePoint); 2114 } 2115 return new String(buffer, 0, count); 2116 } 2117 2118 /** 2119 * Gets the Fuzzy Distance which indicates the similarity score between two Strings. 2120 * 2121 * <p> 2122 * This string matching algorithm is similar to the algorithms of editors such as Sublime Text, TextMate, Atom and others. One point is given for every 2123 * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity. 2124 * </p> 2125 * 2126 * <pre> 2127 * StringUtils.getFuzzyDistance(null, null, null) = Throws {@link IllegalArgumentException} 2128 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2129 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2130 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2131 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2132 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2133 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2134 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2135 * </pre> 2136 * 2137 * @param term A full term that should be matched against, must not be null. 2138 * @param query The query that will be matched against a term, must not be null. 2139 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case. 2140 * @return result score. 2141 * @throws IllegalArgumentException Thrown if either String input {@code null} or Locale input {@code null}. 2142 * @since 3.4 2143 * @deprecated As of 3.6, use Apache Commons Text 2144 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2145 * FuzzyScore</a> instead. 2146 */ 2147 @Deprecated 2148 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2149 if (term == null || query == null) { 2150 throw new IllegalArgumentException("Strings must not be null"); 2151 } 2152 if (locale == null) { 2153 throw new IllegalArgumentException("Locale must not be null"); 2154 } 2155 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2156 // case right from the start. Turning characters to lower case 2157 // via Character.toLowerCase(char) is unfortunately insufficient 2158 // as it does not accept a locale. 2159 final String termLowerCase = term.toString().toLowerCase(locale); 2160 final String queryLowerCase = query.toString().toLowerCase(locale); 2161 // the resulting score 2162 int score = 0; 2163 // the position in the term which will be scanned next for potential 2164 // query character matches 2165 int termIndex = 0; 2166 // index of the previously matched character in the term 2167 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2168 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2169 final char queryChar = queryLowerCase.charAt(queryIndex); 2170 boolean termCharacterMatchFound = false; 2171 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2172 final char termChar = termLowerCase.charAt(termIndex); 2173 if (queryChar == termChar) { 2174 // simple character matches result in one point 2175 score++; 2176 // subsequent character matches further improve 2177 // the score. 2178 if (previousMatchingCharacterIndex + 1 == termIndex) { 2179 score += 2; 2180 } 2181 previousMatchingCharacterIndex = termIndex; 2182 // we can leave the nested loop. Every character in the 2183 // query can match at most one character in the term. 2184 termCharacterMatchFound = true; 2185 } 2186 } 2187 } 2188 return score; 2189 } 2190 2191 /** 2192 * Gets either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 2193 * {@code null}), the value supplied by {@code defaultStrSupplier}. 2194 * 2195 * <p> 2196 * Whitespace is defined by {@link Character#isWhitespace(char)}. 2197 * </p> 2198 * 2199 * <p> 2200 * The caller is responsible for thread safety and exception handling for the default value supplier. 2201 * </p> 2202 * 2203 * <pre> 2204 * {@code 2205 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2206 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2207 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2208 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2209 * StringUtils.getIfBlank("", () -> null) = null 2210 * StringUtils.getIfBlank("", null) = null 2211 * }</pre> 2212 * 2213 * @param <T> the specific kind of CharSequence. 2214 * @param str The CharSequence to check, may be null. 2215 * @param defaultSupplier The supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty 2216 * ({@code ""}), or {@code null}); may be null. 2217 * @return The passed in CharSequence, or the default 2218 * @see StringUtils#defaultString(String, String) 2219 * @see #isBlank(CharSequence) 2220 * @since 3.10 2221 */ 2222 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2223 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2224 } 2225 2226 /** 2227 * Gets either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2228 * 2229 * <p> 2230 * The caller is responsible for thread safety and exception handling for the default value supplier. 2231 * </p> 2232 * 2233 * <pre> 2234 * {@code 2235 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2236 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2237 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2238 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2239 * StringUtils.getIfEmpty("", () -> null) = null 2240 * StringUtils.getIfEmpty("", null) = null 2241 * } 2242 * </pre> 2243 * 2244 * @param <T> the specific kind of CharSequence. 2245 * @param str The CharSequence to check, may be null. 2246 * @param defaultSupplier The supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null. 2247 * @return The passed in CharSequence, or the default. 2248 * @see StringUtils#defaultString(String, String) 2249 * @since 3.10 2250 */ 2251 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2252 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2253 } 2254 2255 /** 2256 * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings. 2257 * 2258 * <p> 2259 * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for 2260 * matching initial characters. 2261 * </p> 2262 * 2263 * <p> 2264 * This implementation is based on the Jaro Winkler similarity algorithm from 2265 * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>. 2266 * </p> 2267 * 2268 * <pre> 2269 * StringUtils.getJaroWinklerDistance(null, null) = Throws {@link IllegalArgumentException} 2270 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2271 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2272 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2273 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2274 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2275 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2276 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2277 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2278 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2279 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2280 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2281 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2282 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2283 * </pre> 2284 * 2285 * @param first The first String, must not be null. 2286 * @param second The second String, must not be null. 2287 * @return result distance. 2288 * @throws IllegalArgumentException Thrown if either String input {@code null}. 2289 * @since 3.3 2290 * @deprecated As of 3.6, use Apache Commons Text 2291 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2292 * JaroWinklerDistance</a> instead. 2293 */ 2294 @Deprecated 2295 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2296 final double DEFAULT_SCALING_FACTOR = 0.1; 2297 2298 if (first == null || second == null) { 2299 throw new IllegalArgumentException("Strings must not be null"); 2300 } 2301 2302 final int[] mtp = matches(first, second); 2303 final double m = mtp[0]; 2304 if (m == 0) { 2305 return 0D; 2306 } 2307 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2308 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2309 return Math.round(jw * 100.0D) / 100.0D; 2310 } 2311 2312 /** 2313 * Gets the Levenshtein distance between two Strings. 2314 * 2315 * <p> 2316 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2317 * substitution). 2318 * </p> 2319 * 2320 * <p> 2321 * The implementation uses a single-dimensional array of length s.length() + 1. See 2322 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2323 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details. 2324 * </p> 2325 * 2326 * <pre> 2327 * StringUtils.getLevenshteinDistance(null, *) = Throws {@link IllegalArgumentException} 2328 * StringUtils.getLevenshteinDistance(*, null) = Throws {@link IllegalArgumentException} 2329 * StringUtils.getLevenshteinDistance("", "") = 0 2330 * StringUtils.getLevenshteinDistance("", "a") = 1 2331 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2332 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2333 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2334 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2335 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2336 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2337 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2338 * </pre> 2339 * 2340 * @param s The first String, must not be null. 2341 * @param t The second String, must not be null. 2342 * @return result distance. 2343 * @throws IllegalArgumentException Thrown if either String input {@code null}. 2344 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence) 2345 * @deprecated As of 3.6, use Apache Commons Text 2346 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2347 * LevenshteinDistance</a> instead. 2348 */ 2349 @Deprecated 2350 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2351 if (s == null || t == null) { 2352 throw new IllegalArgumentException("Strings must not be null"); 2353 } 2354 2355 int n = s.length(); 2356 int m = t.length(); 2357 2358 if (n == 0) { 2359 return m; 2360 } 2361 if (m == 0) { 2362 return n; 2363 } 2364 2365 if (n > m) { 2366 // swap the input strings to consume less memory 2367 final CharSequence tmp = s; 2368 s = t; 2369 t = tmp; 2370 n = m; 2371 m = t.length(); 2372 } 2373 2374 final int[] p = new int[n + 1]; 2375 // indexes into strings s and t 2376 int i; // iterates through s 2377 int j; // iterates through t 2378 int upperleft; 2379 int upper; 2380 2381 char jOfT; // jth character of t 2382 int cost; 2383 2384 for (i = 0; i <= n; i++) { 2385 p[i] = i; 2386 } 2387 2388 for (j = 1; j <= m; j++) { 2389 upperleft = p[0]; 2390 jOfT = t.charAt(j - 1); 2391 p[0] = j; 2392 2393 for (i = 1; i <= n; i++) { 2394 upper = p[i]; 2395 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2396 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2397 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2398 upperleft = upper; 2399 } 2400 } 2401 2402 return p[n]; 2403 } 2404 2405 /** 2406 * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold. 2407 * 2408 * <p> 2409 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2410 * substitution). 2411 * </p> 2412 * 2413 * <p> 2414 * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance 2415 * algorithm. 2416 * </p> 2417 * 2418 * <pre> 2419 * StringUtils.getLevenshteinDistance(null, *, *) = Throws {@link IllegalArgumentException} 2420 * StringUtils.getLevenshteinDistance(*, null, *) = Throws {@link IllegalArgumentException} 2421 * StringUtils.getLevenshteinDistance(*, *, -1) = Throws {@link IllegalArgumentException} 2422 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2423 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2424 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2425 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2426 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2427 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2428 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2429 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2430 * </pre> 2431 * 2432 * @param s The first String, must not be null. 2433 * @param t The second String, must not be null. 2434 * @param threshold The target threshold, must not be negative. 2435 * @return result distance, or {@code -1} if the distance would be greater than the threshold. 2436 * @throws IllegalArgumentException Thrown if either String input {@code null} or negative threshold. 2437 * @deprecated As of 3.6, use Apache Commons Text 2438 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2439 * LevenshteinDistance</a> instead. 2440 */ 2441 @Deprecated 2442 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2443 if (s == null || t == null) { 2444 throw new IllegalArgumentException("Strings must not be null"); 2445 } 2446 if (threshold < 0) { 2447 throw new IllegalArgumentException("Threshold must not be negative"); 2448 } 2449 2450 /* 2451 This implementation only computes the distance if it's less than or equal to the 2452 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2453 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2454 computing a diagonal stripe of width 2k + 1 of the cost table. 2455 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2456 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2457 d is the distance. 2458 2459 One subtlety comes from needing to ignore entries on the border of our stripe 2460 for example, 2461 p[] = |#|#|#|* 2462 d[] = *|#|#|#| 2463 We must ignore the entry to the left of the leftmost member 2464 We must ignore the entry above the rightmost member 2465 2466 Another subtlety comes from our stripe running off the matrix if the strings aren't 2467 of the same size. Since string s is always swapped to be the shorter of the two, 2468 the stripe will always run off to the upper right instead of the lower left of the matrix. 2469 2470 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2471 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2472 2473 1 2 3 4 5 2474 1 |#|#| | | | 2475 2 |#|#|#| | | 2476 3 | |#|#|#| | 2477 4 | | |#|#|#| 2478 5 | | | |#|#| 2479 6 | | | | |#| 2480 7 | | | | | | 2481 2482 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2483 into one of length 7 in edit distance of 1. 2484 2485 Additionally, this implementation decreases memory usage by using two 2486 single-dimensional arrays and swapping them back and forth instead of allocating 2487 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2488 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2489 large values so that entries we don't compute are ignored. 2490 2491 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2492 */ 2493 2494 int n = s.length(); // length of s 2495 int m = t.length(); // length of t 2496 2497 // if one string is empty, the edit distance is necessarily the length of the other 2498 if (n == 0) { 2499 return m <= threshold ? m : -1; 2500 } 2501 if (m == 0) { 2502 return n <= threshold ? n : -1; 2503 } 2504 if (Math.abs(n - m) > threshold) { 2505 // no need to calculate the distance if the length difference is greater than the threshold 2506 return -1; 2507 } 2508 2509 if (n > m) { 2510 // swap the two strings to consume less memory 2511 final CharSequence tmp = s; 2512 s = t; 2513 t = tmp; 2514 n = m; 2515 m = t.length(); 2516 } 2517 2518 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2519 int[] d = new int[n + 1]; // cost array, horizontally 2520 int[] tmp; // placeholder to assist in swapping p and d 2521 2522 // fill in starting table values 2523 final int boundary = Math.min(n, threshold) + 1; 2524 for (int i = 0; i < boundary; i++) { 2525 p[i] = i; 2526 } 2527 // these fills ensure that the value above the rightmost entry of our 2528 // stripe will be ignored in following loop iterations 2529 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2530 Arrays.fill(d, Integer.MAX_VALUE); 2531 2532 // iterates through t 2533 for (int j = 1; j <= m; j++) { 2534 final char jOfT = t.charAt(j - 1); // jth character of t 2535 d[0] = j; 2536 2537 // compute stripe indices, constrain to array size 2538 final int min = Math.max(1, j - threshold); 2539 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2540 2541 // the stripe may lead off of the table if s and t are of different sizes 2542 if (min > max) { 2543 return -1; 2544 } 2545 2546 // ignore entry left of leftmost 2547 if (min > 1) { 2548 d[min - 1] = Integer.MAX_VALUE; 2549 } 2550 2551 // iterates through [min, max] in s 2552 for (int i = min; i <= max; i++) { 2553 if (s.charAt(i - 1) == jOfT) { 2554 // diagonally left and up 2555 d[i] = p[i - 1]; 2556 } else { 2557 // 1 + minimum of cell to the left, to the top, diagonally left and up 2558 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2559 } 2560 } 2561 2562 // copy current distance counts to 'previous row' distance counts 2563 tmp = p; 2564 p = d; 2565 d = tmp; 2566 } 2567 2568 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2569 // distance 2570 if (p[n] <= threshold) { 2571 return p[n]; 2572 } 2573 return -1; 2574 } 2575 2576 /** 2577 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2578 * 2579 * <p> 2580 * A {@code null} CharSequence will return {@code -1}. 2581 * </p> 2582 * 2583 * <pre> 2584 * StringUtils.indexOf(null, *) = -1 2585 * StringUtils.indexOf(*, null) = -1 2586 * StringUtils.indexOf("", "") = 0 2587 * StringUtils.indexOf("", *) = -1 (except when * = "") 2588 * StringUtils.indexOf("aabaabaa", "a") = 0 2589 * StringUtils.indexOf("aabaabaa", "b") = 2 2590 * StringUtils.indexOf("aabaabaa", "ab") = 1 2591 * StringUtils.indexOf("aabaabaa", "") = 0 2592 * </pre> 2593 * 2594 * @param seq The CharSequence to check, may be null. 2595 * @param searchSeq The CharSequence to find, may be null. 2596 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 2597 * @since 2.0 2598 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2599 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}. 2600 */ 2601 @Deprecated 2602 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2603 return Strings.CS.indexOf(seq, searchSeq); 2604 } 2605 2606 /** 2607 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2608 * 2609 * <p> 2610 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 2611 * start position greater than the string length only matches an empty search CharSequence. 2612 * </p> 2613 * 2614 * <pre> 2615 * StringUtils.indexOf(null, *, *) = -1 2616 * StringUtils.indexOf(*, null, *) = -1 2617 * StringUtils.indexOf("", "", 0) = 0 2618 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2619 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2620 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2621 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2622 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2623 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2624 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2625 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2626 * StringUtils.indexOf("abc", "", 9) = 3 2627 * </pre> 2628 * 2629 * @param seq The CharSequence to check, may be null. 2630 * @param searchSeq The CharSequence to find, may be null. 2631 * @param startPos The start position, negative treated as zero. 2632 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 2633 * @since 2.0 2634 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2635 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}. 2636 */ 2637 @Deprecated 2638 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2639 return Strings.CS.indexOf(seq, searchSeq, startPos); 2640 } 2641 2642 /** 2643 * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the 2644 * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is 2645 * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that: 2646 * 2647 * <pre> 2648 * this.charAt(<em>k</em>) == searchChar 2649 * </pre> 2650 * 2651 * <p> 2652 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2653 * </p> 2654 * 2655 * <pre> 2656 * this.codePointAt(<em>k</em>) == searchChar 2657 * </pre> 2658 * 2659 * <p> 2660 * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned. 2661 * </p> 2662 * 2663 * <p> 2664 * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}. 2665 * </p> 2666 * 2667 * <pre> 2668 * StringUtils.indexOf(null, *) = -1 2669 * StringUtils.indexOf("", *) = -1 2670 * StringUtils.indexOf("aabaabaa", 'a') = 0 2671 * StringUtils.indexOf("aabaabaa", 'b') = 2 2672 * StringUtils.indexOf("aaaaaaaa", 'Z') = -1 2673 * </pre> 2674 * 2675 * @param seq The CharSequence to check, may be null. 2676 * @param searchChar The character to find. 2677 * @return The first index of the search character, -1 if no match or {@code null} string input. 2678 * @since 2.0 2679 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2680 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2681 */ 2682 public static int indexOf(final CharSequence seq, final int searchChar) { 2683 if (isEmpty(seq)) { 2684 return INDEX_NOT_FOUND; 2685 } 2686 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2687 } 2688 2689 /** 2690 * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index. 2691 * <p> 2692 * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no 2693 * smaller than {@code startPos}, then the index of the first such occurrence is returned. For values of {@code searchChar} in the range from 0 to 0xFFFF 2694 * (inclusive), this is the smallest value <em>k</em> such that: 2695 * </p> 2696 * 2697 * <pre> 2698 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2699 * </pre> 2700 * 2701 * <p> 2702 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2703 * </p> 2704 * 2705 * <pre> 2706 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2707 * </pre> 2708 * 2709 * <p> 2710 * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned. 2711 * </p> 2712 * 2713 * <p> 2714 * There is no restriction on the value of {@code startPos}. If it is negative, it has the same effect as if it were zero: this entire string may be 2715 * searched. If it is greater than the length of this string, it has the same effect as if it were equal to the length of this string: 2716 * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}. 2717 * </p> 2718 * <p> 2719 * All indices are specified in {@code char} values (Unicode code units). 2720 * </p> 2721 * 2722 * <pre> 2723 * StringUtils.indexOf(null, *, *) = -1 2724 * StringUtils.indexOf("", *, *) = -1 2725 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2726 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2727 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2728 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2729 * </pre> 2730 * 2731 * @param seq The CharSequence to check, may be null. 2732 * @param searchChar The character to find. 2733 * @param startPos The start position, negative treated as zero. 2734 * @return The first index of the search character (always ≥ startPos), -1 if no match or {@code null} string input. 2735 * @since 2.0 2736 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2737 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2738 */ 2739 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2740 if (isEmpty(seq)) { 2741 return INDEX_NOT_FOUND; 2742 } 2743 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2744 } 2745 2746 /** 2747 * Search a CharSequence to find the first index of any character in the given set of characters. 2748 * 2749 * <p> 2750 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2751 * </p> 2752 * 2753 * <pre> 2754 * StringUtils.indexOfAny(null, *) = -1 2755 * StringUtils.indexOfAny("", *) = -1 2756 * StringUtils.indexOfAny(*, null) = -1 2757 * StringUtils.indexOfAny(*, []) = -1 2758 * StringUtils.indexOfAny("zzabyycdxx", 'z', 'a') = 0 2759 * StringUtils.indexOfAny("zzabyycdxx", 'b', 'y') = 3 2760 * StringUtils.indexOfAny("aba", 'z') = -1 2761 * </pre> 2762 * 2763 * @param cs The CharSequence to check, may be null. 2764 * @param searchChars The chars to search for, may be null. 2765 * @return The index of any of the chars, -1 if no match or null input. 2766 * @since 2.0 2767 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2768 */ 2769 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2770 return indexOfAny(cs, 0, searchChars); 2771 } 2772 2773 /** 2774 * Find the first index of any of a set of potential substrings. 2775 * 2776 * <p> 2777 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. A {@code null} search array entry 2778 * will be ignored, but a search array containing "" will return {@code 0} if {@code str} is not null. This method uses {@link String#indexOf(String)} if 2779 * possible. 2780 * </p> 2781 * 2782 * <pre> 2783 * StringUtils.indexOfAny(null, *) = -1 2784 * StringUtils.indexOfAny(*, null) = -1 2785 * StringUtils.indexOfAny(*, []) = -1 2786 * StringUtils.indexOfAny("zzabyycdxx", "ab", "cd") = 2 2787 * StringUtils.indexOfAny("zzabyycdxx", "cd", "ab") = 2 2788 * StringUtils.indexOfAny("zzabyycdxx", "mn", "op") = -1 2789 * StringUtils.indexOfAny("zzabyycdxx", "zab", "aby") = 1 2790 * StringUtils.indexOfAny("zzabyycdxx", "") = 0 2791 * StringUtils.indexOfAny("", "") = 0 2792 * StringUtils.indexOfAny("", "a") = -1 2793 * </pre> 2794 * 2795 * @param str The CharSequence to check, may be null. 2796 * @param searchStrs The CharSequences to search for, may be null. 2797 * @return The first index of any of the searchStrs in str, -1 if no match. 2798 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2799 */ 2800 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2801 if (str == null || searchStrs == null) { 2802 return INDEX_NOT_FOUND; 2803 } 2804 // String's can't have a MAX_VALUEth index. 2805 int ret = Integer.MAX_VALUE; 2806 int tmp; 2807 for (final CharSequence search : searchStrs) { 2808 if (search == null) { 2809 continue; 2810 } 2811 tmp = CharSequenceUtils.indexOf(str, search, 0); 2812 if (tmp == INDEX_NOT_FOUND) { 2813 continue; 2814 } 2815 if (tmp < ret) { 2816 ret = tmp; 2817 } 2818 } 2819 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2820 } 2821 2822 /** 2823 * Search a CharSequence to find the first index of any character in the given set of characters. 2824 * 2825 * <p> 2826 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2827 * </p> 2828 * <p> 2829 * The following is the same as {@code indexOfAny(cs, 0, searchChars)}. 2830 * </p> 2831 * <pre> 2832 * StringUtils.indexOfAny(null, 0, *) = -1 2833 * StringUtils.indexOfAny("", 0, *) = -1 2834 * StringUtils.indexOfAny(*, 0, null) = -1 2835 * StringUtils.indexOfAny(*, 0, []) = -1 2836 * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0 2837 * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3 2838 * StringUtils.indexOfAny("aba", 0, ['z']) = -1 2839 * </pre> 2840 * 2841 * @param cs The CharSequence to check, may be null. 2842 * @param csStart Start searching the input {@code cs} at this index. 2843 * @param searchChars The chars to search for, may be null. 2844 * @return The index of any of the chars, -1 if no match or null input. 2845 * @since 2.0 2846 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2847 */ 2848 public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) { 2849 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2850 return INDEX_NOT_FOUND; 2851 } 2852 final int csLen = cs.length(); 2853 final int csLast = csLen - 1; 2854 final int searchLen = searchChars.length; 2855 final int searchLast = searchLen - 1; 2856 for (int i = Math.max(csStart, 0); i < csLen; i++) { 2857 final char ch = cs.charAt(i); 2858 for (int j = 0; j < searchLen; j++) { 2859 if (searchChars[j] == ch) { 2860 if (Character.isHighSurrogate(ch) 2861 ? j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1) 2862 : j == 0 || !Character.isLowSurrogate(ch) || !Character.isHighSurrogate(searchChars[j - 1]) || i > 0 && searchChars[j - 1] == cs.charAt(i - 1)) { 2863 return i; 2864 } 2865 } 2866 } 2867 } 2868 return INDEX_NOT_FOUND; 2869 } 2870 2871 /** 2872 * Search a CharSequence to find the first index of any character in the given set of characters. 2873 * 2874 * <p> 2875 * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}. 2876 * </p> 2877 * 2878 * <pre> 2879 * StringUtils.indexOfAny(null, *) = -1 2880 * StringUtils.indexOfAny("", *) = -1 2881 * StringUtils.indexOfAny(*, null) = -1 2882 * StringUtils.indexOfAny(*, "") = -1 2883 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2884 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2885 * StringUtils.indexOfAny("aba", "z") = -1 2886 * </pre> 2887 * 2888 * @param cs The CharSequence to check, may be null. 2889 * @param searchChars The chars to search for, may be null. 2890 * @return The index of any of the chars, -1 if no match or null input. 2891 * @since 2.0 2892 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2893 */ 2894 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2895 if (isEmpty(cs) || isEmpty(searchChars)) { 2896 return INDEX_NOT_FOUND; 2897 } 2898 return indexOfAny(cs, searchChars.toCharArray()); 2899 } 2900 2901 /** 2902 * Searches a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in cs such that 2903 * (cs.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2904 * 2905 * <p> 2906 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2907 * </p> 2908 * 2909 * <pre> 2910 * StringUtils.indexOfAnyBut(null, *) = -1 2911 * StringUtils.indexOfAnyBut("", *) = -1 2912 * StringUtils.indexOfAnyBut(*, null) = -1 2913 * StringUtils.indexOfAnyBut(*, []) = -1 2914 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2915 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2916 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2917 * </pre> 2918 * 2919 * @param cs The CharSequence to check, may be null. 2920 * @param searchChars The chars to search for, may be null. 2921 * @return The index of any of the chars, -1 if no match or null input. 2922 * @since 2.0 2923 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2924 */ 2925 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2926 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2927 return INDEX_NOT_FOUND; 2928 } 2929 return indexOfAnyBut(cs, CharBuffer.wrap(searchChars)); 2930 } 2931 2932 /** 2933 * Search a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in seq such that 2934 * (seq.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2935 * 2936 * <p> 2937 * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}. 2938 * </p> 2939 * 2940 * <pre> 2941 * StringUtils.indexOfAnyBut(null, *) = -1 2942 * StringUtils.indexOfAnyBut("", *) = -1 2943 * StringUtils.indexOfAnyBut(*, null) = -1 2944 * StringUtils.indexOfAnyBut(*, "") = -1 2945 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2946 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2947 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2948 * </pre> 2949 * 2950 * @param seq The CharSequence to check, may be null. 2951 * @param searchChars The chars to search for, may be null. 2952 * @return The index of any of the chars, -1 if no match or null input. 2953 * @since 2.0 2954 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2955 */ 2956 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2957 if (isEmpty(seq) || isEmpty(searchChars)) { 2958 return INDEX_NOT_FOUND; 2959 } 2960 final Set<Integer> searchSetCodePoints = searchChars.codePoints() 2961 .boxed().collect(Collectors.toSet()); 2962 // advance character index from one interpreted codepoint to the next 2963 for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) { 2964 final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx); 2965 if (!searchSetCodePoints.contains(curSeqCodePoint)) { 2966 return curSeqCharIdx; 2967 } 2968 curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates 2969 } 2970 return INDEX_NOT_FOUND; 2971 } 2972 2973 /** 2974 * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ. 2975 * 2976 * <p> 2977 * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7} 2978 * </p> 2979 * 2980 * <pre> 2981 * StringUtils.indexOfDifference(null) = -1 2982 * StringUtils.indexOfDifference(new String[] {}) = -1 2983 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2984 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2985 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2986 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2987 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2988 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2989 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2990 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2991 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2992 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2993 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2994 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2995 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2996 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2997 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2998 * </pre> 2999 * 3000 * @param css array of CharSequences, entries may be null. 3001 * @return The index where the strings begin to differ; -1 if they are all equal. 3002 * @since 2.4 3003 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 3004 */ 3005 public static int indexOfDifference(final CharSequence... css) { 3006 if (ArrayUtils.getLength(css) <= 1) { 3007 return INDEX_NOT_FOUND; 3008 } 3009 boolean anyStringNull = false; 3010 boolean allStringsNull = true; 3011 final int arrayLen = css.length; 3012 int shortestStrLen = Integer.MAX_VALUE; 3013 int longestStrLen = 0; 3014 // find the min and max string lengths; this avoids checking to make 3015 // sure we are not exceeding the length of the string each time through 3016 // the bottom loop. 3017 for (final CharSequence cs : css) { 3018 if (cs == null) { 3019 anyStringNull = true; 3020 shortestStrLen = 0; 3021 } else { 3022 allStringsNull = false; 3023 shortestStrLen = Math.min(cs.length(), shortestStrLen); 3024 longestStrLen = Math.max(cs.length(), longestStrLen); 3025 } 3026 } 3027 // handle lists containing all nulls or all empty strings 3028 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 3029 return INDEX_NOT_FOUND; 3030 } 3031 // handle lists containing some nulls or some empty strings 3032 if (shortestStrLen == 0) { 3033 return 0; 3034 } 3035 // find the position with the first difference across all strings 3036 int firstDiff = -1; 3037 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 3038 final char comparisonChar = css[0].charAt(stringPos); 3039 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 3040 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 3041 firstDiff = stringPos; 3042 break; 3043 } 3044 } 3045 if (firstDiff != -1) { 3046 break; 3047 } 3048 } 3049 if (firstDiff > 0 && Character.isLowSurrogate(css[0].charAt(firstDiff)) 3050 && Character.isHighSurrogate(css[0].charAt(firstDiff - 1))) { 3051 // the difference splits a surrogate pair whose high half is common; report the start of the 3052 // pair so getCommonPrefix never slices it in half and leaves a stray high surrogate. 3053 firstDiff--; 3054 } 3055 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 3056 // we compared all of the characters up to the length of the 3057 // shortest string and didn't find a match, but the string lengths 3058 // vary, so return the length of the shortest string. 3059 return shortestStrLen; 3060 } 3061 return firstDiff; 3062 } 3063 3064 /** 3065 * Compares two CharSequences, and returns the index at which the CharSequences begin to differ. 3066 * 3067 * <p> 3068 * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7} 3069 * </p> 3070 * 3071 * <pre> 3072 * StringUtils.indexOfDifference(null, null) = -1 3073 * StringUtils.indexOfDifference("", "") = -1 3074 * StringUtils.indexOfDifference("", "abc") = 0 3075 * StringUtils.indexOfDifference("abc", "") = 0 3076 * StringUtils.indexOfDifference("abc", "abc") = -1 3077 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3078 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3079 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3080 * </pre> 3081 * 3082 * @param cs1 The first CharSequence, may be null. 3083 * @param cs2 The second CharSequence, may be null. 3084 * @return The index where cs1 and cs2 begin to differ; -1 if they are equal. 3085 * @since 2.0 3086 * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence) 3087 */ 3088 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3089 if (cs1 == cs2) { 3090 return INDEX_NOT_FOUND; 3091 } 3092 if (cs1 == null || cs2 == null) { 3093 return 0; 3094 } 3095 int i; 3096 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3097 if (cs1.charAt(i) != cs2.charAt(i)) { 3098 break; 3099 } 3100 } 3101 if (i > 0 && i < cs1.length() && i < cs2.length() && Character.isHighSurrogate(cs1.charAt(i - 1)) 3102 && (Character.isLowSurrogate(cs1.charAt(i)) || Character.isLowSurrogate(cs2.charAt(i)))) { 3103 // the difference splits a surrogate pair whose high half is common; report the start of the 3104 // pair so difference does not return a string that begins with a stray low surrogate. 3105 i--; 3106 } 3107 if (i < cs2.length() || i < cs1.length()) { 3108 return i; 3109 } 3110 return INDEX_NOT_FOUND; 3111 } 3112 3113 /** 3114 * Case insensitive find of the first index within a CharSequence. 3115 * 3116 * <p> 3117 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3118 * start position greater than the string length only matches an empty search CharSequence. 3119 * </p> 3120 * 3121 * <pre> 3122 * StringUtils.indexOfIgnoreCase(null, *) = -1 3123 * StringUtils.indexOfIgnoreCase(*, null) = -1 3124 * StringUtils.indexOfIgnoreCase("", "") = 0 3125 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3126 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3127 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3128 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3129 * </pre> 3130 * 3131 * @param str The CharSequence to check, may be null. 3132 * @param searchStr The CharSequence to find, may be null. 3133 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 3134 * @since 2.5 3135 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3136 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}. 3137 */ 3138 @Deprecated 3139 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3140 return Strings.CI.indexOf(str, searchStr); 3141 } 3142 3143 /** 3144 * Case insensitive find of the first index within a CharSequence from the specified position. 3145 * 3146 * <p> 3147 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3148 * start position greater than the string length only matches an empty search CharSequence. 3149 * </p> 3150 * 3151 * <pre> 3152 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3153 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3154 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3155 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3156 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3157 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3158 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3159 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3160 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3161 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3162 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3163 * </pre> 3164 * 3165 * @param str The CharSequence to check, may be null. 3166 * @param searchStr The CharSequence to find, may be null. 3167 * @param startPos The start position, negative treated as zero. 3168 * @return The first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 3169 * @since 2.5 3170 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3171 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}. 3172 */ 3173 @Deprecated 3174 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 3175 return Strings.CI.indexOf(str, searchStr, startPos); 3176 } 3177 3178 /** 3179 * Tests if all of the CharSequences are empty (""), null or whitespace only. 3180 * 3181 * <p> 3182 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3183 * </p> 3184 * 3185 * <pre> 3186 * StringUtils.isAllBlank(null) = true 3187 * StringUtils.isAllBlank(null, "foo") = false 3188 * StringUtils.isAllBlank(null, null) = true 3189 * StringUtils.isAllBlank("", "bar") = false 3190 * StringUtils.isAllBlank("bob", "") = false 3191 * StringUtils.isAllBlank(" bob ", null) = false 3192 * StringUtils.isAllBlank(" ", "bar") = false 3193 * StringUtils.isAllBlank("foo", "bar") = false 3194 * StringUtils.isAllBlank(new String[] {}) = true 3195 * </pre> 3196 * 3197 * @param css The CharSequences to check, may be null or empty. 3198 * @return {@code true} if all of the CharSequences are empty or null or whitespace only. 3199 * @since 3.6 3200 */ 3201 public static boolean isAllBlank(final CharSequence... css) { 3202 if (ArrayUtils.isEmpty(css)) { 3203 return true; 3204 } 3205 for (final CharSequence cs : css) { 3206 if (isNotBlank(cs)) { 3207 return false; 3208 } 3209 } 3210 return true; 3211 } 3212 3213 /** 3214 * Tests if all of the CharSequences are empty ("") or null. 3215 * 3216 * <pre> 3217 * StringUtils.isAllEmpty(null) = true 3218 * StringUtils.isAllEmpty(null, "") = true 3219 * StringUtils.isAllEmpty(new String[] {}) = true 3220 * StringUtils.isAllEmpty(null, "foo") = false 3221 * StringUtils.isAllEmpty("", "bar") = false 3222 * StringUtils.isAllEmpty("bob", "") = false 3223 * StringUtils.isAllEmpty(" bob ", null) = false 3224 * StringUtils.isAllEmpty(" ", "bar") = false 3225 * StringUtils.isAllEmpty("foo", "bar") = false 3226 * </pre> 3227 * 3228 * @param css The CharSequences to check, may be null or empty. 3229 * @return {@code true} if all of the CharSequences are empty or null. 3230 * @since 3.6 3231 */ 3232 public static boolean isAllEmpty(final CharSequence... css) { 3233 if (ArrayUtils.isEmpty(css)) { 3234 return true; 3235 } 3236 for (final CharSequence cs : css) { 3237 if (isNotEmpty(cs)) { 3238 return false; 3239 } 3240 } 3241 return true; 3242 } 3243 3244 /** 3245 * Tests if the CharSequence contains only lowercase characters. 3246 * 3247 * <p> 3248 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3249 * </p> 3250 * 3251 * <pre> 3252 * StringUtils.isAllLowerCase(null) = false 3253 * StringUtils.isAllLowerCase("") = false 3254 * StringUtils.isAllLowerCase(" ") = false 3255 * StringUtils.isAllLowerCase("abc") = true 3256 * StringUtils.isAllLowerCase("abC") = false 3257 * StringUtils.isAllLowerCase("ab c") = false 3258 * StringUtils.isAllLowerCase("ab1c") = false 3259 * StringUtils.isAllLowerCase("ab/c") = false 3260 * </pre> 3261 * 3262 * @param cs The CharSequence to check, may be null. 3263 * @return {@code true} if only contains lowercase characters, and is non-null. 3264 * @since 2.5 3265 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3266 */ 3267 public static boolean isAllLowerCase(final CharSequence cs) { 3268 if (isEmpty(cs)) { 3269 return false; 3270 } 3271 final int sz = cs.length(); 3272 for (int i = 0; i < sz;) { 3273 final int codePoint = Character.codePointAt(cs, i); 3274 if (!Character.isLowerCase(codePoint)) { 3275 return false; 3276 } 3277 i += Character.charCount(codePoint); 3278 } 3279 return true; 3280 } 3281 3282 /** 3283 * Tests if the CharSequence contains only uppercase characters. 3284 * 3285 * <p> 3286 * {@code null} will return {@code false}. 3287 * An empty String (length()=0) will return {@code false}. 3288 * </p> 3289 * 3290 * <pre> 3291 * StringUtils.isAllUpperCase(null) = false 3292 * StringUtils.isAllUpperCase("") = false 3293 * StringUtils.isAllUpperCase(" ") = false 3294 * StringUtils.isAllUpperCase("ABC") = true 3295 * StringUtils.isAllUpperCase("aBC") = false 3296 * StringUtils.isAllUpperCase("A C") = false 3297 * StringUtils.isAllUpperCase("A1C") = false 3298 * StringUtils.isAllUpperCase("A/C") = false 3299 * </pre> 3300 * 3301 * @param cs The CharSequence to check, may be null. 3302 * @return {@code true} if only contains uppercase characters, and is non-null. 3303 * @since 2.5 3304 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3305 */ 3306 public static boolean isAllUpperCase(final CharSequence cs) { 3307 if (isEmpty(cs)) { 3308 return false; 3309 } 3310 final int sz = cs.length(); 3311 for (int i = 0; i < sz;) { 3312 final int codePoint = Character.codePointAt(cs, i); 3313 if (!Character.isUpperCase(codePoint)) { 3314 return false; 3315 } 3316 i += Character.charCount(codePoint); 3317 } 3318 return true; 3319 } 3320 3321 /** 3322 * Tests if the CharSequence contains only Unicode letters. 3323 * 3324 * <p> 3325 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3326 * </p> 3327 * 3328 * <pre> 3329 * StringUtils.isAlpha(null) = false 3330 * StringUtils.isAlpha("") = false 3331 * StringUtils.isAlpha(" ") = false 3332 * StringUtils.isAlpha("abc") = true 3333 * StringUtils.isAlpha("ab2c") = false 3334 * StringUtils.isAlpha("ab-c") = false 3335 * </pre> 3336 * 3337 * @param cs The CharSequence to check, may be null. 3338 * @return {@code true} if only contains letters, and is non-null. 3339 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3340 * @since 3.0 Changed "" to return false and not true 3341 */ 3342 public static boolean isAlpha(final CharSequence cs) { 3343 if (isEmpty(cs)) { 3344 return false; 3345 } 3346 final int sz = cs.length(); 3347 for (int i = 0; i < sz;) { 3348 final int codePoint = Character.codePointAt(cs, i); 3349 if (!Character.isLetter(codePoint)) { 3350 return false; 3351 } 3352 i += Character.charCount(codePoint); 3353 } 3354 return true; 3355 } 3356 3357 /** 3358 * Tests if the CharSequence contains only Unicode letters or digits. 3359 * 3360 * <p> 3361 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3362 * </p> 3363 * 3364 * <pre> 3365 * StringUtils.isAlphanumeric(null) = false 3366 * StringUtils.isAlphanumeric("") = false 3367 * StringUtils.isAlphanumeric(" ") = false 3368 * StringUtils.isAlphanumeric("abc") = true 3369 * StringUtils.isAlphanumeric("ab c") = false 3370 * StringUtils.isAlphanumeric("ab2c") = true 3371 * StringUtils.isAlphanumeric("ab-c") = false 3372 * </pre> 3373 * 3374 * @param cs The CharSequence to check, may be null. 3375 * @return {@code true} if only contains letters or digits, and is non-null. 3376 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3377 * @since 3.0 Changed "" to return false and not true 3378 */ 3379 public static boolean isAlphanumeric(final CharSequence cs) { 3380 if (isEmpty(cs)) { 3381 return false; 3382 } 3383 final int sz = cs.length(); 3384 for (int i = 0; i < sz;) { 3385 final int codePoint = Character.codePointAt(cs, i); 3386 if (!Character.isLetterOrDigit(codePoint)) { 3387 return false; 3388 } 3389 i += Character.charCount(codePoint); 3390 } 3391 return true; 3392 } 3393 3394 /** 3395 * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}). 3396 * 3397 * <p> 3398 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3399 * </p> 3400 * 3401 * <pre> 3402 * StringUtils.isAlphanumericSpace(null) = false 3403 * StringUtils.isAlphanumericSpace("") = true 3404 * StringUtils.isAlphanumericSpace(" ") = true 3405 * StringUtils.isAlphanumericSpace("abc") = true 3406 * StringUtils.isAlphanumericSpace("ab c") = true 3407 * StringUtils.isAlphanumericSpace("ab2c") = true 3408 * StringUtils.isAlphanumericSpace("ab-c") = false 3409 * </pre> 3410 * 3411 * @param cs The CharSequence to check, may be null. 3412 * @return {@code true} if only contains letters, digits or space, and is non-null. 3413 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3414 */ 3415 public static boolean isAlphanumericSpace(final CharSequence cs) { 3416 if (cs == null) { 3417 return false; 3418 } 3419 final int sz = cs.length(); 3420 for (int i = 0; i < sz;) { 3421 final int codePoint = Character.codePointAt(cs, i); 3422 if (codePoint != ' ' && !Character.isLetterOrDigit(codePoint)) { 3423 return false; 3424 } 3425 i += Character.charCount(codePoint); 3426 } 3427 return true; 3428 } 3429 3430 /** 3431 * Tests if the CharSequence contains only Unicode letters and space (' '). 3432 * 3433 * <p> 3434 * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}. 3435 * </p> 3436 * 3437 * <pre> 3438 * StringUtils.isAlphaSpace(null) = false 3439 * StringUtils.isAlphaSpace("") = true 3440 * StringUtils.isAlphaSpace(" ") = true 3441 * StringUtils.isAlphaSpace("abc") = true 3442 * StringUtils.isAlphaSpace("ab c") = true 3443 * StringUtils.isAlphaSpace("ab2c") = false 3444 * StringUtils.isAlphaSpace("ab-c") = false 3445 * </pre> 3446 * 3447 * @param cs The CharSequence to check, may be null. 3448 * @return {@code true} if only contains letters and space, and is non-null. 3449 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3450 */ 3451 public static boolean isAlphaSpace(final CharSequence cs) { 3452 if (cs == null) { 3453 return false; 3454 } 3455 final int sz = cs.length(); 3456 for (int i = 0; i < sz;) { 3457 final int codePoint = Character.codePointAt(cs, i); 3458 if (codePoint != ' ' && !Character.isLetter(codePoint)) { 3459 return false; 3460 } 3461 i += Character.charCount(codePoint); 3462 } 3463 return true; 3464 } 3465 3466 /** 3467 * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3468 * 3469 * <p> 3470 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3471 * </p> 3472 * 3473 * <pre> 3474 * StringUtils.isAnyBlank((String) null) = true 3475 * StringUtils.isAnyBlank((String[]) null) = false 3476 * StringUtils.isAnyBlank(null, "foo") = true 3477 * StringUtils.isAnyBlank(null, null) = true 3478 * StringUtils.isAnyBlank("", "bar") = true 3479 * StringUtils.isAnyBlank("bob", "") = true 3480 * StringUtils.isAnyBlank(" bob ", null) = true 3481 * StringUtils.isAnyBlank(" ", "bar") = true 3482 * StringUtils.isAnyBlank(new String[] {}) = false 3483 * StringUtils.isAnyBlank(new String[]{""}) = true 3484 * StringUtils.isAnyBlank("foo", "bar") = false 3485 * </pre> 3486 * 3487 * @param css The CharSequences to check, may be null or empty. 3488 * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3489 * @see #isBlank(CharSequence) 3490 * @since 3.2 3491 */ 3492 public static boolean isAnyBlank(final CharSequence... css) { 3493 if (ArrayUtils.isEmpty(css)) { 3494 return false; 3495 } 3496 for (final CharSequence cs : css) { 3497 if (isBlank(cs)) { 3498 return true; 3499 } 3500 } 3501 return false; 3502 } 3503 3504 /** 3505 * Tests if any of the CharSequences are empty ("") or null. 3506 * 3507 * <pre> 3508 * StringUtils.isAnyEmpty((String) null) = true 3509 * StringUtils.isAnyEmpty((String[]) null) = false 3510 * StringUtils.isAnyEmpty(null, "foo") = true 3511 * StringUtils.isAnyEmpty("", "bar") = true 3512 * StringUtils.isAnyEmpty("bob", "") = true 3513 * StringUtils.isAnyEmpty(" bob ", null) = true 3514 * StringUtils.isAnyEmpty(" ", "bar") = false 3515 * StringUtils.isAnyEmpty("foo", "bar") = false 3516 * StringUtils.isAnyEmpty(new String[]{}) = false 3517 * StringUtils.isAnyEmpty(new String[]{""}) = true 3518 * </pre> 3519 * 3520 * @param css The CharSequences to check, may be null or empty. 3521 * @return {@code true} if any of the CharSequences are empty or null. 3522 * @since 3.2 3523 */ 3524 public static boolean isAnyEmpty(final CharSequence... css) { 3525 if (ArrayUtils.isEmpty(css)) { 3526 return false; 3527 } 3528 for (final CharSequence cs : css) { 3529 if (isEmpty(cs)) { 3530 return true; 3531 } 3532 } 3533 return false; 3534 } 3535 3536 /** 3537 * Tests if the CharSequence contains only ASCII printable characters. 3538 * 3539 * <p> 3540 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3541 * </p> 3542 * 3543 * <pre> 3544 * StringUtils.isAsciiPrintable(null) = false 3545 * StringUtils.isAsciiPrintable("") = true 3546 * StringUtils.isAsciiPrintable(" ") = true 3547 * StringUtils.isAsciiPrintable("Ceki") = true 3548 * StringUtils.isAsciiPrintable("ab2c") = true 3549 * StringUtils.isAsciiPrintable("!ab-c~") = true 3550 * StringUtils.isAsciiPrintable("\u0020") = true 3551 * StringUtils.isAsciiPrintable("\u0021") = true 3552 * StringUtils.isAsciiPrintable("\u007e") = true 3553 * StringUtils.isAsciiPrintable("\u007f") = false 3554 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3555 * </pre> 3556 * 3557 * @param cs The CharSequence to check, may be null. 3558 * @return {@code true} if every character is in the range 32 through 126. 3559 * @since 2.1 3560 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3561 */ 3562 public static boolean isAsciiPrintable(final CharSequence cs) { 3563 if (cs == null) { 3564 return false; 3565 } 3566 final int sz = cs.length(); 3567 for (int i = 0; i < sz; i++) { 3568 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3569 return false; 3570 } 3571 } 3572 return true; 3573 } 3574 3575 /** 3576 * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}. 3577 * 3578 * <pre> 3579 * StringUtils.isBlank(null) = true 3580 * StringUtils.isBlank("") = true 3581 * StringUtils.isBlank(" ") = true 3582 * StringUtils.isBlank("bob") = false 3583 * StringUtils.isBlank(" bob ") = false 3584 * </pre> 3585 * 3586 * @param cs The CharSequence to check, may be null. 3587 * @return {@code true} if the CharSequence is null, empty or whitespace only. 3588 * @since 2.0 3589 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3590 */ 3591 public static boolean isBlank(final CharSequence cs) { 3592 final int strLen = length(cs); 3593 for (int i = 0; i < strLen; i++) { 3594 if (!Character.isWhitespace(cs.charAt(i))) { 3595 return false; 3596 } 3597 } 3598 return true; 3599 } 3600 3601 /** 3602 * Tests if a CharSequence is empty ("") or null. 3603 * 3604 * <pre> 3605 * StringUtils.isEmpty(null) = true 3606 * StringUtils.isEmpty("") = true 3607 * StringUtils.isEmpty(" ") = false 3608 * StringUtils.isEmpty("bob") = false 3609 * StringUtils.isEmpty(" bob ") = false 3610 * </pre> 3611 * 3612 * <p> 3613 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank(). 3614 * </p> 3615 * 3616 * @param cs The CharSequence to check, may be null. 3617 * @return {@code true} if the CharSequence is empty or null. 3618 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3619 */ 3620 public static boolean isEmpty(final CharSequence cs) { 3621 return cs == null || cs.length() == 0; 3622 } 3623 3624 /** 3625 * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3626 * 3627 * <p> 3628 * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}. 3629 * </p> 3630 * 3631 * <pre> 3632 * StringUtils.isMixedCase(null) = false 3633 * StringUtils.isMixedCase("") = false 3634 * StringUtils.isMixedCase(" ") = false 3635 * StringUtils.isMixedCase("ABC") = false 3636 * StringUtils.isMixedCase("abc") = false 3637 * StringUtils.isMixedCase("aBc") = true 3638 * StringUtils.isMixedCase("A c") = true 3639 * StringUtils.isMixedCase("A1c") = true 3640 * StringUtils.isMixedCase("a/C") = true 3641 * StringUtils.isMixedCase("aC\t") = true 3642 * </pre> 3643 * 3644 * @param cs The CharSequence to check, may be null. 3645 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters. 3646 * @since 3.5 3647 */ 3648 public static boolean isMixedCase(final CharSequence cs) { 3649 if (isEmpty(cs) || cs.length() == 1) { 3650 return false; 3651 } 3652 boolean containsUppercase = false; 3653 boolean containsLowercase = false; 3654 final int sz = cs.length(); 3655 for (int i = 0; i < sz;) { 3656 final int codePoint = Character.codePointAt(cs, i); 3657 if (Character.isUpperCase(codePoint)) { 3658 containsUppercase = true; 3659 } else if (Character.isLowerCase(codePoint)) { 3660 containsLowercase = true; 3661 } 3662 if (containsUppercase && containsLowercase) { 3663 return true; 3664 } 3665 i += Character.charCount(codePoint); 3666 } 3667 return false; 3668 } 3669 3670 /** 3671 * Tests if none of the CharSequences are empty (""), null or whitespace only. 3672 * 3673 * <p> 3674 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3675 * </p> 3676 * 3677 * <pre> 3678 * StringUtils.isNoneBlank((String) null) = false 3679 * StringUtils.isNoneBlank((String[]) null) = true 3680 * StringUtils.isNoneBlank(null, "foo") = false 3681 * StringUtils.isNoneBlank(null, null) = false 3682 * StringUtils.isNoneBlank("", "bar") = false 3683 * StringUtils.isNoneBlank("bob", "") = false 3684 * StringUtils.isNoneBlank(" bob ", null) = false 3685 * StringUtils.isNoneBlank(" ", "bar") = false 3686 * StringUtils.isNoneBlank(new String[] {}) = true 3687 * StringUtils.isNoneBlank(new String[]{""}) = false 3688 * StringUtils.isNoneBlank("foo", "bar") = true 3689 * </pre> 3690 * 3691 * @param css The CharSequences to check, may be null or empty. 3692 * @return {@code true} if none of the CharSequences are empty or null or whitespace only. 3693 * @since 3.2 3694 */ 3695 public static boolean isNoneBlank(final CharSequence... css) { 3696 return !isAnyBlank(css); 3697 } 3698 3699 /** 3700 * Tests if none of the CharSequences are empty ("") or null. 3701 * 3702 * <pre> 3703 * StringUtils.isNoneEmpty((String) null) = false 3704 * StringUtils.isNoneEmpty((String[]) null) = true 3705 * StringUtils.isNoneEmpty(null, "foo") = false 3706 * StringUtils.isNoneEmpty("", "bar") = false 3707 * StringUtils.isNoneEmpty("bob", "") = false 3708 * StringUtils.isNoneEmpty(" bob ", null) = false 3709 * StringUtils.isNoneEmpty(new String[] {}) = true 3710 * StringUtils.isNoneEmpty(new String[]{""}) = false 3711 * StringUtils.isNoneEmpty(" ", "bar") = true 3712 * StringUtils.isNoneEmpty("foo", "bar") = true 3713 * </pre> 3714 * 3715 * @param css The CharSequences to check, may be null or empty. 3716 * @return {@code true} if none of the CharSequences are empty or null. 3717 * @since 3.2 3718 */ 3719 public static boolean isNoneEmpty(final CharSequence... css) { 3720 return !isAnyEmpty(css); 3721 } 3722 3723 /** 3724 * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3725 * 3726 * <p> 3727 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3728 * </p> 3729 * 3730 * <pre> 3731 * StringUtils.isNotBlank(null) = false 3732 * StringUtils.isNotBlank("") = false 3733 * StringUtils.isNotBlank(" ") = false 3734 * StringUtils.isNotBlank("bob") = true 3735 * StringUtils.isNotBlank(" bob ") = true 3736 * </pre> 3737 * 3738 * @param cs The CharSequence to check, may be null. 3739 * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3740 * @see #isBlank(CharSequence) 3741 * @since 2.0 3742 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3743 */ 3744 public static boolean isNotBlank(final CharSequence cs) { 3745 return !isBlank(cs); 3746 } 3747 3748 /** 3749 * Tests if a CharSequence is not empty ("") and not null. 3750 * 3751 * <pre> 3752 * StringUtils.isNotEmpty(null) = false 3753 * StringUtils.isNotEmpty("") = false 3754 * StringUtils.isNotEmpty(" ") = true 3755 * StringUtils.isNotEmpty("bob") = true 3756 * StringUtils.isNotEmpty(" bob ") = true 3757 * </pre> 3758 * 3759 * @param cs The CharSequence to check, may be null. 3760 * @return {@code true} if the CharSequence is not empty and not null. 3761 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3762 */ 3763 public static boolean isNotEmpty(final CharSequence cs) { 3764 return !isEmpty(cs); 3765 } 3766 3767 /** 3768 * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false. 3769 * 3770 * <p> 3771 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3772 * </p> 3773 * 3774 * <p> 3775 * Note that the method does not allow for a leading sign, either positive or negative. Also, if a String passes the numeric test, it may still generate a 3776 * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively. 3777 * </p> 3778 * 3779 * <pre> 3780 * StringUtils.isNumeric(null) = false 3781 * StringUtils.isNumeric("") = false 3782 * StringUtils.isNumeric(" ") = false 3783 * StringUtils.isNumeric("123") = true 3784 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3785 * StringUtils.isNumeric("12 3") = false 3786 * StringUtils.isNumeric("ab2c") = false 3787 * StringUtils.isNumeric("12-3") = false 3788 * StringUtils.isNumeric("12.3") = false 3789 * StringUtils.isNumeric("-123") = false 3790 * StringUtils.isNumeric("+123") = false 3791 * </pre> 3792 * 3793 * @param cs The CharSequence to check, may be null. 3794 * @return {@code true} if only contains digits, and is non-null. 3795 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3796 * @since 3.0 Changed "" to return false and not true 3797 */ 3798 public static boolean isNumeric(final CharSequence cs) { 3799 if (isEmpty(cs)) { 3800 return false; 3801 } 3802 final int sz = cs.length(); 3803 for (int i = 0; i < sz;) { 3804 final int codePoint = Character.codePointAt(cs, i); 3805 if (!Character.isDigit(codePoint)) { 3806 return false; 3807 } 3808 i += Character.charCount(codePoint); 3809 } 3810 return true; 3811 } 3812 3813 /** 3814 * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false. 3815 * 3816 * <p> 3817 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3818 * </p> 3819 * 3820 * <pre> 3821 * StringUtils.isNumericSpace(null) = false 3822 * StringUtils.isNumericSpace("") = true 3823 * StringUtils.isNumericSpace(" ") = true 3824 * StringUtils.isNumericSpace("123") = true 3825 * StringUtils.isNumericSpace("12 3") = true 3826 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3827 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3828 * StringUtils.isNumericSpace("ab2c") = false 3829 * StringUtils.isNumericSpace("12-3") = false 3830 * StringUtils.isNumericSpace("12.3") = false 3831 * </pre> 3832 * 3833 * @param cs The CharSequence to check, may be null. 3834 * @return {@code true} if only contains digits or space, and is non-null. 3835 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3836 */ 3837 public static boolean isNumericSpace(final CharSequence cs) { 3838 if (cs == null) { 3839 return false; 3840 } 3841 final int sz = cs.length(); 3842 for (int i = 0; i < sz;) { 3843 final int codePoint = Character.codePointAt(cs, i); 3844 if (codePoint != ' ' && !Character.isDigit(codePoint)) { 3845 return false; 3846 } 3847 i += Character.charCount(codePoint); 3848 } 3849 return true; 3850 } 3851 3852 /** 3853 * Tests if the CharSequence contains only whitespace. 3854 * 3855 * <p> 3856 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3857 * </p> 3858 * 3859 * <p> 3860 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3861 * </p> 3862 * 3863 * <pre> 3864 * StringUtils.isWhitespace(null) = false 3865 * StringUtils.isWhitespace("") = true 3866 * StringUtils.isWhitespace(" ") = true 3867 * StringUtils.isWhitespace("abc") = false 3868 * StringUtils.isWhitespace("ab2c") = false 3869 * StringUtils.isWhitespace("ab-c") = false 3870 * </pre> 3871 * 3872 * @param cs The CharSequence to check, may be null. 3873 * @return {@code true} if only contains whitespace, and is non-null. 3874 * @since 2.0 3875 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3876 */ 3877 public static boolean isWhitespace(final CharSequence cs) { 3878 if (cs == null) { 3879 return false; 3880 } 3881 final int sz = cs.length(); 3882 for (int i = 0; i < sz; i++) { 3883 if (!Character.isWhitespace(cs.charAt(i))) { 3884 return false; 3885 } 3886 } 3887 return true; 3888 } 3889 3890 /** 3891 * Joins the elements of the provided array into a single String containing the provided list of elements. 3892 * 3893 * <p> 3894 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 3895 * </p> 3896 * 3897 * <pre> 3898 * StringUtils.join(null, *) = null 3899 * StringUtils.join([], *) = "" 3900 * StringUtils.join([null], *) = "" 3901 * StringUtils.join([false, false], ';') = "false;false" 3902 * </pre> 3903 * 3904 * @param array The array of values to join together, may be null. 3905 * @param delimiter The separator character to use. 3906 * @return The joined String, {@code null} if null array input. 3907 * @since 3.12.0 3908 */ 3909 public static String join(final boolean[] array, final char delimiter) { 3910 if (array == null) { 3911 return null; 3912 } 3913 return join(array, delimiter, 0, array.length); 3914 } 3915 3916 /** 3917 * Joins the elements of the provided array into a single String containing the provided list of elements. 3918 * 3919 * <p> 3920 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3921 * by empty strings. 3922 * </p> 3923 * 3924 * <pre> 3925 * StringUtils.join(null, *) = null 3926 * StringUtils.join([], *) = "" 3927 * StringUtils.join([null], *) = "" 3928 * StringUtils.join([true, false, true], ';') = "true;false;true" 3929 * </pre> 3930 * 3931 * @param array 3932 * the array of values to join together, may be null. 3933 * @param delimiter 3934 * the separator character to use. 3935 * @param startIndex 3936 * the first index to start joining from. It is an error to pass in a start index past the end of the 3937 * array. 3938 * @param endIndex 3939 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3940 * the array. 3941 * @return The joined String, {@code null} if null array input. 3942 * @since 3.12.0 3943 */ 3944 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3945 // See StringUtilsJoinBenchmark 3946 if (array == null) { 3947 return null; 3948 } 3949 checkFromToIndex(startIndex, endIndex, array.length); 3950 final int count = endIndex - startIndex; 3951 if (count <= 0) { 3952 return EMPTY; 3953 } 3954 final byte maxElementChars = 5; // "false" 3955 final StringBuilder stringBuilder = capacity(count, maxElementChars); 3956 stringBuilder.append(array[startIndex]); 3957 for (int i = startIndex + 1; i < endIndex; i++) { 3958 stringBuilder.append(delimiter).append(array[i]); 3959 } 3960 return stringBuilder.toString(); 3961 } 3962 3963 /** 3964 * Joins the elements of the provided array into a single String containing the provided list of elements. 3965 * 3966 * <p> 3967 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3968 * by empty strings. 3969 * </p> 3970 * 3971 * <pre> 3972 * StringUtils.join(null, *) = null 3973 * StringUtils.join([], *) = "" 3974 * StringUtils.join([null], *) = "" 3975 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3976 * StringUtils.join([1, 2, 3], null) = "123" 3977 * </pre> 3978 * 3979 * @param array 3980 * the array of values to join together, may be null. 3981 * @param delimiter 3982 * the separator character to use. 3983 * @return The joined String, {@code null} if null array input. 3984 * @since 3.2 3985 */ 3986 public static String join(final byte[] array, final char delimiter) { 3987 if (array == null) { 3988 return null; 3989 } 3990 return join(array, delimiter, 0, array.length); 3991 } 3992 3993 /** 3994 * Joins the elements of the provided array into a single String containing the provided list of elements. 3995 * 3996 * <p> 3997 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3998 * by empty strings. 3999 * </p> 4000 * 4001 * <pre> 4002 * StringUtils.join(null, *) = null 4003 * StringUtils.join([], *) = "" 4004 * StringUtils.join([null], *) = "" 4005 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4006 * StringUtils.join([1, 2, 3], null) = "123" 4007 * </pre> 4008 * 4009 * @param array 4010 * the array of values to join together, may be null. 4011 * @param delimiter 4012 * the separator character to use. 4013 * @param startIndex 4014 * the first index to start joining from. It is an error to pass in a start index past the end of the 4015 * array. 4016 * @param endIndex 4017 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4018 * the array. 4019 * @return The joined String, {@code null} if null array input. 4020 * @since 3.2 4021 */ 4022 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 4023 // See StringUtilsJoinBenchmark 4024 if (array == null) { 4025 return null; 4026 } 4027 checkFromToIndex(startIndex, endIndex, array.length); 4028 final int count = endIndex - startIndex; 4029 if (count <= 0) { 4030 return EMPTY; 4031 } 4032 final byte maxElementChars = 4; // "-128" 4033 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4034 stringBuilder.append(array[startIndex]); 4035 for (int i = startIndex + 1; i < endIndex; i++) { 4036 stringBuilder.append(delimiter).append(array[i]); 4037 } 4038 return stringBuilder.toString(); 4039 } 4040 4041 /** 4042 * Joins the elements of the provided array into a single String containing the provided list of elements. 4043 * 4044 * <p> 4045 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4046 * by empty strings. 4047 * </p> 4048 * 4049 * <pre> 4050 * StringUtils.join(null, *) = null 4051 * StringUtils.join([], *) = "" 4052 * StringUtils.join([null], *) = "" 4053 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4054 * StringUtils.join([1, 2, 3], null) = "123" 4055 * </pre> 4056 * 4057 * @param array 4058 * the array of values to join together, may be null. 4059 * @param delimiter 4060 * the separator character to use. 4061 * @return The joined String, {@code null} if null array input. 4062 * @since 3.2 4063 */ 4064 public static String join(final char[] array, final char delimiter) { 4065 if (array == null) { 4066 return null; 4067 } 4068 return join(array, delimiter, 0, array.length); 4069 } 4070 4071 /** 4072 * Joins the elements of the provided array into a single String containing the provided list of elements. 4073 * 4074 * <p> 4075 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4076 * by empty strings. 4077 * </p> 4078 * 4079 * <pre> 4080 * StringUtils.join(null, *) = null 4081 * StringUtils.join([], *) = "" 4082 * StringUtils.join([null], *) = "" 4083 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4084 * StringUtils.join([1, 2, 3], null) = "123" 4085 * </pre> 4086 * 4087 * @param array 4088 * the array of values to join together, may be null. 4089 * @param delimiter 4090 * the separator character to use. 4091 * @param startIndex 4092 * the first index to start joining from. It is an error to pass in a start index past the end of the 4093 * array. 4094 * @param endIndex 4095 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4096 * the array. 4097 * @return The joined String, {@code null} if null array input. 4098 * @since 3.2 4099 */ 4100 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4101 // See StringUtilsJoinBenchmark 4102 if (array == null) { 4103 return null; 4104 } 4105 checkFromToIndex(startIndex, endIndex, array.length); 4106 final int count = endIndex - startIndex; 4107 if (count <= 0) { 4108 return EMPTY; 4109 } 4110 final byte maxElementChars = 1; 4111 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4112 stringBuilder.append(array[startIndex]); 4113 for (int i = startIndex + 1; i < endIndex; i++) { 4114 stringBuilder.append(delimiter).append(array[i]); 4115 } 4116 return stringBuilder.toString(); 4117 } 4118 4119 /** 4120 * Joins the elements of the provided array into a single String containing the provided list of elements. 4121 * 4122 * <p> 4123 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4124 * by empty strings. 4125 * </p> 4126 * 4127 * <pre> 4128 * StringUtils.join(null, *) = null 4129 * StringUtils.join([], *) = "" 4130 * StringUtils.join([null], *) = "" 4131 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4132 * StringUtils.join([1, 2, 3], null) = "123" 4133 * </pre> 4134 * 4135 * @param array 4136 * the array of values to join together, may be null. 4137 * @param delimiter 4138 * the separator character to use. 4139 * @return The joined String, {@code null} if null array input. 4140 * @since 3.2 4141 */ 4142 public static String join(final double[] array, final char delimiter) { 4143 if (array == null) { 4144 return null; 4145 } 4146 return join(array, delimiter, 0, array.length); 4147 } 4148 4149 /** 4150 * Joins the elements of the provided array into a single String containing the provided list of elements. 4151 * 4152 * <p> 4153 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4154 * by empty strings. 4155 * </p> 4156 * 4157 * <pre> 4158 * StringUtils.join(null, *) = null 4159 * StringUtils.join([], *) = "" 4160 * StringUtils.join([null], *) = "" 4161 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4162 * StringUtils.join([1, 2, 3], null) = "123" 4163 * </pre> 4164 * 4165 * @param array 4166 * the array of values to join together, may be null. 4167 * @param delimiter 4168 * the separator character to use. 4169 * @param startIndex 4170 * the first index to start joining from. It is an error to pass in a start index past the end of the 4171 * array. 4172 * @param endIndex 4173 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4174 * the array. 4175 * @return The joined String, {@code null} if null array input. 4176 * @since 3.2 4177 */ 4178 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4179 // See StringUtilsJoinBenchmark 4180 if (array == null) { 4181 return null; 4182 } 4183 checkFromToIndex(startIndex, endIndex, array.length); 4184 final int count = endIndex - startIndex; 4185 if (count <= 0) { 4186 return EMPTY; 4187 } 4188 final byte maxElementChars = 22; // "1.7976931348623157E308" 4189 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4190 stringBuilder.append(array[startIndex]); 4191 for (int i = startIndex + 1; i < endIndex; i++) { 4192 stringBuilder.append(delimiter).append(array[i]); 4193 } 4194 return stringBuilder.toString(); 4195 } 4196 4197 /** 4198 * Joins the elements of the provided array into a single String containing the provided list of elements. 4199 * 4200 * <p> 4201 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4202 * by empty strings. 4203 * </p> 4204 * 4205 * <pre> 4206 * StringUtils.join(null, *) = null 4207 * StringUtils.join([], *) = "" 4208 * StringUtils.join([null], *) = "" 4209 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4210 * StringUtils.join([1, 2, 3], null) = "123" 4211 * </pre> 4212 * 4213 * @param array 4214 * the array of values to join together, may be null. 4215 * @param delimiter 4216 * the separator character to use. 4217 * @return The joined String, {@code null} if null array input 4218 * @since 3.2 4219 */ 4220 public static String join(final float[] array, final char delimiter) { 4221 if (array == null) { 4222 return null; 4223 } 4224 return join(array, delimiter, 0, array.length); 4225 } 4226 4227 /** 4228 * Joins the elements of the provided array into a single String containing the provided list of elements. 4229 * 4230 * <p> 4231 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4232 * by empty strings. 4233 * </p> 4234 * 4235 * <pre> 4236 * StringUtils.join(null, *) = null 4237 * StringUtils.join([], *) = "" 4238 * StringUtils.join([null], *) = "" 4239 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4240 * StringUtils.join([1, 2, 3], null) = "123" 4241 * </pre> 4242 * 4243 * @param array 4244 * the array of values to join together, may be null. 4245 * @param delimiter 4246 * the separator character to use. 4247 * @param startIndex 4248 * the first index to start joining from. It is an error to pass in a start index past the end of the 4249 * array. 4250 * @param endIndex 4251 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4252 * the array. 4253 * @return The joined String, {@code null} if null array input. 4254 * @since 3.2 4255 */ 4256 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4257 // See StringUtilsJoinBenchmark 4258 if (array == null) { 4259 return null; 4260 } 4261 checkFromToIndex(startIndex, endIndex, array.length); 4262 final int count = endIndex - startIndex; 4263 if (count <= 0) { 4264 return EMPTY; 4265 } 4266 final byte maxElementChars = 12; // "3.4028235E38" 4267 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4268 stringBuilder.append(array[startIndex]); 4269 for (int i = startIndex + 1; i < endIndex; i++) { 4270 stringBuilder.append(delimiter).append(array[i]); 4271 } 4272 return stringBuilder.toString(); 4273 } 4274 4275 /** 4276 * Joins the elements of the provided array into a single String containing the provided list of elements. 4277 * 4278 * <p> 4279 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4280 * by empty strings. 4281 * </p> 4282 * 4283 * <pre> 4284 * StringUtils.join(null, *) = null 4285 * StringUtils.join([], *) = "" 4286 * StringUtils.join([null], *) = "" 4287 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4288 * StringUtils.join([1, 2, 3], null) = "123" 4289 * </pre> 4290 * 4291 * @param array 4292 * the array of values to join together, may be null. 4293 * @param separator 4294 * the separator character to use. 4295 * @return The joined String, {@code null} if null array input. 4296 * @since 3.2 4297 */ 4298 public static String join(final int[] array, final char separator) { 4299 if (array == null) { 4300 return null; 4301 } 4302 return join(array, separator, 0, array.length); 4303 } 4304 4305 /** 4306 * Joins the elements of the provided array into a single String containing the provided list of elements. 4307 * 4308 * <p> 4309 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4310 * by empty strings. 4311 * </p> 4312 * 4313 * <pre> 4314 * StringUtils.join(null, *) = null 4315 * StringUtils.join([], *) = "" 4316 * StringUtils.join([null], *) = "" 4317 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4318 * StringUtils.join([1, 2, 3], null) = "123" 4319 * </pre> 4320 * 4321 * @param array 4322 * the array of values to join together, may be null. 4323 * @param delimiter 4324 * the separator character to use. 4325 * @param startIndex 4326 * the first index to start joining from. It is an error to pass in a start index past the end of the 4327 * array. 4328 * @param endIndex 4329 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4330 * the array. 4331 * @return The joined String, {@code null} if null array input. 4332 * @since 3.2 4333 */ 4334 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4335 // See StringUtilsJoinBenchmark 4336 if (array == null) { 4337 return null; 4338 } 4339 checkFromToIndex(startIndex, endIndex, array.length); 4340 final int count = endIndex - startIndex; 4341 if (count <= 0) { 4342 return EMPTY; 4343 } 4344 final byte maxElementChars = 11; // "-2147483648" 4345 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4346 stringBuilder.append(array[startIndex]); 4347 for (int i = startIndex + 1; i < endIndex; i++) { 4348 stringBuilder.append(delimiter).append(array[i]); 4349 } 4350 return stringBuilder.toString(); 4351 } 4352 4353 /** 4354 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4355 * 4356 * <p> 4357 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4358 * </p> 4359 * 4360 * <p> 4361 * See the examples here: {@link #join(Object[],char)}. 4362 * </p> 4363 * 4364 * @param iterable The {@link Iterable} providing the values to join together, may be null. 4365 * @param separator The separator character to use. 4366 * @return The joined String, {@code null} if null iterator input. 4367 * @since 2.3 4368 */ 4369 public static String join(final Iterable<?> iterable, final char separator) { 4370 return iterable != null ? join(iterable.iterator(), separator) : null; 4371 } 4372 4373 /** 4374 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4375 * 4376 * <p> 4377 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4378 * </p> 4379 * 4380 * <p> 4381 * See the examples here: {@link #join(Object[],String)}. 4382 * </p> 4383 * 4384 * @param iterable The {@link Iterable} providing the values to join together, may be null. 4385 * @param separator The separator character to use, null treated as "". 4386 * @return The joined String, {@code null} if null iterator input. 4387 * @since 2.3 4388 */ 4389 public static String join(final Iterable<?> iterable, final String separator) { 4390 return iterable != null ? join(iterable.iterator(), separator) : null; 4391 } 4392 4393 /** 4394 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4395 * 4396 * <p> 4397 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4398 * </p> 4399 * 4400 * <p> 4401 * See the examples here: {@link #join(Object[],char)}. 4402 * </p> 4403 * 4404 * @param iterator The {@link Iterator} of values to join together, may be null. 4405 * @param separator The separator character to use. 4406 * @return The joined String, {@code null} if null iterator input. 4407 * @since 2.0 4408 */ 4409 public static String join(final Iterator<?> iterator, final char separator) { 4410 // handle null, zero and one elements before building a buffer 4411 if (iterator == null) { 4412 return null; 4413 } 4414 if (!iterator.hasNext()) { 4415 return EMPTY; 4416 } 4417 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString)); 4418 } 4419 4420 /** 4421 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4422 * 4423 * <p> 4424 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4425 * </p> 4426 * 4427 * <p> 4428 * See the examples here: {@link #join(Object[],String)}. 4429 * </p> 4430 * 4431 * @param iterator The {@link Iterator} of values to join together, may be null. 4432 * @param separator The separator character to use, null treated as "". 4433 * @return The joined String, {@code null} if null iterator input. 4434 */ 4435 public static String join(final Iterator<?> iterator, final String separator) { 4436 // handle null, zero and one elements before building a buffer 4437 if (iterator == null) { 4438 return null; 4439 } 4440 if (!iterator.hasNext()) { 4441 return EMPTY; 4442 } 4443 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString)); 4444 } 4445 4446 /** 4447 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4448 * 4449 * <p> 4450 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4451 * </p> 4452 * 4453 * <pre> 4454 * StringUtils.join(null, *) = null 4455 * StringUtils.join([], *) = "" 4456 * StringUtils.join([null], *) = "" 4457 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4458 * StringUtils.join(["a", "b", "c"], null) = "abc" 4459 * StringUtils.join([null, "", "a"], ';') = ";;a" 4460 * </pre> 4461 * 4462 * @param list The {@link List} of values to join together, may be null. 4463 * @param separator The separator character to use. 4464 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the list. 4465 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list. 4466 * @return The joined String, {@code null} if null list input. 4467 * @since 3.8 4468 */ 4469 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4470 if (list == null) { 4471 return null; 4472 } 4473 final int noOfItems = endIndex - startIndex; 4474 if (noOfItems <= 0) { 4475 return EMPTY; 4476 } 4477 final List<?> subList = list.subList(startIndex, endIndex); 4478 return join(subList.iterator(), separator); 4479 } 4480 4481 /** 4482 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4483 * 4484 * <p> 4485 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4486 * </p> 4487 * 4488 * <pre> 4489 * StringUtils.join(null, *) = null 4490 * StringUtils.join([], *) = "" 4491 * StringUtils.join([null], *) = "" 4492 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4493 * StringUtils.join(["a", "b", "c"], null) = "abc" 4494 * StringUtils.join([null, "", "a"], ';') = ";;a" 4495 * </pre> 4496 * 4497 * @param list The {@link List} of values to join together, may be null. 4498 * @param separator The separator character to use. 4499 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the list. 4500 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list. 4501 * @return The joined String, {@code null} if null list input. 4502 * @since 3.8 4503 */ 4504 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4505 if (list == null) { 4506 return null; 4507 } 4508 final int noOfItems = endIndex - startIndex; 4509 if (noOfItems <= 0) { 4510 return EMPTY; 4511 } 4512 final List<?> subList = list.subList(startIndex, endIndex); 4513 return join(subList.iterator(), separator); 4514 } 4515 4516 /** 4517 * Joins the elements of the provided array into a single String containing the provided list of elements. 4518 * 4519 * <p> 4520 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4521 * by empty strings. 4522 * </p> 4523 * 4524 * <pre> 4525 * StringUtils.join(null, *) = null 4526 * StringUtils.join([], *) = "" 4527 * StringUtils.join([null], *) = "" 4528 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4529 * StringUtils.join([1, 2, 3], null) = "123" 4530 * </pre> 4531 * 4532 * @param array 4533 * the array of values to join together, may be null. 4534 * @param separator 4535 * the separator character to use. 4536 * @return The joined String, {@code null} if null array input. 4537 * @since 3.2 4538 */ 4539 public static String join(final long[] array, final char separator) { 4540 if (array == null) { 4541 return null; 4542 } 4543 return join(array, separator, 0, array.length); 4544 } 4545 4546 /** 4547 * Joins the elements of the provided array into a single String containing the provided list of elements. 4548 * 4549 * <p> 4550 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4551 * by empty strings. 4552 * </p> 4553 * 4554 * <pre> 4555 * StringUtils.join(null, *) = null 4556 * StringUtils.join([], *) = "" 4557 * StringUtils.join([null], *) = "" 4558 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4559 * StringUtils.join([1, 2, 3], null) = "123" 4560 * </pre> 4561 * 4562 * @param array 4563 * the array of values to join together, may be null. 4564 * @param delimiter 4565 * the separator character to use. 4566 * @param startIndex 4567 * the first index to start joining from. It is an error to pass in a start index past the end of the 4568 * array. 4569 * @param endIndex 4570 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4571 * the array. 4572 * @return The joined String, {@code null} if null array input. 4573 * @since 3.2 4574 */ 4575 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4576 // See StringUtilsJoinBenchmark 4577 if (array == null) { 4578 return null; 4579 } 4580 checkFromToIndex(startIndex, endIndex, array.length); 4581 final int count = endIndex - startIndex; 4582 if (count <= 0) { 4583 return EMPTY; 4584 } 4585 final byte maxElementChars = 20; // "-9223372036854775808" 4586 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4587 stringBuilder.append(array[startIndex]); 4588 for (int i = startIndex + 1; i < endIndex; i++) { 4589 stringBuilder.append(delimiter).append(array[i]); 4590 } 4591 return stringBuilder.toString(); 4592 } 4593 4594 /** 4595 * Joins the elements of the provided array into a single String containing the provided list of elements. 4596 * 4597 * <p> 4598 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4599 * </p> 4600 * 4601 * <pre> 4602 * StringUtils.join(null, *) = null 4603 * StringUtils.join([], *) = "" 4604 * StringUtils.join([null], *) = "" 4605 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4606 * StringUtils.join(["a", "b", "c"], null) = "abc" 4607 * StringUtils.join([null, "", "a"], ';') = ";;a" 4608 * </pre> 4609 * 4610 * @param array The array of values to join together, may be null. 4611 * @param delimiter The separator character to use. 4612 * @return The joined String, {@code null} if null array input. 4613 * @since 2.0 4614 */ 4615 public static String join(final Object[] array, final char delimiter) { 4616 if (array == null) { 4617 return null; 4618 } 4619 return join(array, delimiter, 0, array.length); 4620 } 4621 4622 /** 4623 * Joins the elements of the provided array into a single String containing the provided list of elements. 4624 * 4625 * <p> 4626 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4627 * </p> 4628 * 4629 * <pre> 4630 * StringUtils.join(null, *) = null 4631 * StringUtils.join([], *) = "" 4632 * StringUtils.join([null], *) = "" 4633 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4634 * StringUtils.join(["a", "b", "c"], null) = "abc" 4635 * StringUtils.join([null, "", "a"], ';') = ";;a" 4636 * </pre> 4637 * 4638 * @param array The array of values to join together, may be null. 4639 * @param delimiter The separator character to use. 4640 * @param startIndex The first index to start joining from. It is an error to pass in a start index past the end of the array. 4641 * @param endIndex The index to stop joining from (exclusive). It is an error to pass in an end index past the end of the array. 4642 * @return The joined String, {@code null} if null array input. 4643 * @since 2.0 4644 */ 4645 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4646 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4647 } 4648 4649 /** 4650 * Joins the elements of the provided array into a single String containing the provided list of elements. 4651 * 4652 * <p> 4653 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the 4654 * array are represented by empty strings. 4655 * </p> 4656 * 4657 * <pre> 4658 * StringUtils.join(null, *) = null 4659 * StringUtils.join([], *) = "" 4660 * StringUtils.join([null], *) = "" 4661 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4662 * StringUtils.join(["a", "b", "c"], null) = "abc" 4663 * StringUtils.join(["a", "b", "c"], "") = "abc" 4664 * StringUtils.join([null, "", "a"], ',') = ",,a" 4665 * </pre> 4666 * 4667 * @param array The array of values to join together, may be null. 4668 * @param delimiter The separator character to use, null treated as "". 4669 * @return The joined String, {@code null} if null array input. 4670 */ 4671 public static String join(final Object[] array, final String delimiter) { 4672 return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null; 4673 } 4674 4675 /** 4676 * Joins the elements of the provided array into a single String containing the provided list of elements. 4677 * 4678 * <p> 4679 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the 4680 * array are represented by empty strings. 4681 * </p> 4682 * 4683 * <pre> 4684 * StringUtils.join(null, *, *, *) = null 4685 * StringUtils.join([], *, *, *) = "" 4686 * StringUtils.join([null], *, *, *) = "" 4687 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4688 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4689 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4690 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4691 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4692 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4693 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4694 * </pre> 4695 * 4696 * @param array The array of values to join together, may be null. 4697 * @param delimiter The separator character to use, null treated as "". 4698 * @param startIndex The first index to start joining from. 4699 * @param endIndex The index to stop joining from (exclusive). 4700 * @return The joined String, {@code null} if null array input; or the empty string if {@code endIndex - startIndex <= 0}. The number of joined entries is 4701 * given by {@code endIndex - startIndex}. 4702 * @throws ArrayIndexOutOfBoundsException Thrown if<br> {@code startIndex < 0} or <br> {@code startIndex >= array.length()} or <br> {@code endIndex < 0} or 4703 * <br> {@code endIndex > array.length()}. 4704 */ 4705 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4706 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4707 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null; 4708 } 4709 4710 /** 4711 * Joins the elements of the provided array into a single String containing the provided list of elements. 4712 * 4713 * <p> 4714 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4715 * by empty strings. 4716 * </p> 4717 * 4718 * <pre> 4719 * StringUtils.join(null, *) = null 4720 * StringUtils.join([], *) = "" 4721 * StringUtils.join([null], *) = "" 4722 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4723 * StringUtils.join([1, 2, 3], null) = "123" 4724 * </pre> 4725 * 4726 * @param array 4727 * the array of values to join together, may be null. 4728 * @param delimiter 4729 * the separator character to use. 4730 * @return The joined String, {@code null} if null array input. 4731 * @since 3.2 4732 */ 4733 public static String join(final short[] array, final char delimiter) { 4734 if (array == null) { 4735 return null; 4736 } 4737 return join(array, delimiter, 0, array.length); 4738 } 4739 4740 /** 4741 * Joins the elements of the provided array into a single String containing the provided list of elements. 4742 * 4743 * <p> 4744 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4745 * by empty strings. 4746 * </p> 4747 * 4748 * <pre> 4749 * StringUtils.join(null, *) = null 4750 * StringUtils.join([], *) = "" 4751 * StringUtils.join([null], *) = "" 4752 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4753 * StringUtils.join([1, 2, 3], null) = "123" 4754 * </pre> 4755 * 4756 * @param array 4757 * the array of values to join together, may be null. 4758 * @param delimiter 4759 * the separator character to use. 4760 * @param startIndex 4761 * the first index to start joining from. It is an error to pass in a start index past the end of the 4762 * array. 4763 * @param endIndex 4764 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4765 * the array. 4766 * @return The joined String, {@code null} if null array input. 4767 * @since 3.2 4768 */ 4769 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4770 // See StringUtilsJoinBenchmark 4771 if (array == null) { 4772 return null; 4773 } 4774 checkFromToIndex(startIndex, endIndex, array.length); 4775 final int count = endIndex - startIndex; 4776 if (count <= 0) { 4777 return EMPTY; 4778 } 4779 final byte maxElementChars = 6; // "-32768" 4780 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4781 stringBuilder.append(array[startIndex]); 4782 for (int i = startIndex + 1; i < endIndex; i++) { 4783 stringBuilder.append(delimiter).append(array[i]); 4784 } 4785 return stringBuilder.toString(); 4786 } 4787 4788 /** 4789 * Joins the elements of the provided array into a single String containing the provided list of elements. 4790 * 4791 * <p> 4792 * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings. 4793 * </p> 4794 * 4795 * <pre> 4796 * StringUtils.join(null) = null 4797 * StringUtils.join([]) = "" 4798 * StringUtils.join([null]) = "" 4799 * StringUtils.join("a", "b", "c") = "abc" 4800 * StringUtils.join(null, "", "a") = "a" 4801 * </pre> 4802 * 4803 * @param <T> the specific type of values to join together. 4804 * @param elements The values to join together, may be null. 4805 * @return The joined String, {@code null} if null array input. 4806 * @since 2.0 4807 * @since 3.0 Changed signature to use varargs 4808 */ 4809 @SafeVarargs 4810 public static <T> String join(final T... elements) { 4811 return join(elements, null); 4812 } 4813 4814 /** 4815 * Joins the elements of the provided varargs into a single String containing the provided elements. 4816 * 4817 * <p> 4818 * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings (""). 4819 * </p> 4820 * 4821 * <pre> 4822 * StringUtils.joinWith(",", "a", "b") = "a,b" 4823 * StringUtils.joinWith(",", "a", "b","") = "a,b," 4824 * StringUtils.joinWith(",", "a", null, "b") = "a,,b" 4825 * StringUtils.joinWith(null, "a", "b") = "ab" 4826 * </pre> 4827 * 4828 * @param delimiter The separator character to use, null treated as "". 4829 * @param array The varargs providing the values to join together. {@code null} elements are treated as "". 4830 * @return The joined String. 4831 * @throws IllegalArgumentException Thrown if a null varargs is provided. 4832 * @since 3.5 4833 */ 4834 public static String joinWith(final String delimiter, final Object... array) { 4835 if (array == null) { 4836 throw new IllegalArgumentException("Object varargs must not be null"); 4837 } 4838 return join(array, delimiter); 4839 } 4840 4841 /** 4842 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible. 4843 * 4844 * <p> 4845 * A {@code null} CharSequence will return {@code -1}. 4846 * </p> 4847 * 4848 * <pre> 4849 * StringUtils.lastIndexOf(null, *) = -1 4850 * StringUtils.lastIndexOf(*, null) = -1 4851 * StringUtils.lastIndexOf("", "") = 0 4852 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4853 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4854 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4855 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4856 * </pre> 4857 * 4858 * @param seq The CharSequence to check, may be null. 4859 * @param searchSeq The CharSequence to find, may be null. 4860 * @return The last index of the search String, -1 if no match or {@code null} string input. 4861 * @since 2.0 4862 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4863 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}. 4864 */ 4865 @Deprecated 4866 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4867 return Strings.CS.lastIndexOf(seq, searchSeq); 4868 } 4869 4870 /** 4871 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible. 4872 * 4873 * <p> 4874 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4875 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works 4876 * backwards; matches starting after the start position are ignored. 4877 * </p> 4878 * 4879 * <pre> 4880 * StringUtils.lastIndexOf(null, *, *) = -1 4881 * StringUtils.lastIndexOf(*, null, *) = -1 4882 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4883 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4884 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4885 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4886 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4887 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4888 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4889 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4890 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4891 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4892 * </pre> 4893 * 4894 * @param seq The CharSequence to check, may be null. 4895 * @param searchSeq The CharSequence to find, may be null. 4896 * @param startPos The start position, negative treated as zero. 4897 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} string input. 4898 * @since 2.0 4899 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4900 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}. 4901 */ 4902 @Deprecated 4903 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4904 return Strings.CS.lastIndexOf(seq, searchSeq, startPos); 4905 } 4906 4907 /** 4908 * Returns the index within {@code seq} of the last occurrence of the specified character. For values of {@code searchChar} in the range from 0 to 0xFFFF 4909 * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that: 4910 * 4911 * <pre> 4912 * this.charAt(<em>k</em>) == searchChar 4913 * </pre> 4914 * 4915 * <p> 4916 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4917 * </p> 4918 * 4919 * <pre> 4920 * this.codePointAt(<em>k</em>) == searchChar 4921 * </pre> 4922 * 4923 * <p> 4924 * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4925 * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character. 4926 * </p> 4927 * 4928 * <pre> 4929 * StringUtils.lastIndexOf(null, *) = -1 4930 * StringUtils.lastIndexOf("", *) = -1 4931 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4932 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4933 * </pre> 4934 * 4935 * @param seq The {@link CharSequence} to check, may be null. 4936 * @param searchChar The character to find. 4937 * @return The last index of the search character, -1 if no match or {@code null} string input. 4938 * @since 2.0 4939 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4940 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4941 */ 4942 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4943 if (isEmpty(seq)) { 4944 return INDEX_NOT_FOUND; 4945 } 4946 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4947 } 4948 4949 /** 4950 * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of 4951 * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that: 4952 * 4953 * <pre> 4954 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4955 * </pre> 4956 * 4957 * <p> 4958 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4959 * </p> 4960 * 4961 * <pre> 4962 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4963 * </pre> 4964 * 4965 * <p> 4966 * is true. In either case, if no such character occurs in {@code seq} at or before position {@code startPos}, then {@code -1} is returned. Furthermore, a 4967 * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The 4968 * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored. 4969 * </p> 4970 * 4971 * <p> 4972 * All indices are specified in {@code char} values (Unicode code units). 4973 * </p> 4974 * 4975 * <pre> 4976 * StringUtils.lastIndexOf(null, *, *) = -1 4977 * StringUtils.lastIndexOf("", *, *) = -1 4978 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4979 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4980 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4981 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4982 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4983 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 4984 * </pre> 4985 * 4986 * @param seq The CharSequence to check, may be null. 4987 * @param searchChar The character to find. 4988 * @param startPos The start position. 4989 * @return The last index of the search character (always ≤ startPos), -1 if no match or {@code null} string input. 4990 * @since 2.0 4991 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 4992 */ 4993 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 4994 if (isEmpty(seq)) { 4995 return INDEX_NOT_FOUND; 4996 } 4997 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 4998 } 4999 5000 /** 5001 * Finds the latest index of any substring in a set of potential substrings. 5002 * 5003 * <p> 5004 * A {@code null} CharSequence will return {@code -1}. A {@code null} search array will return {@code -1}. A {@code null} or zero length search array entry 5005 * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses 5006 * {@link String#indexOf(String)} if possible 5007 * </p> 5008 * 5009 * <pre> 5010 * StringUtils.lastIndexOfAny(null, *) = -1 5011 * StringUtils.lastIndexOfAny(*, null) = -1 5012 * StringUtils.lastIndexOfAny(*, []) = -1 5013 * StringUtils.lastIndexOfAny(*, [null]) = -1 5014 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 5015 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 5016 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5017 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 5018 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 5019 * </pre> 5020 * 5021 * @param str The CharSequence to check, may be null. 5022 * @param searchStrs The CharSequences to search for, may be null. 5023 * @return The last index of any of the CharSequences, -1 if no match. 5024 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 5025 */ 5026 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 5027 if (str == null || searchStrs == null) { 5028 return INDEX_NOT_FOUND; 5029 } 5030 int ret = INDEX_NOT_FOUND; 5031 int tmp; 5032 for (final CharSequence search : searchStrs) { 5033 if (search == null) { 5034 continue; 5035 } 5036 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 5037 if (tmp > ret) { 5038 ret = tmp; 5039 } 5040 } 5041 return ret; 5042 } 5043 5044 /** 5045 * Case insensitive find of the last index within a CharSequence. 5046 * 5047 * <p> 5048 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 5049 * the start position is negative. A start position greater than the string length searches the whole string. 5050 * </p> 5051 * 5052 * <pre> 5053 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 5054 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 5055 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 5056 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 5057 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 5058 * </pre> 5059 * 5060 * @param str The CharSequence to check, may be null. 5061 * @param searchStr The CharSequence to find, may be null. 5062 * @return The first index of the search CharSequence, -1 if no match or {@code null} string input. 5063 * @since 2.5 5064 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 5065 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}. 5066 */ 5067 @Deprecated 5068 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 5069 return Strings.CI.lastIndexOf(str, searchStr); 5070 } 5071 5072 /** 5073 * Case insensitive find of the last index within a CharSequence from the specified position. 5074 * 5075 * <p> 5076 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 5077 * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works 5078 * backwards; matches starting after the start position are ignored. 5079 * </p> 5080 * 5081 * <pre> 5082 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 5083 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 5084 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5085 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5086 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5087 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5088 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5089 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5090 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5091 * </pre> 5092 * 5093 * @param str The CharSequence to check, may be null. 5094 * @param searchStr The CharSequence to find, may be null. 5095 * @param startPos The start position. 5096 * @return The last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} input. 5097 * @since 2.5 5098 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5099 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}. 5100 */ 5101 @Deprecated 5102 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 5103 return Strings.CI.lastIndexOf(str, searchStr, startPos); 5104 } 5105 5106 /** 5107 * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}. 5108 * 5109 * <p> 5110 * A {@code null} String will return {@code -1}. 5111 * </p> 5112 * 5113 * <pre> 5114 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5115 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5116 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5117 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5118 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5119 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5120 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5121 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5122 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5123 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5124 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5125 * </pre> 5126 * 5127 * <p> 5128 * Note that 'tail(CharSequence str, int n)' may be implemented as: 5129 * </p> 5130 * 5131 * <pre> 5132 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5133 * </pre> 5134 * 5135 * @param str The CharSequence to check, may be null. 5136 * @param searchStr The CharSequence to find, may be null. 5137 * @param ordinal The n-th last {@code searchStr} to find. 5138 * @return The n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5139 * @since 2.5 5140 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5141 */ 5142 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5143 return ordinalIndexOf(str, searchStr, ordinal, true); 5144 } 5145 5146 /** 5147 * Gets the leftmost {@code len} characters of a String. 5148 * 5149 * <p> 5150 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is returned 5151 * if len is negative. 5152 * </p> 5153 * 5154 * <pre> 5155 * StringUtils.left(null, *) = null 5156 * StringUtils.left(*, -ve) = "" 5157 * StringUtils.left("", *) = "" 5158 * StringUtils.left("abc", 0) = "" 5159 * StringUtils.left("abc", 2) = "ab" 5160 * StringUtils.left("abc", 4) = "abc" 5161 * </pre> 5162 * 5163 * @param str The String to get the leftmost characters from, may be null. 5164 * @param len The length of the required String. 5165 * @return The leftmost characters, {@code null} if null String input. 5166 */ 5167 public static String left(final String str, final int len) { 5168 if (str == null) { 5169 return null; 5170 } 5171 if (len < 0) { 5172 return EMPTY; 5173 } 5174 if (str.length() <= len) { 5175 return str; 5176 } 5177 int cut = len; 5178 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 5179 if (splitsSurrogatePair(str, cut)) { 5180 cut--; 5181 } 5182 return str.substring(0, cut); 5183 } 5184 5185 /** 5186 * Left pad a String with spaces (' '). 5187 * 5188 * <p> 5189 * The String is padded to the size of {@code size}. 5190 * </p> 5191 * 5192 * <pre> 5193 * StringUtils.leftPad(null, *) = null 5194 * StringUtils.leftPad("", 3) = " " 5195 * StringUtils.leftPad("bat", 3) = "bat" 5196 * StringUtils.leftPad("bat", 5) = " bat" 5197 * StringUtils.leftPad("bat", 1) = "bat" 5198 * StringUtils.leftPad("bat", -1) = "bat" 5199 * </pre> 5200 * 5201 * @param str The String to pad out, may be null. 5202 * @param size The size to pad to. 5203 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5204 */ 5205 public static String leftPad(final String str, final int size) { 5206 return leftPad(str, size, ' '); 5207 } 5208 5209 /** 5210 * Left pad a String with a specified character. 5211 * 5212 * <p> 5213 * Pad to a size of {@code size}. 5214 * </p> 5215 * 5216 * <pre> 5217 * StringUtils.leftPad(null, *, *) = null 5218 * StringUtils.leftPad("", 3, 'z') = "zzz" 5219 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5220 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5221 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5222 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5223 * </pre> 5224 * 5225 * @param str The String to pad out, may be null. 5226 * @param size The size to pad to. 5227 * @param padChar The character to pad with. 5228 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5229 * @since 2.0 5230 */ 5231 public static String leftPad(final String str, final int size, final char padChar) { 5232 if (str == null || size <= str.length()) { 5233 return str; 5234 } 5235 final int pads = size - str.length(); 5236 if (pads <= 0) { 5237 return str; // returns original String when possible 5238 } 5239 if (pads > PAD_LIMIT) { 5240 return leftPad(str, size, String.valueOf(padChar)); 5241 } 5242 return repeat(padChar, pads).concat(str); 5243 } 5244 5245 /** 5246 * Left pad a String with a specified String. 5247 * 5248 * <p> 5249 * Pad to a size of {@code size}. 5250 * </p> 5251 * 5252 * <pre> 5253 * StringUtils.leftPad(null, *, *) = null 5254 * StringUtils.leftPad("", 3, "z") = "zzz" 5255 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5256 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5257 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5258 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5259 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5260 * StringUtils.leftPad("bat", 5, null) = " bat" 5261 * StringUtils.leftPad("bat", 5, "") = " bat" 5262 * </pre> 5263 * 5264 * @param str The String to pad out, may be null. 5265 * @param size The size to pad to. 5266 * @param padStr The String to pad with, null or empty treated as single space. 5267 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5268 */ 5269 public static String leftPad(final String str, final int size, String padStr) { 5270 if (str == null || size <= str.length()) { 5271 return str; 5272 } 5273 if (isEmpty(padStr)) { 5274 padStr = SPACE; 5275 } 5276 final int padLen = padStr.length(); 5277 final int strLen = str.length(); 5278 final int pads = size - strLen; 5279 if (pads <= 0) { 5280 return str; // returns original String when possible 5281 } 5282 if (padLen == 1 && pads <= PAD_LIMIT) { 5283 return leftPad(str, size, padStr.charAt(0)); 5284 } 5285 if (pads == padLen) { 5286 return padStr.concat(str); 5287 } 5288 if (pads < padLen) { 5289 return padStr.substring(0, pads).concat(str); 5290 } 5291 final char[] padding = new char[pads]; 5292 final char[] padChars = padStr.toCharArray(); 5293 for (int i = 0; i < pads; i++) { 5294 padding[i] = padChars[i % padLen]; 5295 } 5296 return new String(padding).concat(str); 5297 } 5298 5299 /** 5300 * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}. 5301 * 5302 * @param cs A CharSequence or {@code null}. 5303 * @return CharSequence length or {@code 0} if the CharSequence is {@code null}. 5304 * @since 2.4 5305 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5306 */ 5307 public static int length(final CharSequence cs) { 5308 return cs == null ? 0 : cs.length(); 5309 } 5310 5311 /** 5312 * Converts a String to lower case as per {@link String#toLowerCase()}. 5313 * 5314 * <p> 5315 * A {@code null} input String returns {@code null}. 5316 * </p> 5317 * 5318 * <pre> 5319 * StringUtils.lowerCase(null) = null 5320 * StringUtils.lowerCase("") = "" 5321 * StringUtils.lowerCase("aBc") = "abc" 5322 * </pre> 5323 * 5324 * <p> 5325 * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale. 5326 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g. 5327 * {@link Locale#ENGLISH}). 5328 * </p> 5329 * 5330 * @param str The String to lower case, may be null. 5331 * @return The lower cased String, {@code null} if null String input. 5332 */ 5333 public static String lowerCase(final String str) { 5334 if (str == null) { 5335 return null; 5336 } 5337 return str.toLowerCase(); 5338 } 5339 5340 /** 5341 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5342 * 5343 * <p> 5344 * A {@code null} input String returns {@code null}. 5345 * </p> 5346 * 5347 * <pre> 5348 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5349 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5350 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5351 * </pre> 5352 * 5353 * @param str The String to lower case, may be null. 5354 * @param locale The locale that defines the case transformation rules, must not be null. 5355 * @return The lower cased String, {@code null} if null String input. 5356 * @since 2.5 5357 */ 5358 public static String lowerCase(final String str, final Locale locale) { 5359 if (str == null) { 5360 return null; 5361 } 5362 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5363 } 5364 5365 private static int[] matches(final CharSequence first, final CharSequence second) { 5366 final CharSequence max; 5367 final CharSequence min; 5368 if (first.length() > second.length()) { 5369 max = first; 5370 min = second; 5371 } else { 5372 max = second; 5373 min = first; 5374 } 5375 final int range = Math.max(max.length() / 2 - 1, 0); 5376 final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1); 5377 final boolean[] matchFlags = new boolean[max.length()]; 5378 int matches = 0; 5379 for (int mi = 0; mi < min.length(); mi++) { 5380 final char c1 = min.charAt(mi); 5381 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5382 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5383 matchIndexes[mi] = xi; 5384 matchFlags[xi] = true; 5385 matches++; 5386 break; 5387 } 5388 } 5389 } 5390 final char[] ms1 = new char[matches]; 5391 final char[] ms2 = new char[matches]; 5392 for (int i = 0, si = 0; i < min.length(); i++) { 5393 if (matchIndexes[i] != -1) { 5394 ms1[si] = min.charAt(i); 5395 si++; 5396 } 5397 } 5398 for (int i = 0, si = 0; i < max.length(); i++) { 5399 if (matchFlags[i]) { 5400 ms2[si] = max.charAt(i); 5401 si++; 5402 } 5403 } 5404 int transpositions = 0; 5405 for (int mi = 0; mi < ms1.length; mi++) { 5406 if (ms1[mi] != ms2[mi]) { 5407 transpositions++; 5408 } 5409 } 5410 int prefix = 0; 5411 for (int mi = 0; mi < min.length(); mi++) { 5412 if (first.charAt(mi) != second.charAt(mi)) { 5413 break; 5414 } 5415 prefix++; 5416 } 5417 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5418 } 5419 5420 /** 5421 * Gets {@code len} characters from the middle of a String. 5422 * 5423 * <p> 5424 * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null}, 5425 * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}. 5426 * </p> 5427 * 5428 * <pre> 5429 * StringUtils.mid(null, *, *) = null 5430 * StringUtils.mid(*, *, -ve) = "" 5431 * StringUtils.mid("", 0, *) = "" 5432 * StringUtils.mid("abc", 0, 2) = "ab" 5433 * StringUtils.mid("abc", 0, 4) = "abc" 5434 * StringUtils.mid("abc", 2, 4) = "c" 5435 * StringUtils.mid("abc", 4, 2) = "" 5436 * StringUtils.mid("abc", -2, 2) = "ab" 5437 * </pre> 5438 * 5439 * @param str The String to get the characters from, may be null. 5440 * @param pos The position to start from, negative treated as zero. 5441 * @param len The length of the required String. 5442 * @return The middle characters, {@code null} if null String input. 5443 */ 5444 public static String mid(final String str, int pos, final int len) { 5445 if (str == null) { 5446 return null; 5447 } 5448 if (len < 0 || pos > str.length()) { 5449 return EMPTY; 5450 } 5451 if (pos < 0) { 5452 pos = 0; 5453 } 5454 int start = pos; 5455 // keep the start off the middle of a surrogate pair so the result is never left holding a lone surrogate 5456 if (splitsSurrogatePair(str, start)) { 5457 start++; 5458 } 5459 if (str.length() - pos <= len) { 5460 return str.substring(start); 5461 } 5462 int end = pos + len; 5463 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 5464 if (splitsSurrogatePair(str, end)) { 5465 end--; 5466 } 5467 return str.substring(start, Math.max(start, end)); 5468 } 5469 5470 /** 5471 * Similar to <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize -space</a> 5472 * 5473 * <p> 5474 * This function returns the argument string with whitespace normalized by using {@code {@link #trim(String)}} to remove leading and trailing whitespace and 5475 * then replacing sequences of whitespace characters by a single space. 5476 * </p> 5477 * In XML, whitespace characters are the same as those allowed by the <a href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | 5478 * #x9 | #xD | #xA)+ 5479 * <p> 5480 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5481 * </p> 5482 * <p> 5483 * For reference: 5484 * </p> 5485 * <ul> 5486 * <li>\x0B = vertical tab</li> 5487 * <li>\f = #xC = form feed</li> 5488 * <li>#x20 = space</li> 5489 * <li>#x9 = \t</li> 5490 * <li>#xA = \n</li> 5491 * <li>#xD = \r</li> 5492 * </ul> 5493 * 5494 * <p> 5495 * The difference is that Java's whitespace includes vertical tab and form feed, which this function will also normalize. Additionally {@code {@link 5496 * #trim(String)}} removes control characters (char <= 32) from both ends of this String. 5497 * </p> 5498 * 5499 * @param str The source String to normalize whitespaces from, may be null. 5500 * @return The modified string with whitespace normalized, {@code null} if null String input. 5501 * @see Pattern 5502 * @see #trim(String) 5503 * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5504 * @since 3.0 5505 */ 5506 public static String normalizeSpace(final String str) { 5507 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5508 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5509 if (isEmpty(str)) { 5510 return str; 5511 } 5512 final int size = str.length(); 5513 final char[] newChars = new char[size]; 5514 int count = 0; 5515 int whitespacesCount = 0; 5516 boolean startWhitespaces = true; 5517 for (int i = 0; i < size; i++) { 5518 final char actualChar = str.charAt(i); 5519 final boolean isWhitespace = Character.isWhitespace(actualChar); 5520 if (isWhitespace) { 5521 if (whitespacesCount == 0 && !startWhitespaces) { 5522 newChars[count++] = SPACE.charAt(0); 5523 } 5524 whitespacesCount++; 5525 } else { 5526 startWhitespaces = false; 5527 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5528 whitespacesCount = 0; 5529 } 5530 } 5531 if (startWhitespaces) { 5532 return EMPTY; 5533 } 5534 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5535 } 5536 5537 /** 5538 * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5539 * <p> 5540 * <strong>Note:</strong> The code starts looking for a match at the start of the target, incrementing the starting index by one after each successful match 5541 * (unless {@code searchStr} is an empty string, in which case the position is never incremented and {@code 0} is returned immediately). This means that 5542 * matches may overlap. 5543 * </p> 5544 * <p> 5545 * A {@code null} CharSequence will return {@code -1}. 5546 * </p> 5547 * 5548 * <pre> 5549 * StringUtils.ordinalIndexOf(null, *, *) = -1 5550 * StringUtils.ordinalIndexOf(*, null, *) = -1 5551 * StringUtils.ordinalIndexOf("", "", *) = 0 5552 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5553 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5554 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5555 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5556 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5557 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5558 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5559 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5560 * </pre> 5561 * 5562 * <p> 5563 * Matches may overlap: 5564 * </p> 5565 * 5566 * <pre> 5567 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5568 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5569 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5570 * 5571 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5572 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5573 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5574 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5575 * </pre> 5576 * 5577 * <p> 5578 * Note that 'head(CharSequence str, int n)' may be implemented as: 5579 * </p> 5580 * 5581 * <pre> 5582 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5583 * </pre> 5584 * 5585 * @param str The CharSequence to check, may be null. 5586 * @param searchStr The CharSequence to find, may be null. 5587 * @param ordinal The n-th {@code searchStr} to find. 5588 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5589 * @since 2.1 5590 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5591 */ 5592 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5593 return ordinalIndexOf(str, searchStr, ordinal, false); 5594 } 5595 5596 /** 5597 * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5598 * <p> 5599 * Note that matches may overlap. 5600 * <p> 5601 * 5602 * <p> 5603 * A {@code null} CharSequence will return {@code -1}. 5604 * </p> 5605 * 5606 * @param str The CharSequence to check, may be null. 5607 * @param searchStr The CharSequence to find, may be null. 5608 * @param ordinal The n-th {@code searchStr} to find, overlapping matches are allowed. 5609 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf(). 5610 * @return The n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5611 */ 5612 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5613 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5614 if (str == null || searchStr == null || ordinal <= 0) { 5615 return INDEX_NOT_FOUND; 5616 } 5617 if (isEmpty(searchStr)) { 5618 return lastIndex ? str.length() : 0; 5619 } 5620 int found = 0; 5621 // set the initial index beyond the end of the string 5622 // this is to allow for the initial index decrement/increment 5623 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5624 do { 5625 if (lastIndex) { 5626 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5627 } else { 5628 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5629 } 5630 if (index < 0) { 5631 return index; 5632 } 5633 found++; 5634 } while (found < ordinal); 5635 return index; 5636 } 5637 5638 /** 5639 * Overlays part of a String with another String. 5640 * 5641 * <p> 5642 * A {@code null} string input returns {@code null}. A negative index is treated as zero. An index greater than the string length is treated as the string 5643 * length. The start index is always the smaller of the two indices. 5644 * </p> 5645 * 5646 * <pre> 5647 * StringUtils.overlay(null, *, *, *) = null 5648 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5649 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5650 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5651 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5652 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5653 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5654 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5655 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5656 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5657 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5658 * </pre> 5659 * 5660 * @param str The String to do overlaying in, may be null. 5661 * @param overlay The String to overlay, may be null. 5662 * @param start The position to start overlaying at. 5663 * @param end The position to stop overlaying before. 5664 * @return overlaid String, {@code null} if null String input. 5665 * @since 2.0 5666 */ 5667 public static String overlay(final String str, String overlay, int start, int end) { 5668 if (str == null) { 5669 return null; 5670 } 5671 if (overlay == null) { 5672 overlay = EMPTY; 5673 } 5674 final int len = str.length(); 5675 if (start < 0) { 5676 start = 0; 5677 } 5678 if (start > len) { 5679 start = len; 5680 } 5681 if (end < 0) { 5682 end = 0; 5683 } 5684 if (end > len) { 5685 end = len; 5686 } 5687 if (start > end) { 5688 final int temp = start; 5689 start = end; 5690 end = temp; 5691 } 5692 // keep both cuts off the middle of a surrogate pair so the result is never left holding a lone surrogate 5693 if (splitsSurrogatePair(str, start)) { 5694 start--; 5695 } 5696 if (splitsSurrogatePair(str, end)) { 5697 end++; 5698 } 5699 return str.substring(0, start) + overlay + str.substring(end); 5700 } 5701 5702 /** 5703 * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes. 5704 * 5705 * <pre> 5706 * StringUtils.prependIfMissing(null, null) = null 5707 * StringUtils.prependIfMissing("abc", null) = "abc" 5708 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5709 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5710 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5711 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5712 * </pre> 5713 * <p> 5714 * With additional prefixes, 5715 * </p> 5716 * 5717 * <pre> 5718 * StringUtils.prependIfMissing(null, null, null) = null 5719 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5720 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5721 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5722 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5723 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5724 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5725 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5726 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5727 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5728 * </pre> 5729 * 5730 * @param str The string. 5731 * @param prefix The prefix to prepend to the start of the string. 5732 * @param prefixes Additional prefixes that are valid. 5733 * @return A new String if prefix was prepended, the same string otherwise. 5734 * @since 3.2 5735 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence, 5736 * CharSequence...)}. 5737 */ 5738 @Deprecated 5739 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5740 return Strings.CS.prependIfMissing(str, prefix, prefixes); 5741 } 5742 5743 /** 5744 * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes. 5745 * 5746 * <pre> 5747 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5748 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5749 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5750 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5751 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5752 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5753 * </pre> 5754 * <p> 5755 * With additional prefixes, 5756 * </p> 5757 * 5758 * <pre> 5759 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5760 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5761 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5762 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5763 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5764 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5765 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5766 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5767 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5768 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5769 * </pre> 5770 * 5771 * @param str The string. 5772 * @param prefix The prefix to prepend to the start of the string. 5773 * @param prefixes Additional prefixes that are valid (optional). 5774 * @return A new String if prefix was prepended, the same string otherwise. 5775 * @since 3.2 5776 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence, 5777 * CharSequence...)}. 5778 */ 5779 @Deprecated 5780 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5781 return Strings.CI.prependIfMissing(str, prefix, prefixes); 5782 } 5783 5784 /** 5785 * Removes all occurrences of a character from within the source string. 5786 * 5787 * <p> 5788 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. 5789 * </p> 5790 * 5791 * <pre> 5792 * StringUtils.remove(null, *) = null 5793 * StringUtils.remove("", *) = "" 5794 * StringUtils.remove("queued", 'u') = "qeed" 5795 * StringUtils.remove("queued", 'z') = "queued" 5796 * </pre> 5797 * 5798 * @param str The source String to search, may be null. 5799 * @param remove The char to search for and remove, may be null. 5800 * @return The substring with the char removed if found, {@code null} if null String input. 5801 * @since 2.1 5802 */ 5803 public static String remove(final String str, final char remove) { 5804 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5805 return str; 5806 } 5807 final char[] chars = str.toCharArray(); 5808 int pos = 0; 5809 for (int i = 0; i < chars.length; i++) { 5810 if (chars[i] != remove) { 5811 chars[pos++] = chars[i]; 5812 } 5813 } 5814 return new String(chars, 0, pos); 5815 } 5816 5817 /** 5818 * Removes all occurrences of a substring from within the source string. 5819 * 5820 * <p> 5821 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return 5822 * the source string. An empty ("") remove string will return the source string. 5823 * </p> 5824 * 5825 * <pre> 5826 * StringUtils.remove(null, *) = null 5827 * StringUtils.remove("", *) = "" 5828 * StringUtils.remove(*, null) = * 5829 * StringUtils.remove(*, "") = * 5830 * StringUtils.remove("queued", "ue") = "qd" 5831 * StringUtils.remove("queued", "zz") = "queued" 5832 * </pre> 5833 * 5834 * @param str The source String to search, may be null. 5835 * @param remove The String to search for and remove, may be null. 5836 * @return The substring with the string removed if found, {@code null} if null String input. 5837 * @since 2.1 5838 * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}. 5839 */ 5840 @Deprecated 5841 public static String remove(final String str, final String remove) { 5842 return Strings.CS.remove(str, remove); 5843 } 5844 5845 /** 5846 * Removes each substring of the text String that matches the given regular expression. 5847 * 5848 * This method is a {@code null} safe equivalent to: 5849 * <ul> 5850 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5851 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5852 * </ul> 5853 * 5854 * <p> 5855 * A {@code null} reference passed to this method is a no-op. 5856 * </p> 5857 * 5858 * <p> 5859 * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option 5860 * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 5861 * </p> 5862 * 5863 * <pre>{@code 5864 * StringUtils.removeAll(null, *) = null 5865 * StringUtils.removeAll("any", (String) null) = "any" 5866 * StringUtils.removeAll("any", "") = "any" 5867 * StringUtils.removeAll("any", ".*") = "" 5868 * StringUtils.removeAll("any", ".+") = "" 5869 * StringUtils.removeAll("abc", ".?") = "" 5870 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5871 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5872 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5873 * }</pre> 5874 * 5875 * @param text text to remove from, may be null. 5876 * @param regex The regular expression to which this string is to be matched. 5877 * @return The text with any removes processed, {@code null} if null String input. 5878 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 5879 * @see #replaceAll(String, String, String) 5880 * @see #removePattern(String, String) 5881 * @see String#replaceAll(String, String) 5882 * @see java.util.regex.Pattern 5883 * @see java.util.regex.Pattern#DOTALL 5884 * @since 3.5 5885 * @deprecated Use {@link RegExUtils#removeAll(String, String)}. 5886 */ 5887 @Deprecated 5888 public static String removeAll(final String text, final String regex) { 5889 return RegExUtils.removeAll(text, regex); 5890 } 5891 5892 /** 5893 * Removes a substring only if it is at the end of a source string, otherwise returns the source string. 5894 * 5895 * <p> 5896 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5897 * the source string. 5898 * </p> 5899 * 5900 * <pre> 5901 * StringUtils.removeEnd(null, *) = null 5902 * StringUtils.removeEnd("", *) = "" 5903 * StringUtils.removeEnd(*, null) = * 5904 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5905 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5906 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5907 * StringUtils.removeEnd("abc", "") = "abc" 5908 * </pre> 5909 * 5910 * @param str The source String to search, may be null. 5911 * @param remove The String to search for and remove, may be null. 5912 * @return The substring with the string removed if found, {@code null} if null String input. 5913 * @since 2.1 5914 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}. 5915 */ 5916 @Deprecated 5917 public static String removeEnd(final String str, final String remove) { 5918 return Strings.CS.removeEnd(str, remove); 5919 } 5920 5921 /** 5922 * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string. 5923 * 5924 * <p> 5925 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 5926 * the source string. 5927 * </p> 5928 * 5929 * <pre> 5930 * StringUtils.removeEndIgnoreCase(null, *) = null 5931 * StringUtils.removeEndIgnoreCase("", *) = "" 5932 * StringUtils.removeEndIgnoreCase(*, null) = * 5933 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5934 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5935 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5936 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5937 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain" 5938 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain" 5939 * </pre> 5940 * 5941 * @param str The source String to search, may be null. 5942 * @param remove The String to search for (case-insensitive) and remove, may be null. 5943 * @return The substring with the string removed if found, {@code null} if null String input. 5944 * @since 2.4 5945 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}. 5946 */ 5947 @Deprecated 5948 public static String removeEndIgnoreCase(final String str, final String remove) { 5949 return Strings.CI.removeEnd(str, remove); 5950 } 5951 5952 /** 5953 * Removes the first substring of the text string that matches the given regular expression. 5954 * 5955 * This method is a {@code null} safe equivalent to: 5956 * <ul> 5957 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 5958 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 5959 * </ul> 5960 * 5961 * <p> 5962 * A {@code null} reference passed to this method is a no-op. 5963 * </p> 5964 * 5965 * <p> 5966 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as 5967 * single-line mode in Perl. 5968 * </p> 5969 * 5970 * <pre>{@code 5971 * StringUtils.removeFirst(null, *) = null 5972 * StringUtils.removeFirst("any", (String) null) = "any" 5973 * StringUtils.removeFirst("any", "") = "any" 5974 * StringUtils.removeFirst("any", ".*") = "" 5975 * StringUtils.removeFirst("any", ".+") = "" 5976 * StringUtils.removeFirst("abc", ".?") = "bc" 5977 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5978 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5979 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5980 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5981 * }</pre> 5982 * 5983 * @param text text to remove from, may be null. 5984 * @param regex The regular expression to which this string is to be matched. 5985 * @return The text with the first replacement processed, {@code null} if null String input. 5986 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 5987 * @see #replaceFirst(String, String, String) 5988 * @see String#replaceFirst(String, String) 5989 * @see java.util.regex.Pattern 5990 * @see java.util.regex.Pattern#DOTALL 5991 * @since 3.5 5992 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String) RegExUtils.replaceFirst(String, String, EMPTY)}. 5993 */ 5994 @Deprecated 5995 public static String removeFirst(final String text, final String regex) { 5996 return replaceFirst(text, regex, EMPTY); 5997 } 5998 5999 /** 6000 * Case-insensitive removal of all occurrences of a substring from within the source string. 6001 * 6002 * <p> 6003 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return 6004 * the source string. An empty ("") remove string will return the source string. 6005 * </p> 6006 * 6007 * <pre> 6008 * StringUtils.removeIgnoreCase(null, *) = null 6009 * StringUtils.removeIgnoreCase("", *) = "" 6010 * StringUtils.removeIgnoreCase(*, null) = * 6011 * StringUtils.removeIgnoreCase(*, "") = * 6012 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 6013 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 6014 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 6015 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 6016 * </pre> 6017 * 6018 * @param str The source String to search, may be null. 6019 * @param remove The String to search for (case-insensitive) and remove, may be null. 6020 * @return The substring with the string removed if found, {@code null} if null String input. 6021 * @since 3.5 6022 * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}. 6023 */ 6024 @Deprecated 6025 public static String removeIgnoreCase(final String str, final String remove) { 6026 return Strings.CI.remove(str, remove); 6027 } 6028 6029 /** 6030 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 6031 * 6032 * This call is a {@code null} safe equivalent to: 6033 * <ul> 6034 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 6035 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 6036 * </ul> 6037 * 6038 * <p> 6039 * A {@code null} reference passed to this method is a no-op. 6040 * </p> 6041 * 6042 * <pre>{@code 6043 * StringUtils.removePattern(null, *) = null 6044 * StringUtils.removePattern("any", (String) null) = "any" 6045 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 6046 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 6047 * }</pre> 6048 * 6049 * @param source The source string. 6050 * @param regex The regular expression to which this string is to be matched. 6051 * @return The resulting {@link String}. 6052 * @see #replacePattern(String, String, String) 6053 * @see String#replaceAll(String, String) 6054 * @see Pattern#DOTALL 6055 * @since 3.2 6056 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6057 * @deprecated Use {@link RegExUtils#removePattern(CharSequence, String)}. 6058 */ 6059 @Deprecated 6060 public static String removePattern(final String source, final String regex) { 6061 return RegExUtils.removePattern(source, regex); 6062 } 6063 6064 /** 6065 * Removes a char only if it is at the beginning of a source string, otherwise returns the source string. 6066 * 6067 * <p> 6068 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search char will return 6069 * the source string. 6070 * </p> 6071 * 6072 * <pre> 6073 * StringUtils.removeStart(null, *) = null 6074 * StringUtils.removeStart("", *) = "" 6075 * StringUtils.removeStart(*, null) = * 6076 * StringUtils.removeStart("/path", '/') = "path" 6077 * StringUtils.removeStart("path", '/') = "path" 6078 * StringUtils.removeStart("path", 0) = "path" 6079 * </pre> 6080 * 6081 * @param str The source String to search, may be null. 6082 * @param remove The char to search for and remove. 6083 * @return The substring with the char removed if found, {@code null} if null String input. 6084 * @since 3.13.0 6085 */ 6086 public static String removeStart(final String str, final char remove) { 6087 if (isEmpty(str)) { 6088 return str; 6089 } 6090 return str.charAt(0) == remove ? str.substring(1) : str; 6091 } 6092 6093 /** 6094 * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string. 6095 * 6096 * <p> 6097 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 6098 * the source string. 6099 * </p> 6100 * 6101 * <pre> 6102 * StringUtils.removeStart(null, *) = null 6103 * StringUtils.removeStart("", *) = "" 6104 * StringUtils.removeStart(*, null) = * 6105 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 6106 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6107 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6108 * StringUtils.removeStart("abc", "") = "abc" 6109 * </pre> 6110 * 6111 * @param str The source String to search, may be null. 6112 * @param remove The String to search for and remove, may be null. 6113 * @return The substring with the string removed if found, {@code null} if null String input. 6114 * @since 2.1 6115 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}. 6116 */ 6117 @Deprecated 6118 public static String removeStart(final String str, final String remove) { 6119 return Strings.CS.removeStart(str, remove); 6120 } 6121 6122 /** 6123 * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string. 6124 * 6125 * <p> 6126 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return 6127 * the source string. 6128 * </p> 6129 * 6130 * <pre> 6131 * StringUtils.removeStartIgnoreCase(null, *) = null 6132 * StringUtils.removeStartIgnoreCase("", *) = "" 6133 * StringUtils.removeStartIgnoreCase(*, null) = * 6134 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6135 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6136 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6137 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6138 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6139 * </pre> 6140 * 6141 * @param str The source String to search, may be null. 6142 * @param remove The String to search for (case-insensitive) and remove, may be null. 6143 * @return The substring with the string removed if found, {@code null} if null String input. 6144 * @since 2.4 6145 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}. 6146 */ 6147 @Deprecated 6148 public static String removeStartIgnoreCase(final String str, final String remove) { 6149 return Strings.CI.removeStart(str, remove); 6150 } 6151 6152 /** 6153 * Returns padding using the specified delimiter repeated to a given length. 6154 * 6155 * <pre> 6156 * StringUtils.repeat('e', 0) = "" 6157 * StringUtils.repeat('e', 3) = "eee" 6158 * StringUtils.repeat('e', -2) = "" 6159 * </pre> 6160 * 6161 * <p> 6162 * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6163 * as they require a pair of {@code char}s to be represented. If you are needing to support full I18N of your applications consider using 6164 * {@link #repeat(String, int)} instead. 6165 * </p> 6166 * 6167 * @param repeat character to repeat. 6168 * @param count number of times to repeat char, negative treated as zero. 6169 * @return String with repeated character. 6170 * @see #repeat(String, int) 6171 */ 6172 public static String repeat(final char repeat, final int count) { 6173 if (count <= 0) { 6174 return EMPTY; 6175 } 6176 return new String(ArrayFill.fill(new char[count], repeat)); 6177 } 6178 6179 /** 6180 * Repeats a String {@code repeat} times to form a new String. 6181 * 6182 * <pre> 6183 * StringUtils.repeat(null, 2) = null 6184 * StringUtils.repeat("", 0) = "" 6185 * StringUtils.repeat("", 2) = "" 6186 * StringUtils.repeat("a", 3) = "aaa" 6187 * StringUtils.repeat("ab", 2) = "abab" 6188 * StringUtils.repeat("a", -2) = "" 6189 * </pre> 6190 * 6191 * @param repeat The String to repeat, may be null. 6192 * @param count number of times to repeat str, negative treated as zero. 6193 * @return A new String consisting of the original String repeated, {@code null} if null String input. 6194 */ 6195 public static String repeat(final String repeat, final int count) { 6196 // Performance tuned for 2.0 (JDK1.4) 6197 if (repeat == null) { 6198 return null; 6199 } 6200 if (count <= 0) { 6201 return EMPTY; 6202 } 6203 final int inputLength = repeat.length(); 6204 if (count == 1 || inputLength == 0) { 6205 return repeat; 6206 } 6207 if (inputLength == 1 && count <= PAD_LIMIT) { 6208 return repeat(repeat.charAt(0), count); 6209 } 6210 final int outputLength; 6211 try { 6212 outputLength = Math.multiplyExact(inputLength, count); 6213 } catch (final Exception e) { 6214 throw new IllegalArgumentException("The requested result is too large for a String."); 6215 } 6216 switch (inputLength) { 6217 case 1: 6218 return repeat(repeat.charAt(0), count); 6219 case 2: 6220 final char ch0 = repeat.charAt(0); 6221 final char ch1 = repeat.charAt(1); 6222 final char[] output2 = new char[outputLength]; 6223 for (int i = count * 2 - 2; i >= 0; i--, i--) { 6224 output2[i] = ch0; 6225 output2[i + 1] = ch1; 6226 } 6227 return new String(output2); 6228 default: 6229 final StringBuilder buf = new StringBuilder(outputLength); 6230 for (int i = 0; i < count; i++) { 6231 buf.append(repeat); 6232 } 6233 return buf.toString(); 6234 } 6235 } 6236 6237 /** 6238 * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time. 6239 * 6240 * <pre> 6241 * StringUtils.repeat(null, null, 2) = null 6242 * StringUtils.repeat(null, "x", 2) = null 6243 * StringUtils.repeat("", null, 0) = "" 6244 * StringUtils.repeat("", "", 2) = "" 6245 * StringUtils.repeat("", "x", 3) = "xx" 6246 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6247 * </pre> 6248 * 6249 * @param repeat The String to repeat, may be null. 6250 * @param separator The String to inject, may be null. 6251 * @param count number of times to repeat str, negative treated as zero. 6252 * @return A new String consisting of the original String repeated, {@code null} if null String input. 6253 * @since 2.5 6254 */ 6255 public static String repeat(final String repeat, final String separator, final int count) { 6256 if (repeat == null || separator == null) { 6257 return repeat(repeat, count); 6258 } 6259 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6260 final String result = repeat(repeat + separator, count); 6261 return Strings.CS.removeEnd(result, separator); 6262 } 6263 6264 /** 6265 * Replaces all occurrences of a String within another String. 6266 * 6267 * <p> 6268 * A {@code null} reference passed to this method is a no-op. 6269 * </p> 6270 * 6271 * <pre> 6272 * StringUtils.replace(null, *, *) = null 6273 * StringUtils.replace("", *, *) = "" 6274 * StringUtils.replace("any", null, *) = "any" 6275 * StringUtils.replace("any", *, null) = "any" 6276 * StringUtils.replace("any", "", *) = "any" 6277 * StringUtils.replace("aba", "a", null) = "aba" 6278 * StringUtils.replace("aba", "a", "") = "b" 6279 * StringUtils.replace("aba", "a", "z") = "zbz" 6280 * </pre> 6281 * 6282 * @param text text to search and replace in, may be null. 6283 * @param searchString The String to search for, may be null. 6284 * @param replacement The String to replace it with, may be null. 6285 * @return The text with any replacements processed, {@code null} if null String input. 6286 * @see #replace(String text, String searchString, String replacement, int max) 6287 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}. 6288 */ 6289 @Deprecated 6290 public static String replace(final String text, final String searchString, final String replacement) { 6291 return Strings.CS.replace(text, searchString, replacement); 6292 } 6293 6294 /** 6295 * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6296 * 6297 * <p> 6298 * A {@code null} reference passed to this method is a no-op. 6299 * </p> 6300 * 6301 * <pre> 6302 * StringUtils.replace(null, *, *, *) = null 6303 * StringUtils.replace("", *, *, *) = "" 6304 * StringUtils.replace("any", null, *, *) = "any" 6305 * StringUtils.replace("any", *, null, *) = "any" 6306 * StringUtils.replace("any", "", *, *) = "any" 6307 * StringUtils.replace("any", *, *, 0) = "any" 6308 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6309 * StringUtils.replace("abaa", "a", "", -1) = "b" 6310 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6311 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6312 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6313 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6314 * </pre> 6315 * 6316 * @param text text to search and replace in, may be null. 6317 * @param searchString The String to search for, may be null. 6318 * @param replacement The String to replace it with, may be null. 6319 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6320 * @return The text with any replacements processed, {@code null} if null String input. 6321 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}. 6322 */ 6323 @Deprecated 6324 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6325 return Strings.CS.replace(text, searchString, replacement, max); 6326 } 6327 6328 /** 6329 * Replaces each substring of the text String that matches the given regular expression with the given replacement. 6330 * 6331 * This method is a {@code null} safe equivalent to: 6332 * <ul> 6333 * <li>{@code text.replaceAll(regex, replacement)}</li> 6334 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6335 * </ul> 6336 * 6337 * <p> 6338 * A {@code null} reference passed to this method is a no-op. 6339 * </p> 6340 * 6341 * <p> 6342 * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL 6343 * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 6344 * </p> 6345 * 6346 * <pre>{@code 6347 * StringUtils.replaceAll(null, *, *) = null 6348 * StringUtils.replaceAll("any", (String) null, *) = "any" 6349 * StringUtils.replaceAll("any", *, null) = "any" 6350 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6351 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6352 * StringUtils.replaceAll("", ".+", "zzz") = "" 6353 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6354 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6355 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6356 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6357 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6358 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6359 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6360 * }</pre> 6361 * 6362 * @param text text to search and replace in, may be null. 6363 * @param regex The regular expression to which this string is to be matched. 6364 * @param replacement The string to be substituted for each match. 6365 * @return The text with any replacements processed, {@code null} if null String input. 6366 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 6367 * @see #replacePattern(String, String, String) 6368 * @see String#replaceAll(String, String) 6369 * @see java.util.regex.Pattern 6370 * @see java.util.regex.Pattern#DOTALL 6371 * @since 3.5 6372 * @deprecated Use {@link RegExUtils#replaceAll(String, String, String)}. 6373 */ 6374 @Deprecated 6375 public static String replaceAll(final String text, final String regex, final String replacement) { 6376 return RegExUtils.replaceAll(text, regex, replacement); 6377 } 6378 6379 /** 6380 * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}. 6381 * 6382 * <p> 6383 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. 6384 * </p> 6385 * 6386 * <pre> 6387 * StringUtils.replaceChars(null, *, *) = null 6388 * StringUtils.replaceChars("", *, *) = "" 6389 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6390 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6391 * </pre> 6392 * 6393 * @param str String to replace characters in, may be null. 6394 * @param searchChar The character to search for, may be null. 6395 * @param replaceChar The character to replace, may be null. 6396 * @return modified String, {@code null} if null string input. 6397 * @since 2.0 6398 */ 6399 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6400 if (str == null) { 6401 return null; 6402 } 6403 return str.replace(searchChar, replaceChar); 6404 } 6405 6406 /** 6407 * Replaces multiple characters in a String in one go. This method can also be used to delete characters. 6408 * 6409 * <p> 6410 * For example: 6411 * </p> 6412 * <pre> 6413 * replaceChars("hello", "ho", "jy") = jelly. 6414 * </pre> 6415 * 6416 * <p> 6417 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. A null or empty set of search characters returns 6418 * the input string. 6419 * </p> 6420 * 6421 * <p> 6422 * The length of the search characters should normally equal the length of the replace characters. If the search characters is longer, then the extra search 6423 * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored. 6424 * </p> 6425 * 6426 * <pre> 6427 * StringUtils.replaceChars(null, *, *) = null 6428 * StringUtils.replaceChars("", *, *) = "" 6429 * StringUtils.replaceChars("abc", null, *) = "abc" 6430 * StringUtils.replaceChars("abc", "", *) = "abc" 6431 * StringUtils.replaceChars("abc", "b", null) = "ac" 6432 * StringUtils.replaceChars("abc", "b", "") = "ac" 6433 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6434 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6435 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6436 * </pre> 6437 * 6438 * @param str String to replace characters in, may be null. 6439 * @param searchChars A set of characters to search for, may be null. 6440 * @param replaceChars A set of characters to replace, may be null. 6441 * @return modified String, {@code null} if null string input. 6442 * @since 2.0 6443 */ 6444 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6445 if (isEmpty(str) || isEmpty(searchChars)) { 6446 return str; 6447 } 6448 replaceChars = ObjectUtils.toString(replaceChars); 6449 boolean modified = false; 6450 final int replaceCharsLength = replaceChars.length(); 6451 final int strLength = str.length(); 6452 final StringBuilder buf = new StringBuilder(strLength); 6453 for (int i = 0; i < strLength; i++) { 6454 final char ch = str.charAt(i); 6455 final int index = searchChars.indexOf(ch); 6456 if (index >= 0) { 6457 modified = true; 6458 if (index < replaceCharsLength) { 6459 buf.append(replaceChars.charAt(index)); 6460 } 6461 } else { 6462 buf.append(ch); 6463 } 6464 } 6465 if (modified) { 6466 return buf.toString(); 6467 } 6468 return str; 6469 } 6470 6471 /** 6472 * Replaces all occurrences of Strings within another String. 6473 * 6474 * <p> 6475 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. This 6476 * will not repeat. For repeating replaces, call the overloaded method. 6477 * </p> 6478 * 6479 * <pre> 6480 * StringUtils.replaceEach(null, *, *) = null 6481 * StringUtils.replaceEach("", *, *) = "" 6482 * StringUtils.replaceEach("aba", null, null) = "aba" 6483 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6484 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6485 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6486 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6487 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6488 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6489 * (example of how it does not repeat) 6490 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6491 * </pre> 6492 * 6493 * @param text text to search and replace in, no-op if null. 6494 * @param searchList The Strings to search for, no-op if null. 6495 * @param replacementList The Strings to replace them with, no-op if null. 6496 * @return The text with any replacements processed, {@code null} if null String input. 6497 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6498 * @since 2.4 6499 */ 6500 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6501 return replaceEachOnce(text, searchList, replacementList); 6502 } 6503 6504 /** 6505 * Replace all occurrences of Strings within another String, in a single pass. This is a private helper method for 6506 * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])} 6507 * 6508 * <p> 6509 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. 6510 * </p> 6511 * 6512 * <pre> 6513 * StringUtils.replaceEachOnce(null, *, *) = null 6514 * StringUtils.replaceEachOnce("", *, *) = "" 6515 * StringUtils.replaceEachOnce("aba", null, null) = "aba" 6516 * StringUtils.replaceEachOnce("aba", new String[0], null) = "aba" 6517 * StringUtils.replaceEachOnce("aba", null, new String[0]) = "aba" 6518 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, null) = "aba" 6519 * StringUtils.replaceEachOnce("aba", new String[]{"a"}, new String[]{""}) = "b" 6520 * StringUtils.replaceEachOnce("aba", new String[]{null}, new String[]{"a"}) = "aba" 6521 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6522 * StringUtils.replaceEachOnce("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6523 * </pre> 6524 * 6525 * <p> 6526 * When no replacement is performed, the {@code text} argument is returned unchanged (same reference); callers rely on this to detect convergence. 6527 * </p> 6528 * 6529 * @param text text to search and replace in, no-op if null. 6530 * @param searchList The Strings to search for, no-op if null. 6531 * @param replacementList The Strings to replace them with, no-op if null. 6532 * @return The text with any replacements processed, {@code null} if null String input. 6533 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6534 * @since 2.4 6535 */ 6536 private static String replaceEachOnce(final String text, final String[] searchList, final String[] replacementList) { 6537 6538 // Performance note: This creates very few new objects (one major goal) 6539 // let me know if there are performance requests, we can create a harness to measure 6540 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) { 6541 return text; 6542 } 6543 6544 final int searchLength = searchList.length; 6545 final int replacementLength = replacementList.length; 6546 6547 // make sure lengths are ok, these need to be equal 6548 if (searchLength != replacementLength) { 6549 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6550 + searchLength 6551 + " vs " 6552 + replacementLength); 6553 } 6554 6555 // keep track of which still have matches 6556 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6557 6558 // index on index that the match was found 6559 int textIndex = -1; 6560 int replaceIndex = -1; 6561 int tempIndex; 6562 6563 // index of replace array that will replace the search string found 6564 // NOTE: logic duplicated below START 6565 for (int i = 0; i < searchLength; i++) { 6566 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6567 continue; 6568 } 6569 tempIndex = text.indexOf(searchList[i]); 6570 6571 // see if we need to keep searching for this 6572 if (tempIndex == -1) { 6573 noMoreMatchesForReplIndex[i] = true; 6574 } else if (textIndex == -1 || tempIndex < textIndex) { 6575 textIndex = tempIndex; 6576 replaceIndex = i; 6577 } 6578 } 6579 // NOTE: logic mostly below END 6580 6581 // no search strings found, we are done 6582 if (textIndex == -1) { 6583 return text; 6584 } 6585 6586 int start = 0; 6587 6588 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6589 int increase = 0; 6590 6591 // count the replacement text elements that are larger than their corresponding text being replaced 6592 for (int i = 0; i < searchList.length; i++) { 6593 if (searchList[i] == null || replacementList[i] == null) { 6594 continue; 6595 } 6596 final int greater = replacementList[i].length() - searchList[i].length(); 6597 if (greater > 0) { 6598 increase += 3 * greater; // assume 3 matches 6599 } 6600 } 6601 // have upper-bound at 20% increase, then let Java take over 6602 increase = Math.min(increase, text.length() / 5); 6603 6604 final StringBuilder buf = new StringBuilder(text.length() + increase); 6605 6606 while (textIndex != -1) { 6607 6608 for (int i = start; i < textIndex; i++) { 6609 buf.append(text.charAt(i)); 6610 } 6611 buf.append(replacementList[replaceIndex]); 6612 6613 start = textIndex + searchList[replaceIndex].length(); 6614 6615 textIndex = -1; 6616 replaceIndex = -1; 6617 // find the next earliest match 6618 // NOTE: logic mostly duplicated above START 6619 for (int i = 0; i < searchLength; i++) { 6620 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6621 continue; 6622 } 6623 tempIndex = text.indexOf(searchList[i], start); 6624 6625 // see if we need to keep searching for this 6626 if (tempIndex == -1) { 6627 noMoreMatchesForReplIndex[i] = true; 6628 } else if (textIndex == -1 || tempIndex < textIndex) { 6629 textIndex = tempIndex; 6630 replaceIndex = i; 6631 } 6632 } 6633 // NOTE: logic duplicated above END 6634 6635 } 6636 final int textLength = text.length(); 6637 for (int i = start; i < textLength; i++) { 6638 buf.append(text.charAt(i)); 6639 } 6640 return buf.toString(); 6641 } 6642 6643 /** 6644 * Replaces all occurrences of Strings within another String. 6645 * 6646 * <p> 6647 * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. 6648 * </p> 6649 * 6650 * <pre> 6651 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6652 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6653 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6654 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6655 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6656 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6657 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6658 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6659 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6660 * (example of how it repeats) 6661 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6662 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = Throws {@link IllegalStateException} 6663 * </pre> 6664 * 6665 * @param text text to search and replace in, no-op if null. 6666 * @param searchList The Strings to search for, no-op if null. 6667 * @param replacementList The Strings to replace them with, no-op if null. 6668 * @return The text with any replacements processed, {@code null} if null String input. 6669 * @throws IllegalStateException Thrown if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6670 * @throws IllegalArgumentException Thrown if the lengths of the arrays are not the same (null is ok, and/or size 0). 6671 * @since 2.4 6672 */ 6673 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6674 // The iteration budget is a fixed constant, deliberately independent of the caller-supplied 6675 // searchList length: deriving the budget from the input would let the input size choose the 6676 // recursion depth/amplification (formerly a real StackOverflowError on large search lists). 6677 String result = text; 6678 for (int timeToLive = DEFAULT_TTL; timeToLive >= 0; timeToLive--) { 6679 final String next = replaceEachOnce(result, searchList, replacementList); 6680 if (next == result) { 6681 // No replacement was performed; converged. 6682 return result; 6683 } 6684 result = next; 6685 } 6686 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6687 "output of one loop is the input of another"); 6688 } 6689 6690 /** 6691 * Replaces the first substring of the text string that matches the given regular expression with the given replacement. 6692 * 6693 * This method is a {@code null} safe equivalent to: 6694 * <ul> 6695 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6696 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6697 * </ul> 6698 * 6699 * <p> 6700 * A {@code null} reference passed to this method is a no-op. 6701 * </p> 6702 * 6703 * <p> 6704 * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as 6705 * single-line mode in Perl. 6706 * </p> 6707 * 6708 * <pre>{@code 6709 * StringUtils.replaceFirst(null, *, *) = null 6710 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6711 * StringUtils.replaceFirst("any", *, null) = "any" 6712 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6713 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6714 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6715 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6716 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6717 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6718 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6719 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6720 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6721 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6722 * }</pre> 6723 * 6724 * @param text text to search and replace in, may be null. 6725 * @param regex The regular expression to which this string is to be matched. 6726 * @param replacement The string to be substituted for the first match. 6727 * @return The text with the first replacement processed, {@code null} if null String input. 6728 * @throws java.util.regex.PatternSyntaxException Thrown if the regular expression's syntax is invalid. 6729 * @see String#replaceFirst(String, String) 6730 * @see java.util.regex.Pattern 6731 * @see java.util.regex.Pattern#DOTALL 6732 * @since 3.5 6733 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String)}. 6734 */ 6735 @Deprecated 6736 public static String replaceFirst(final String text, final String regex, final String replacement) { 6737 return RegExUtils.replaceFirst(text, regex, replacement); 6738 } 6739 6740 /** 6741 * Case insensitively replaces all occurrences of a String within another String. 6742 * 6743 * <p> 6744 * A {@code null} reference passed to this method is a no-op. 6745 * </p> 6746 * 6747 * <pre> 6748 * StringUtils.replaceIgnoreCase(null, *, *) = null 6749 * StringUtils.replaceIgnoreCase("", *, *) = "" 6750 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6751 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6752 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6753 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6754 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6755 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6756 * </pre> 6757 * 6758 * @param text text to search and replace in, may be null. 6759 * @param searchString The String to search for (case-insensitive), may be null. 6760 * @param replacement The String to replace it with, may be null. 6761 * @return The text with any replacements processed, {@code null} if null String input. 6762 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6763 * @since 3.5 6764 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}. 6765 */ 6766 @Deprecated 6767 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6768 return Strings.CI.replace(text, searchString, replacement); 6769 } 6770 6771 /** 6772 * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6773 * 6774 * <p> 6775 * A {@code null} reference passed to this method is a no-op. 6776 * </p> 6777 * 6778 * <pre> 6779 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6780 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6781 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6782 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6783 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6784 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6785 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6786 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6787 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6788 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6789 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6790 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6791 * </pre> 6792 * 6793 * @param text text to search and replace in, may be null. 6794 * @param searchString The String to search for (case-insensitive), may be null. 6795 * @param replacement The String to replace it with, may be null. 6796 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6797 * @return The text with any replacements processed, {@code null} if null String input. 6798 * @since 3.5 6799 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}. 6800 */ 6801 @Deprecated 6802 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6803 return Strings.CI.replace(text, searchString, replacement, max); 6804 } 6805 6806 /** 6807 * Replaces a String with another String inside a larger String, once. 6808 * 6809 * <p> 6810 * A {@code null} reference passed to this method is a no-op. 6811 * </p> 6812 * 6813 * <pre> 6814 * StringUtils.replaceOnce(null, *, *) = null 6815 * StringUtils.replaceOnce("", *, *) = "" 6816 * StringUtils.replaceOnce("any", null, *) = "any" 6817 * StringUtils.replaceOnce("any", *, null) = "any" 6818 * StringUtils.replaceOnce("any", "", *) = "any" 6819 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6820 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6821 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6822 * </pre> 6823 * 6824 * @param text text to search and replace in, may be null. 6825 * @param searchString The String to search for, may be null. 6826 * @param replacement The String to replace with, may be null. 6827 * @return The text with any replacements processed, {@code null} if null String input. 6828 * @see #replace(String text, String searchString, String replacement, int max) 6829 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}. 6830 */ 6831 @Deprecated 6832 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6833 return Strings.CS.replaceOnce(text, searchString, replacement); 6834 } 6835 6836 /** 6837 * Case insensitively replaces a String with another String inside a larger String, once. 6838 * 6839 * <p> 6840 * A {@code null} reference passed to this method is a no-op. 6841 * </p> 6842 * 6843 * <pre> 6844 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6845 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6846 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6847 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6848 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6849 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6850 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6851 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6852 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6853 * </pre> 6854 * 6855 * @param text text to search and replace in, may be null. 6856 * @param searchString The String to search for (case-insensitive), may be null. 6857 * @param replacement The String to replace with, may be null. 6858 * @return The text with any replacements processed, {@code null} if null String input. 6859 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6860 * @since 3.5 6861 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}. 6862 */ 6863 @Deprecated 6864 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6865 return Strings.CI.replaceOnce(text, searchString, replacement); 6866 } 6867 6868 /** 6869 * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL} 6870 * option. DOTALL is also known as single-line mode in Perl. 6871 * 6872 * This call is a {@code null} safe equivalent to: 6873 * <ul> 6874 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6875 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6876 * </ul> 6877 * 6878 * <p> 6879 * A {@code null} reference passed to this method is a no-op. 6880 * </p> 6881 * 6882 * <pre>{@code 6883 * StringUtils.replacePattern(null, *, *) = null 6884 * StringUtils.replacePattern("any", (String) null, *) = "any" 6885 * StringUtils.replacePattern("any", *, null) = "any" 6886 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6887 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6888 * StringUtils.replacePattern("", ".+", "zzz") = "" 6889 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6890 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6891 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6892 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6893 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6894 * }</pre> 6895 * 6896 * @param source The source string. 6897 * @param regex The regular expression to which this string is to be matched. 6898 * @param replacement The string to be substituted for each match. 6899 * @return The resulting {@link String}. 6900 * @see #replaceAll(String, String, String) 6901 * @see String#replaceAll(String, String) 6902 * @see Pattern#DOTALL 6903 * @since 3.2 6904 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6905 * @deprecated Use {@link RegExUtils#replacePattern(CharSequence, String, String)}. 6906 */ 6907 @Deprecated 6908 public static String replacePattern(final String source, final String regex, final String replacement) { 6909 return RegExUtils.replacePattern(source, regex, replacement); 6910 } 6911 6912 /** 6913 * Reverses a String as per {@link StringBuilder#reverse()}. 6914 * 6915 * <p> 6916 * A {@code null} String returns {@code null}. 6917 * </p> 6918 * 6919 * <pre> 6920 * StringUtils.reverse(null) = null 6921 * StringUtils.reverse("") = "" 6922 * StringUtils.reverse("bat") = "tab" 6923 * </pre> 6924 * 6925 * @param str The String to reverse, may be null. 6926 * @return The reversed String, {@code null} if null String input. 6927 */ 6928 public static String reverse(final String str) { 6929 if (str == null) { 6930 return null; 6931 } 6932 return new StringBuilder(str).reverse().toString(); 6933 } 6934 6935 /** 6936 * Reverses a String that is delimited by a specific character. 6937 * 6938 * <p> 6939 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}). 6940 * </p> 6941 * 6942 * <pre> 6943 * StringUtils.reverseDelimited(null, *) = null 6944 * StringUtils.reverseDelimited("", *) = "" 6945 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 6946 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 6947 * </pre> 6948 * 6949 * @param str The String to reverse, may be null. 6950 * @param separatorChar The separator character to use. 6951 * @return The reversed String, {@code null} if null String input. 6952 * @since 2.0 6953 */ 6954 public static String reverseDelimited(final String str, final char separatorChar) { 6955 final String[] strs = split(str, separatorChar); 6956 ArrayUtils.reverse(strs); 6957 return join(strs, separatorChar); 6958 } 6959 6960 /** 6961 * Gets the rightmost {@code len} characters of a String. 6962 * 6963 * <p> 6964 * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is 6965 * returned if len is negative. 6966 * </p> 6967 * 6968 * <pre> 6969 * StringUtils.right(null, *) = null 6970 * StringUtils.right(*, -ve) = "" 6971 * StringUtils.right("", *) = "" 6972 * StringUtils.right("abc", 0) = "" 6973 * StringUtils.right("abc", 2) = "bc" 6974 * StringUtils.right("abc", 4) = "abc" 6975 * </pre> 6976 * 6977 * @param str The String to get the rightmost characters from, may be null. 6978 * @param len The length of the required String. 6979 * @return The rightmost characters, {@code null} if null String input. 6980 */ 6981 public static String right(final String str, final int len) { 6982 if (str == null) { 6983 return null; 6984 } 6985 if (len < 0) { 6986 return EMPTY; 6987 } 6988 if (str.length() <= len) { 6989 return str; 6990 } 6991 int start = str.length() - len; 6992 // keep the cut off the middle of a surrogate pair so the result is never left holding a lone surrogate 6993 if (splitsSurrogatePair(str, start)) { 6994 start++; 6995 } 6996 return str.substring(start); 6997 } 6998 6999 /** 7000 * Right pad a String with spaces (' '). 7001 * 7002 * <p> 7003 * The String is padded to the size of {@code size}. 7004 * </p> 7005 * 7006 * <pre> 7007 * StringUtils.rightPad(null, *) = null 7008 * StringUtils.rightPad("", 3) = " " 7009 * StringUtils.rightPad("bat", 3) = "bat" 7010 * StringUtils.rightPad("bat", 5) = "bat " 7011 * StringUtils.rightPad("bat", 1) = "bat" 7012 * StringUtils.rightPad("bat", -1) = "bat" 7013 * </pre> 7014 * 7015 * @param str The String to pad out, may be null. 7016 * @param size The size to pad to. 7017 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7018 */ 7019 public static String rightPad(final String str, final int size) { 7020 return rightPad(str, size, ' '); 7021 } 7022 7023 /** 7024 * Right pad a String with a specified character. 7025 * 7026 * <p> 7027 * The String is padded to the size of {@code size}. 7028 * </p> 7029 * 7030 * <pre> 7031 * StringUtils.rightPad(null, *, *) = null 7032 * StringUtils.rightPad("", 3, 'z') = "zzz" 7033 * StringUtils.rightPad("bat", 3, 'z') = "bat" 7034 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 7035 * StringUtils.rightPad("bat", 1, 'z') = "bat" 7036 * StringUtils.rightPad("bat", -1, 'z') = "bat" 7037 * </pre> 7038 * 7039 * @param str The String to pad out, may be null. 7040 * @param size The size to pad to. 7041 * @param padChar The character to pad with. 7042 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7043 * @since 2.0 7044 */ 7045 public static String rightPad(final String str, final int size, final char padChar) { 7046 if (str == null || size <= str.length()) { 7047 return str; 7048 } 7049 final int pads = size - str.length(); 7050 if (pads <= 0) { 7051 return str; // returns original String when possible 7052 } 7053 if (pads > PAD_LIMIT) { 7054 return rightPad(str, size, String.valueOf(padChar)); 7055 } 7056 return str.concat(repeat(padChar, pads)); 7057 } 7058 7059 /** 7060 * Right pad a String with a specified String. 7061 * 7062 * <p> 7063 * The String is padded to the size of {@code size}. 7064 * </p> 7065 * 7066 * <pre> 7067 * StringUtils.rightPad(null, *, *) = null 7068 * StringUtils.rightPad("", 3, "z") = "zzz" 7069 * StringUtils.rightPad("bat", 3, "yz") = "bat" 7070 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 7071 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 7072 * StringUtils.rightPad("bat", 1, "yz") = "bat" 7073 * StringUtils.rightPad("bat", -1, "yz") = "bat" 7074 * StringUtils.rightPad("bat", 5, null) = "bat " 7075 * StringUtils.rightPad("bat", 5, "") = "bat " 7076 * </pre> 7077 * 7078 * @param str The String to pad out, may be null. 7079 * @param size The size to pad to. 7080 * @param padStr The String to pad with, null or empty treated as single space. 7081 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 7082 */ 7083 public static String rightPad(final String str, final int size, String padStr) { 7084 if (str == null || size <= str.length()) { 7085 return str; 7086 } 7087 if (isEmpty(padStr)) { 7088 padStr = SPACE; 7089 } 7090 final int padLen = padStr.length(); 7091 final int strLen = str.length(); 7092 final int pads = size - strLen; 7093 if (pads <= 0) { 7094 return str; // returns original String when possible 7095 } 7096 if (padLen == 1 && pads <= PAD_LIMIT) { 7097 return rightPad(str, size, padStr.charAt(0)); 7098 } 7099 if (pads == padLen) { 7100 return str.concat(padStr); 7101 } 7102 if (pads < padLen) { 7103 return str.concat(padStr.substring(0, pads)); 7104 } 7105 final char[] padding = new char[pads]; 7106 final char[] padChars = padStr.toCharArray(); 7107 for (int i = 0; i < pads; i++) { 7108 padding[i] = padChars[i % padLen]; 7109 } 7110 return str.concat(new String(padding)); 7111 } 7112 7113 /** 7114 * Rotate (circular shift) a String of {@code shift} characters. 7115 * <ul> 7116 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7117 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7118 * </ul> 7119 * 7120 * <pre> 7121 * StringUtils.rotate(null, *) = null 7122 * StringUtils.rotate("", *) = "" 7123 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7124 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7125 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7126 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7127 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7128 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7129 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7130 * </pre> 7131 * 7132 * @param str The String to rotate, may be null. 7133 * @param shift number of time to shift (positive : right shift, negative : left shift). 7134 * @return The rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input. 7135 * @since 3.5 7136 */ 7137 public static String rotate(final String str, final int shift) { 7138 if (str == null) { 7139 return null; 7140 } 7141 final int strLen = str.length(); 7142 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7143 return str; 7144 } 7145 final StringBuilder builder = new StringBuilder(strLen); 7146 final int offset = -(shift % strLen); 7147 builder.append(substring(str, offset)); 7148 builder.append(substring(str, 0, offset)); 7149 return builder.toString(); 7150 } 7151 7152 /** 7153 * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 7154 * 7155 * <p> 7156 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7157 * StrTokenizer class. 7158 * </p> 7159 * 7160 * <p> 7161 * A {@code null} input String returns {@code null}. 7162 * </p> 7163 * 7164 * <pre> 7165 * StringUtils.split(null) = null 7166 * StringUtils.split("") = [] 7167 * StringUtils.split("abc def") = ["abc", "def"] 7168 * StringUtils.split("abc def") = ["abc", "def"] 7169 * StringUtils.split(" abc ") = ["abc"] 7170 * </pre> 7171 * 7172 * @param str The String to parse, may be null. 7173 * @return An array of parsed Strings, {@code null} if null String input. 7174 */ 7175 public static String[] split(final String str) { 7176 return split(str, null, -1); 7177 } 7178 7179 /** 7180 * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer. 7181 * 7182 * <p> 7183 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7184 * StrTokenizer class. 7185 * </p> 7186 * 7187 * <p> 7188 * A {@code null} input String returns {@code null}. 7189 * </p> 7190 * 7191 * <pre> 7192 * StringUtils.split(null, *) = null 7193 * StringUtils.split("", *) = [] 7194 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7195 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7196 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7197 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7198 * </pre> 7199 * 7200 * @param str The String to parse, may be null. 7201 * @param separatorChar The character used as the delimiter. 7202 * @return An array of parsed Strings, {@code null} if null String input. 7203 * @since 2.0 7204 */ 7205 public static String[] split(final String str, final char separatorChar) { 7206 return splitWorker(str, separatorChar, false); 7207 } 7208 7209 /** 7210 * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer. 7211 * 7212 * <p> 7213 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the 7214 * StrTokenizer class. 7215 * </p> 7216 * 7217 * <p> 7218 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7219 * </p> 7220 * 7221 * <pre> 7222 * StringUtils.split(null, *) = null 7223 * StringUtils.split("", *) = [] 7224 * StringUtils.split("abc def", null) = ["abc", "def"] 7225 * StringUtils.split("abc def", " ") = ["abc", "def"] 7226 * StringUtils.split("abc def", " ") = ["abc", "def"] 7227 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7228 * </pre> 7229 * 7230 * @param str The String to parse, may be null. 7231 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7232 * @return An array of parsed Strings, {@code null} if null String input. 7233 */ 7234 public static String[] split(final String str, final String separatorChars) { 7235 return splitWorker(str, separatorChars, -1, false); 7236 } 7237 7238 /** 7239 * Splits the provided text into an array with a maximum length, separators specified. 7240 * 7241 * <p> 7242 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. 7243 * </p> 7244 * 7245 * <p> 7246 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7247 * </p> 7248 * 7249 * <p> 7250 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7251 * strings (including separator characters). 7252 * </p> 7253 * 7254 * <pre> 7255 * StringUtils.split(null, *, *) = null 7256 * StringUtils.split("", *, *) = [] 7257 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7258 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7259 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7260 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7261 * </pre> 7262 * 7263 * @param str The String to parse, may be null. 7264 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7265 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7266 * @return An array of parsed Strings, {@code null} if null String input. 7267 */ 7268 public static String[] split(final String str, final String separatorChars, final int max) { 7269 return splitWorker(str, separatorChars, max, false); 7270 } 7271 7272 /** 7273 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned 7274 * as complete tokens. 7275 * 7276 * <pre> 7277 * StringUtils.splitByCharacterType(null) = null 7278 * StringUtils.splitByCharacterType("") = [] 7279 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7280 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7281 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7282 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7283 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7284 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7285 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7286 * </pre> 7287 * 7288 * @param str The String to split, may be {@code null}. 7289 * @return An array of parsed Strings, {@code null} if null String input. 7290 * @see Character#getType(int) 7291 * @since 2.4 7292 */ 7293 public static String[] splitByCharacterType(final String str) { 7294 return splitByCharacterType(str, false); 7295 } 7296 7297 /** 7298 * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned 7299 * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@link Character#UPPERCASE_LETTER}, if any, 7300 * immediately preceding a token of type {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, 7301 * {@link Character#UPPERCASE_LETTER} token. 7302 * 7303 * @param str The String to split, may be {@code null}. 7304 * @param camelCase whether to use so-called "camel-case" for letter types. 7305 * @return An array of parsed Strings, {@code null} if null String input. 7306 * @since 2.4 7307 */ 7308 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7309 if (str == null) { 7310 return null; 7311 } 7312 if (str.isEmpty()) { 7313 return ArrayUtils.EMPTY_STRING_ARRAY; 7314 } 7315 final char[] c = str.toCharArray(); 7316 final List<String> list = new ArrayList<>(); 7317 int tokenStart = 0; 7318 int currentType = Character.getType(Character.codePointAt(c, tokenStart)); 7319 for (int pos = tokenStart + Character.charCount(Character.codePointAt(c, tokenStart)); pos < c.length;) { 7320 final int codePoint = Character.codePointAt(c, pos); 7321 final int type = Character.getType(codePoint); 7322 final int count = Character.charCount(codePoint); 7323 if (type == currentType) { 7324 pos += count; 7325 continue; 7326 } 7327 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7328 final int newTokenStart = pos - Character.charCount(Character.codePointBefore(c, pos)); 7329 if (newTokenStart != tokenStart) { 7330 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7331 tokenStart = newTokenStart; 7332 } 7333 } else { 7334 list.add(new String(c, tokenStart, pos - tokenStart)); 7335 tokenStart = pos; 7336 } 7337 currentType = type; 7338 pos += count; 7339 } 7340 list.add(new String(c, tokenStart, c.length - tokenStart)); 7341 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7342 } 7343 7344 /** 7345 * Splits a String by Character type as returned by {@link Character#getType(int)}. Groups of contiguous characters of the same type are returned 7346 * as complete tokens, with the following exception: the character of type {@link Character#UPPERCASE_LETTER}, if any, immediately preceding a token of type 7347 * {@link Character#LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@link Character#UPPERCASE_LETTER} token. 7348 * 7349 * <pre> 7350 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7351 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7352 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7353 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7354 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7355 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7356 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7357 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7358 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7359 * </pre> 7360 * 7361 * @param str The String to split, may be {@code null}. 7362 * @return An array of parsed Strings, {@code null} if null String input. 7363 * @see Character#getType(int) 7364 * @since 2.4 7365 */ 7366 public static String[] splitByCharacterTypeCamelCase(final String str) { 7367 return splitByCharacterType(str, true); 7368 } 7369 7370 /** 7371 * Splits the provided text into an array, separator string specified. 7372 * 7373 * <p> 7374 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7375 * </p> 7376 * 7377 * <p> 7378 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7379 * </p> 7380 * 7381 * <pre> 7382 * StringUtils.splitByWholeSeparator(null, *) = null 7383 * StringUtils.splitByWholeSeparator("", *) = [] 7384 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7385 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7386 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7387 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7388 * </pre> 7389 * 7390 * @param str The String to parse, may be null. 7391 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7392 * @return An array of parsed Strings, {@code null} if null String was input. 7393 */ 7394 public static String[] splitByWholeSeparator(final String str, final String separator) { 7395 return splitByWholeSeparatorWorker(str, separator, -1, false); 7396 } 7397 7398 /** 7399 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7400 * 7401 * <p> 7402 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7403 * </p> 7404 * 7405 * <p> 7406 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7407 * </p> 7408 * 7409 * <pre> 7410 * StringUtils.splitByWholeSeparator(null, *, *) = null 7411 * StringUtils.splitByWholeSeparator("", *, *) = [] 7412 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7413 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7414 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7415 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7416 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7417 * </pre> 7418 * 7419 * @param str The String to parse, may be null. 7420 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7421 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7422 * @return An array of parsed Strings, {@code null} if null String was input. 7423 */ 7424 public static String[] splitByWholeSeparator(final String str, final String separator, final int max) { 7425 return splitByWholeSeparatorWorker(str, separator, max, false); 7426 } 7427 7428 /** 7429 * Splits the provided text into an array, separator string specified. 7430 * 7431 * <p> 7432 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7433 * split use the StrTokenizer class. 7434 * </p> 7435 * 7436 * <p> 7437 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7438 * </p> 7439 * 7440 * <pre> 7441 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7442 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7443 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7444 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7445 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7446 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7447 * </pre> 7448 * 7449 * @param str The String to parse, may be null. 7450 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7451 * @return An array of parsed Strings, {@code null} if null String was input. 7452 * @since 2.4 7453 */ 7454 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7455 return splitByWholeSeparatorWorker(str, separator, -1, true); 7456 } 7457 7458 /** 7459 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7460 * 7461 * <p> 7462 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7463 * split use the StrTokenizer class. 7464 * </p> 7465 * 7466 * <p> 7467 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7468 * </p> 7469 * 7470 * <pre> 7471 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7472 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7473 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7474 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7475 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7476 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7477 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7478 * </pre> 7479 * 7480 * @param str The String to parse, may be null. 7481 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7482 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7483 * @return An array of parsed Strings, {@code null} if null String was input. 7484 * @since 2.4 7485 */ 7486 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7487 return splitByWholeSeparatorWorker(str, separator, max, true); 7488 } 7489 7490 /** 7491 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7492 * 7493 * @param str The String to parse, may be {@code null}. 7494 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7495 * @param max The maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7496 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7497 * one separator. 7498 * @return An array of parsed Strings, {@code null} if null String input. 7499 * @since 2.4 7500 */ 7501 private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) { 7502 if (str == null) { 7503 return null; 7504 } 7505 final int len = str.length(); 7506 if (len == 0) { 7507 return ArrayUtils.EMPTY_STRING_ARRAY; 7508 } 7509 if (separator == null || EMPTY.equals(separator)) { 7510 // Split on whitespace. 7511 return splitWorker(str, null, max, preserveAllTokens); 7512 } 7513 final int separatorLength = separator.length(); 7514 final ArrayList<String> substrings = new ArrayList<>(); 7515 int numberOfSubstrings = 0; 7516 int beg = 0; 7517 int end = 0; 7518 while (end < len) { 7519 end = str.indexOf(separator, beg); 7520 if (end > -1) { 7521 if (end > beg) { 7522 numberOfSubstrings += 1; 7523 if (numberOfSubstrings == max) { 7524 end = len; 7525 substrings.add(str.substring(beg)); 7526 } else { 7527 // The following is OK, because String.substring( beg, end ) excludes 7528 // the character at the position 'end'. 7529 substrings.add(str.substring(beg, end)); 7530 // Set the starting point for the next search. 7531 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7532 // which is the right calculation: 7533 beg = end + separatorLength; 7534 } 7535 } else { 7536 // We found a consecutive occurrence of the separator, so skip it. 7537 if (preserveAllTokens) { 7538 numberOfSubstrings += 1; 7539 if (numberOfSubstrings == max) { 7540 end = len; 7541 substrings.add(str.substring(beg)); 7542 } else { 7543 substrings.add(EMPTY); 7544 } 7545 } 7546 beg = end + separatorLength; 7547 } 7548 } else { 7549 // String.substring( beg ) goes from 'beg' to the end of the String. 7550 // beg == len means the String ended on a separator, so the trailing 7551 // token is empty and must be dropped unless empty tokens are preserved. 7552 if (preserveAllTokens || beg < len) { 7553 substrings.add(str.substring(beg)); 7554 } 7555 end = len; 7556 } 7557 } 7558 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7559 } 7560 7561 /** 7562 * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators. 7563 * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}. 7564 * 7565 * <p> 7566 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7567 * split use the StrTokenizer class. 7568 * </p> 7569 * 7570 * <p> 7571 * A {@code null} input String returns {@code null}. 7572 * </p> 7573 * 7574 * <pre> 7575 * StringUtils.splitPreserveAllTokens(null) = null 7576 * StringUtils.splitPreserveAllTokens("") = [] 7577 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7578 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7579 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7580 * </pre> 7581 * 7582 * @param str The String to parse, may be {@code null}. 7583 * @return An array of parsed Strings, {@code null} if null String input. 7584 * @since 2.1 7585 */ 7586 public static String[] splitPreserveAllTokens(final String str) { 7587 return splitWorker(str, null, -1, true); 7588 } 7589 7590 /** 7591 * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7592 * alternative to using StringTokenizer. 7593 * 7594 * <p> 7595 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7596 * split use the StrTokenizer class. 7597 * </p> 7598 * 7599 * <p> 7600 * A {@code null} input String returns {@code null}. 7601 * </p> 7602 * 7603 * <pre> 7604 * StringUtils.splitPreserveAllTokens(null, *) = null 7605 * StringUtils.splitPreserveAllTokens("", *) = [] 7606 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7607 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7608 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7609 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7610 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7611 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7612 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7613 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "a", "b", "c"] 7614 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", "a", "b", "c"] 7615 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", "a", "b", "c", ""] 7616 * </pre> 7617 * 7618 * @param str The String to parse, may be {@code null}. 7619 * @param separatorChar The character used as the delimiter, {@code null} splits on whitespace. 7620 * @return An array of parsed Strings, {@code null} if null String input. 7621 * @since 2.1 7622 */ 7623 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7624 return splitWorker(str, separatorChar, true); 7625 } 7626 7627 /** 7628 * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7629 * alternative to using StringTokenizer. 7630 * 7631 * <p> 7632 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7633 * split use the StrTokenizer class. 7634 * </p> 7635 * 7636 * <p> 7637 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7638 * </p> 7639 * 7640 * <pre> 7641 * StringUtils.splitPreserveAllTokens(null, *) = null 7642 * StringUtils.splitPreserveAllTokens("", *) = [] 7643 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7644 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7645 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", "def"] 7646 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7647 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7648 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7649 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", "cd", "ef"] 7650 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", "cd", "ef"] 7651 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", "cd", "ef"] 7652 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", "cd", "ef", ""] 7653 * </pre> 7654 * 7655 * @param str The String to parse, may be {@code null}. 7656 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7657 * @return An array of parsed Strings, {@code null} if null String input. 7658 * @since 2.1 7659 */ 7660 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7661 return splitWorker(str, separatorChars, -1, true); 7662 } 7663 7664 /** 7665 * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent 7666 * separators. 7667 * 7668 * <p> 7669 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are 7670 * treated as one separator. 7671 * </p> 7672 * 7673 * <p> 7674 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7675 * </p> 7676 * 7677 * <p> 7678 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7679 * strings (including separator characters). 7680 * </p> 7681 * 7682 * <pre> 7683 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7684 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7685 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7686 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7687 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7688 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7689 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7690 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7691 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7692 * </pre> 7693 * 7694 * @param str The String to parse, may be {@code null}. 7695 * @param separatorChars The characters used as the delimiters, {@code null} splits on whitespace. 7696 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7697 * @return An array of parsed Strings, {@code null} if null String input. 7698 * @since 2.1 7699 */ 7700 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7701 return splitWorker(str, separatorChars, max, true); 7702 } 7703 7704 /** 7705 * Tests whether a {@link String#substring} boundary at {@code index} would fall between the two halves of a surrogate pair, that is the char before 7706 * {@code index} is a high surrogate and the char at {@code index} is its low surrogate. Slicing there leaves a lone surrogate in the result. 7707 * 7708 * @param str The String being sliced. 7709 * @param index A candidate substring boundary, in {@code char} units. 7710 * @return whether slicing at {@code index} would split a surrogate pair. 7711 */ 7712 private static boolean splitsSurrogatePair(final String str, final int index) { 7713 return index > 0 && index < str.length() && Character.isHighSurrogate(str.charAt(index - 1)) && Character.isLowSurrogate(str.charAt(index)); 7714 } 7715 7716 /** 7717 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length. 7718 * 7719 * @param str The String to parse, may be {@code null}. 7720 * @param separatorChar The separate character. 7721 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7722 * one separator. 7723 * @return An array of parsed Strings, {@code null} if null String input. 7724 */ 7725 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7726 // Performance tuned for 2.0 (JDK1.4) 7727 if (str == null) { 7728 return null; 7729 } 7730 final int len = str.length(); 7731 if (len == 0) { 7732 return ArrayUtils.EMPTY_STRING_ARRAY; 7733 } 7734 final List<String> list = new ArrayList<>(); 7735 int i = 0; 7736 int start = 0; 7737 boolean match = false; 7738 boolean lastMatch = false; 7739 while (i < len) { 7740 if (str.charAt(i) == separatorChar) { 7741 if (match || preserveAllTokens) { 7742 list.add(str.substring(start, i)); 7743 match = false; 7744 lastMatch = true; 7745 } 7746 start = ++i; 7747 continue; 7748 } 7749 lastMatch = false; 7750 match = true; 7751 i++; 7752 } 7753 if (match || preserveAllTokens && lastMatch) { 7754 list.add(str.substring(start, i)); 7755 } 7756 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7757 } 7758 7759 /** 7760 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length. 7761 * 7762 * @param str The String to parse, may be {@code null}. 7763 * @param separatorChars The separate character. 7764 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit. 7765 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7766 * one separator. 7767 * @return An array of parsed Strings, {@code null} if null String input. 7768 */ 7769 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7770 // Performance tuned for 2.0 (JDK1.4) 7771 // Direct code is quicker than StringTokenizer. 7772 // Also, StringTokenizer uses isSpace() not isWhitespace() 7773 if (str == null) { 7774 return null; 7775 } 7776 final int len = str.length(); 7777 if (len == 0) { 7778 return ArrayUtils.EMPTY_STRING_ARRAY; 7779 } 7780 final List<String> list = new ArrayList<>(); 7781 int sizePlus1 = 1; 7782 int i = 0; 7783 int start = 0; 7784 boolean match = false; 7785 boolean lastMatch = false; 7786 if (separatorChars == null) { 7787 // Null separator means use whitespace 7788 while (i < len) { 7789 if (Character.isWhitespace(str.charAt(i))) { 7790 if (match || preserveAllTokens) { 7791 lastMatch = true; 7792 if (sizePlus1++ == max) { 7793 i = len; 7794 lastMatch = false; 7795 } 7796 list.add(str.substring(start, i)); 7797 match = false; 7798 } 7799 start = ++i; 7800 continue; 7801 } 7802 lastMatch = false; 7803 match = true; 7804 i++; 7805 } 7806 } else if (separatorChars.length() == 1) { 7807 // Optimize 1 character case 7808 final char sep = separatorChars.charAt(0); 7809 while (i < len) { 7810 if (str.charAt(i) == sep) { 7811 if (match || preserveAllTokens) { 7812 lastMatch = true; 7813 if (sizePlus1++ == max) { 7814 i = len; 7815 lastMatch = false; 7816 } 7817 list.add(str.substring(start, i)); 7818 match = false; 7819 } 7820 start = ++i; 7821 continue; 7822 } 7823 lastMatch = false; 7824 match = true; 7825 i++; 7826 } 7827 } else { 7828 // standard case 7829 while (i < len) { 7830 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 7831 if (match || preserveAllTokens) { 7832 lastMatch = true; 7833 if (sizePlus1++ == max) { 7834 i = len; 7835 lastMatch = false; 7836 } 7837 list.add(str.substring(start, i)); 7838 match = false; 7839 } 7840 start = ++i; 7841 continue; 7842 } 7843 lastMatch = false; 7844 match = true; 7845 i++; 7846 } 7847 } 7848 if (match || preserveAllTokens && lastMatch) { 7849 list.add(str.substring(start, i)); 7850 } 7851 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7852 } 7853 7854 /** 7855 * Tests if a CharSequence starts with a specified prefix. 7856 * 7857 * <p> 7858 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 7859 * </p> 7860 * 7861 * <pre> 7862 * StringUtils.startsWith(null, null) = true 7863 * StringUtils.startsWith(null, "abc") = false 7864 * StringUtils.startsWith("abcdef", null) = false 7865 * StringUtils.startsWith("abcdef", "abc") = true 7866 * StringUtils.startsWith("ABCDEF", "abc") = false 7867 * </pre> 7868 * 7869 * @param str The CharSequence to check, may be null. 7870 * @param prefix The prefix to find, may be null. 7871 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}. 7872 * @see String#startsWith(String) 7873 * @since 2.4 7874 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 7875 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}. 7876 */ 7877 @Deprecated 7878 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7879 return Strings.CS.startsWith(str, prefix); 7880 } 7881 7882 /** 7883 * Tests if a CharSequence starts with any of the provided case-sensitive prefixes. 7884 * 7885 * <pre> 7886 * StringUtils.startsWithAny(null, null) = false 7887 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 7888 * StringUtils.startsWithAny("abcxyz", null) = false 7889 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 7890 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 7891 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7892 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 7893 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 7894 * </pre> 7895 * 7896 * @param sequence The CharSequence to check, may be null. 7897 * @param searchStrings The case-sensitive CharSequence prefixes, may be empty or contain {@code null}. 7898 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with 7899 * any of the provided case-sensitive {@code searchStrings}. 7900 * @see StringUtils#startsWith(CharSequence, CharSequence) 7901 * @since 2.5 7902 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 7903 * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)}. 7904 */ 7905 @Deprecated 7906 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 7907 return Strings.CS.startsWithAny(sequence, searchStrings); 7908 } 7909 7910 /** 7911 * Case-insensitive check if a CharSequence starts with a specified prefix. 7912 * 7913 * <p> 7914 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 7915 * </p> 7916 * 7917 * <pre> 7918 * StringUtils.startsWithIgnoreCase(null, null) = true 7919 * StringUtils.startsWithIgnoreCase(null, "abc") = false 7920 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 7921 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 7922 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 7923 * </pre> 7924 * 7925 * @param str The CharSequence to check, may be null. 7926 * @param prefix The prefix to find, may be null. 7927 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}. 7928 * @see String#startsWith(String) 7929 * @since 2.4 7930 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 7931 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}. 7932 */ 7933 @Deprecated 7934 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 7935 return Strings.CI.startsWith(str, prefix); 7936 } 7937 7938 /** 7939 * Strips whitespace from the start and end of a String. 7940 * 7941 * <p> 7942 * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 7943 * </p> 7944 * 7945 * <p> 7946 * A {@code null} input String returns {@code null}. 7947 * </p> 7948 * 7949 * <pre> 7950 * StringUtils.strip(null) = null 7951 * StringUtils.strip("") = "" 7952 * StringUtils.strip(" ") = "" 7953 * StringUtils.strip("abc") = "abc" 7954 * StringUtils.strip(" abc") = "abc" 7955 * StringUtils.strip("abc ") = "abc" 7956 * StringUtils.strip(" abc ") = "abc" 7957 * StringUtils.strip(" ab c ") = "ab c" 7958 * </pre> 7959 * 7960 * @param str The String to remove whitespace from, may be null. 7961 * @return The stripped String, {@code null} if null String input. 7962 */ 7963 public static String strip(final String str) { 7964 return strip(str, null); 7965 } 7966 7967 /** 7968 * Strips any of a set of characters from the start and end of a String. This is similar to {@link String#trim()} but allows the characters to be stripped 7969 * to be controlled. 7970 * 7971 * <p> 7972 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7973 * </p> 7974 * 7975 * <p> 7976 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use 7977 * {@link #strip(String)}. 7978 * </p> 7979 * 7980 * <pre> 7981 * StringUtils.strip(null, *) = null 7982 * StringUtils.strip("", *) = "" 7983 * StringUtils.strip("abc", null) = "abc" 7984 * StringUtils.strip(" abc", null) = "abc" 7985 * StringUtils.strip("abc ", null) = "abc" 7986 * StringUtils.strip(" abc ", null) = "abc" 7987 * StringUtils.strip(" abcyx", "xyz") = " abc" 7988 * </pre> 7989 * 7990 * @param str The String to remove characters from, may be null. 7991 * @param stripChars The characters to remove, null treated as whitespace. 7992 * @return The stripped String, {@code null} if null String input. 7993 */ 7994 public static String strip(String str, final String stripChars) { 7995 str = stripStart(str, stripChars); 7996 return stripEnd(str, stripChars); 7997 } 7998 7999 /** 8000 * Removes diacritics (~= accents) from a string. The case will not be altered. 8001 * <p> 8002 * For instance, 'à' will be replaced by 'a'. 8003 * </p> 8004 * <p> 8005 * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a> 8006 * </p> 8007 * <p> 8008 * Be aware that this NFKD compatibility decomposition can map non-letter compatibility forms (fullwidth, small-form, math-symbol variants of {@code <}, 8009 * {@code >}, {@code /}, and so on) to their ASCII counterparts. 8010 * </p> 8011 * 8012 * <pre> 8013 * StringUtils.stripAccents(null) = null 8014 * StringUtils.stripAccents("") = "" 8015 * StringUtils.stripAccents("control") = "control" 8016 * StringUtils.stripAccents("éclair") = "eclair" 8017 * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3") = "abc123" 8018 * StringUtils.stripAccents("\u00BC \u00BD \u00BE") = "1⁄4 1⁄2 3⁄4" 8019 * </pre> 8020 * <p> 8021 * See also <a href="https://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>. 8022 * </p> 8023 * 8024 * @param input String to be stripped. 8025 * @return input text with diacritics removed. 8026 * @since 3.0 8027 */ 8028 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: 8029 // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 8030 public static String stripAccents(final String input) { 8031 if (isEmpty(input)) { 8032 return input; 8033 } 8034 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD)); 8035 convertRemainingAccentCharacters(decomposed); 8036 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 8037 } 8038 8039 /** 8040 * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}. 8041 * 8042 * <p> 8043 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A 8044 * {@code null} array entry will be ignored. 8045 * </p> 8046 * 8047 * <pre> 8048 * StringUtils.stripAll(null) = null 8049 * StringUtils.stripAll([]) = [] 8050 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 8051 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 8052 * </pre> 8053 * 8054 * @param strs The array to remove whitespace from, may be null. 8055 * @return The stripped Strings, {@code null} if null array input. 8056 */ 8057 public static String[] stripAll(final String... strs) { 8058 return stripAll(strs, null); 8059 } 8060 8061 /** 8062 * Strips any of a set of characters from the start and end of every String in an array. 8063 * <p> 8064 * Whitespace is defined by {@link Character#isWhitespace(char)}. 8065 * </p> 8066 * 8067 * <p> 8068 * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A 8069 * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}. 8070 * </p> 8071 * 8072 * <pre> 8073 * StringUtils.stripAll(null, *) = null 8074 * StringUtils.stripAll([], *) = [] 8075 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 8076 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 8077 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 8078 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 8079 * </pre> 8080 * 8081 * @param strs The array to remove characters from, may be null. 8082 * @param stripChars The characters to remove, null treated as whitespace. 8083 * @return The stripped Strings, {@code null} if null array input. 8084 */ 8085 public static String[] stripAll(final String[] strs, final String stripChars) { 8086 final int strsLen = ArrayUtils.getLength(strs); 8087 if (strsLen == 0) { 8088 return strs; 8089 } 8090 return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars)); 8091 } 8092 8093 /** 8094 * Strips any of a set of characters from the end of a String. 8095 * 8096 * <p> 8097 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 8098 * </p> 8099 * 8100 * <p> 8101 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 8102 * </p> 8103 * 8104 * <pre> 8105 * StringUtils.stripEnd(null, *) = null 8106 * StringUtils.stripEnd("", *) = "" 8107 * StringUtils.stripEnd("abc", "") = "abc" 8108 * StringUtils.stripEnd("abc", null) = "abc" 8109 * StringUtils.stripEnd(" abc", null) = " abc" 8110 * StringUtils.stripEnd("abc ", null) = "abc" 8111 * StringUtils.stripEnd(" abc ", null) = " abc" 8112 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 8113 * StringUtils.stripEnd("120.00", ".0") = "12" 8114 * </pre> 8115 * 8116 * @param str The String to remove characters from, may be null. 8117 * @param stripChars The set of characters to remove, null treated as whitespace. 8118 * @return The stripped String, {@code null} if null String input. 8119 */ 8120 public static String stripEnd(final String str, final String stripChars) { 8121 int end = length(str); 8122 if (end == 0) { 8123 return str; 8124 } 8125 if (stripChars == null) { 8126 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 8127 end--; 8128 } 8129 } else if (stripChars.isEmpty()) { 8130 return str; 8131 } else { 8132 while (end != 0) { 8133 final int codePoint = str.codePointBefore(end); 8134 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) { 8135 break; 8136 } 8137 end -= Character.charCount(codePoint); 8138 } 8139 } 8140 return str.substring(0, end); 8141 } 8142 8143 /** 8144 * Strips any of a set of characters from the start of a String. 8145 * 8146 * <p> 8147 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 8148 * </p> 8149 * 8150 * <p> 8151 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 8152 * </p> 8153 * 8154 * <pre> 8155 * StringUtils.stripStart(null, *) = null 8156 * StringUtils.stripStart("", *) = "" 8157 * StringUtils.stripStart("abc", "") = "abc" 8158 * StringUtils.stripStart("abc", null) = "abc" 8159 * StringUtils.stripStart(" abc", null) = "abc" 8160 * StringUtils.stripStart("abc ", null) = "abc " 8161 * StringUtils.stripStart(" abc ", null) = "abc " 8162 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8163 * </pre> 8164 * 8165 * @param str The String to remove characters from, may be null. 8166 * @param stripChars The characters to remove, null treated as whitespace. 8167 * @return The stripped String, {@code null} if null String input. 8168 */ 8169 public static String stripStart(final String str, final String stripChars) { 8170 final int strLen = length(str); 8171 if (strLen == 0) { 8172 return str; 8173 } 8174 int start = 0; 8175 if (stripChars == null) { 8176 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8177 start++; 8178 } 8179 } else if (stripChars.isEmpty()) { 8180 return str; 8181 } else { 8182 while (start != strLen) { 8183 final int codePoint = str.codePointAt(start); 8184 if (stripChars.indexOf(codePoint) == INDEX_NOT_FOUND) { 8185 break; 8186 } 8187 start += Character.charCount(codePoint); 8188 } 8189 } 8190 return str.substring(start); 8191 } 8192 8193 /** 8194 * Strips whitespace from the start and end of a String returning an empty String if {@code null} input. 8195 * 8196 * <p> 8197 * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8198 * </p> 8199 * 8200 * <pre> 8201 * StringUtils.stripToEmpty(null) = "" 8202 * StringUtils.stripToEmpty("") = "" 8203 * StringUtils.stripToEmpty(" ") = "" 8204 * StringUtils.stripToEmpty("abc") = "abc" 8205 * StringUtils.stripToEmpty(" abc") = "abc" 8206 * StringUtils.stripToEmpty("abc ") = "abc" 8207 * StringUtils.stripToEmpty(" abc ") = "abc" 8208 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8209 * </pre> 8210 * 8211 * @param str The String to be stripped, may be null. 8212 * @return The trimmed String, or an empty String if {@code null} input. 8213 * @since 2.0 8214 */ 8215 public static String stripToEmpty(final String str) { 8216 return str == null ? EMPTY : strip(str, null); 8217 } 8218 8219 /** 8220 * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip. 8221 * 8222 * <p> 8223 * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8224 * </p> 8225 * 8226 * <pre> 8227 * StringUtils.stripToNull(null) = null 8228 * StringUtils.stripToNull("") = null 8229 * StringUtils.stripToNull(" ") = null 8230 * StringUtils.stripToNull("abc") = "abc" 8231 * StringUtils.stripToNull(" abc") = "abc" 8232 * StringUtils.stripToNull("abc ") = "abc" 8233 * StringUtils.stripToNull(" abc ") = "abc" 8234 * StringUtils.stripToNull(" ab c ") = "ab c" 8235 * </pre> 8236 * 8237 * @param str The String to be stripped, may be null. 8238 * @return The stripped String, {@code null} if whitespace, empty or null String input. 8239 * @since 2.0 8240 */ 8241 public static String stripToNull(String str) { 8242 if (str == null) { 8243 return null; 8244 } 8245 str = strip(str, null); 8246 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here 8247 } 8248 8249 /** 8250 * Gets a substring from the specified String avoiding exceptions. 8251 * 8252 * <p> 8253 * A negative start position can be used to start {@code n} characters from the end of the String. 8254 * </p> 8255 * 8256 * <p> 8257 * A {@code null} String will return {@code null}. An empty ("") String will return "". 8258 * </p> 8259 * 8260 * <pre> 8261 * StringUtils.substring(null, *) = null 8262 * StringUtils.substring("", *) = "" 8263 * StringUtils.substring("abc", 0) = "abc" 8264 * StringUtils.substring("abc", 2) = "c" 8265 * StringUtils.substring("abc", 4) = "" 8266 * StringUtils.substring("abc", -2) = "bc" 8267 * StringUtils.substring("abc", -4) = "abc" 8268 * </pre> 8269 * 8270 * @param str The String to get the substring from, may be null. 8271 * @param start The position to start from, negative means count back from the end of the String by this many characters. 8272 * @return substring from start position, {@code null} if null String input. 8273 */ 8274 public static String substring(final String str, int start) { 8275 if (str == null) { 8276 return null; 8277 } 8278 // handle negatives, which means last n characters 8279 if (start < 0) { 8280 start = str.length() + start; // remember start is negative 8281 } 8282 if (start < 0) { 8283 start = 0; 8284 } 8285 if (start > str.length()) { 8286 return EMPTY; 8287 } 8288 return str.substring(start); 8289 } 8290 8291 /** 8292 * Gets a substring from the specified String avoiding exceptions. 8293 * 8294 * <p> 8295 * A negative start position can be used to start/end {@code n} characters from the end of the String. 8296 * </p> 8297 * 8298 * <p> 8299 * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is 8300 * zero-based -- i.e., to start at the beginning of the string use {@code start = 0}. Negative start and end positions can be used to specify offsets 8301 * relative to the end of the String. 8302 * </p> 8303 * 8304 * <p> 8305 * If {@code start} is not strictly to the left of {@code end}, "" is returned. 8306 * </p> 8307 * 8308 * <pre> 8309 * StringUtils.substring(null, *, *) = null 8310 * StringUtils.substring("", * , *) = ""; 8311 * StringUtils.substring("abc", 0, 2) = "ab" 8312 * StringUtils.substring("abc", 2, 0) = "" 8313 * StringUtils.substring("abc", 2, 4) = "c" 8314 * StringUtils.substring("abc", 4, 6) = "" 8315 * StringUtils.substring("abc", 2, 2) = "" 8316 * StringUtils.substring("abc", -2, -1) = "b" 8317 * StringUtils.substring("abc", -4, 2) = "ab" 8318 * </pre> 8319 * 8320 * @param str The String to get the substring from, may be null. 8321 * @param start The position to start from, negative means count back from the end of the String by this many characters. 8322 * @param end The position to end at (exclusive), negative means count back from the end of the String by this many characters. 8323 * @return substring from start position to end position, {@code null} if null String input. 8324 */ 8325 public static String substring(final String str, int start, int end) { 8326 if (str == null) { 8327 return null; 8328 } 8329 // handle negatives 8330 if (end < 0) { 8331 end = str.length() + end; // remember end is negative 8332 } 8333 if (start < 0) { 8334 start = str.length() + start; // remember start is negative 8335 } 8336 // check length next 8337 if (end > str.length()) { 8338 end = str.length(); 8339 } 8340 // if start is greater than end, return "" 8341 if (start > end) { 8342 return EMPTY; 8343 } 8344 if (start < 0) { 8345 start = 0; 8346 } 8347 if (end < 0) { 8348 end = 0; 8349 } 8350 return str.substring(start, end); 8351 } 8352 8353 /** 8354 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8355 * 8356 * <p> 8357 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8358 * </p> 8359 * 8360 * <p> 8361 * If nothing is found, the empty string is returned. 8362 * </p> 8363 * 8364 * <pre> 8365 * StringUtils.substringAfter(null, *) = null 8366 * StringUtils.substringAfter("", *) = "" 8367 * StringUtils.substringAfter("abc", 'a') = "bc" 8368 * StringUtils.substringAfter("abcba", 'b') = "cba" 8369 * StringUtils.substringAfter("abc", 'c') = "" 8370 * StringUtils.substringAfter("abc", 'd') = "" 8371 * StringUtils.substringAfter(" abc", 32) = "abc" 8372 * </pre> 8373 * 8374 * @param str The String to get a substring from, may be null. 8375 * @param find The character (Unicode code point) to find. 8376 * @return The substring after the first occurrence of the specified character, {@code null} if null String input. 8377 * @since 3.11 8378 */ 8379 public static String substringAfter(final String str, final int find) { 8380 if (isEmpty(str)) { 8381 return str; 8382 } 8383 final int pos = str.indexOf(find); 8384 if (pos == INDEX_NOT_FOUND) { 8385 return EMPTY; 8386 } 8387 return str.substring(pos + Character.charCount(find)); 8388 } 8389 8390 /** 8391 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8392 * 8393 * <p> 8394 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the 8395 * empty string if the input string is not {@code null}. 8396 * </p> 8397 * 8398 * <p> 8399 * If nothing is found, the empty string is returned. 8400 * </p> 8401 * 8402 * <pre> 8403 * StringUtils.substringAfter(null, *) = null 8404 * StringUtils.substringAfter("", *) = "" 8405 * StringUtils.substringAfter(*, null) = "" 8406 * StringUtils.substringAfter("abc", "a") = "bc" 8407 * StringUtils.substringAfter("abcba", "b") = "cba" 8408 * StringUtils.substringAfter("abc", "c") = "" 8409 * StringUtils.substringAfter("abc", "d") = "" 8410 * StringUtils.substringAfter("abc", "") = "abc" 8411 * </pre> 8412 * 8413 * @param str The String to get a substring from, may be null. 8414 * @param find The String to find, may be null. 8415 * @return The substring after the first occurrence of the specified string, {@code null} if null String input. 8416 * @since 2.0 8417 */ 8418 public static String substringAfter(final String str, final String find) { 8419 if (isEmpty(str)) { 8420 return str; 8421 } 8422 if (find == null) { 8423 return EMPTY; 8424 } 8425 final int pos = str.indexOf(find); 8426 if (pos == INDEX_NOT_FOUND) { 8427 return EMPTY; 8428 } 8429 return str.substring(pos + find.length()); 8430 } 8431 8432 /** 8433 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8434 * 8435 * <p> 8436 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8437 * </p> 8438 * 8439 * <p> 8440 * If nothing is found, the empty string is returned. 8441 * </p> 8442 * 8443 * <pre> 8444 * StringUtils.substringAfterLast(null, *) = null 8445 * StringUtils.substringAfterLast("", *) = "" 8446 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8447 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8448 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8449 * StringUtils.substringAfterLast("abc", 'c') = "" 8450 * StringUtils.substringAfterLast("a", 'a') = "" 8451 * StringUtils.substringAfterLast("a", 'z') = "" 8452 * </pre> 8453 * 8454 * @param str The String to get a substring from, may be null. 8455 * @param find The character (Unicode code point) to find. 8456 * @return The substring after the last occurrence of the specified character, {@code null} if null String input. 8457 * @since 3.11 8458 */ 8459 public static String substringAfterLast(final String str, final int find) { 8460 if (isEmpty(str)) { 8461 return str; 8462 } 8463 final int pos = str.lastIndexOf(find); 8464 if (pos == INDEX_NOT_FOUND || pos == str.length() - Character.charCount(find)) { 8465 return EMPTY; 8466 } 8467 return str.substring(pos + Character.charCount(find)); 8468 } 8469 8470 /** 8471 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8472 * 8473 * <p> 8474 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will 8475 * return the empty string if the input string is not {@code null}. 8476 * </p> 8477 * 8478 * <p> 8479 * If nothing is found, the empty string is returned. 8480 * </p> 8481 * 8482 * <pre> 8483 * StringUtils.substringAfterLast(null, *) = null 8484 * StringUtils.substringAfterLast("", *) = "" 8485 * StringUtils.substringAfterLast(*, "") = "" 8486 * StringUtils.substringAfterLast(*, null) = "" 8487 * StringUtils.substringAfterLast("abc", "a") = "bc" 8488 * StringUtils.substringAfterLast("abcba", "b") = "a" 8489 * StringUtils.substringAfterLast("abc", "c") = "" 8490 * StringUtils.substringAfterLast("a", "a") = "" 8491 * StringUtils.substringAfterLast("a", "z") = "" 8492 * </pre> 8493 * 8494 * @param str The String to get a substring from, may be null. 8495 * @param find The String to find, may be null. 8496 * @return The substring after the last occurrence of the specified string, {@code null} if null String input. 8497 * @since 2.0 8498 */ 8499 public static String substringAfterLast(final String str, final String find) { 8500 if (isEmpty(str)) { 8501 return str; 8502 } 8503 if (isEmpty(find)) { 8504 return EMPTY; 8505 } 8506 final int pos = str.lastIndexOf(find); 8507 if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) { 8508 return EMPTY; 8509 } 8510 return str.substring(pos + find.length()); 8511 } 8512 8513 /** 8514 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8515 * 8516 * <p> 8517 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8518 * </p> 8519 * 8520 * <p> 8521 * If nothing is found, the string input is returned. 8522 * </p> 8523 * 8524 * <pre> 8525 * StringUtils.substringBefore(null, *) = null 8526 * StringUtils.substringBefore("", *) = "" 8527 * StringUtils.substringBefore("abc", 'a') = "" 8528 * StringUtils.substringBefore("abcba", 'b') = "a" 8529 * StringUtils.substringBefore("abc", 'c') = "ab" 8530 * StringUtils.substringBefore("abc", 'd') = "abc" 8531 * </pre> 8532 * 8533 * @param str The String to get a substring from, may be null. 8534 * @param find The character (Unicode code point) to find. 8535 * @return The substring before the first occurrence of the specified character, {@code null} if null String input. 8536 * @since 3.12.0 8537 */ 8538 public static String substringBefore(final String str, final int find) { 8539 if (isEmpty(str)) { 8540 return str; 8541 } 8542 final int pos = str.indexOf(find); 8543 if (pos == INDEX_NOT_FOUND) { 8544 return str; 8545 } 8546 return str.substring(0, pos); 8547 } 8548 8549 /** 8550 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8551 * 8552 * <p> 8553 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the 8554 * input string. 8555 * </p> 8556 * 8557 * <p> 8558 * If nothing is found, the string input is returned. 8559 * </p> 8560 * 8561 * <pre> 8562 * StringUtils.substringBefore(null, *) = null 8563 * StringUtils.substringBefore("", *) = "" 8564 * StringUtils.substringBefore("abc", "a") = "" 8565 * StringUtils.substringBefore("abcba", "b") = "a" 8566 * StringUtils.substringBefore("abc", "c") = "ab" 8567 * StringUtils.substringBefore("abc", "d") = "abc" 8568 * StringUtils.substringBefore("abc", "") = "" 8569 * StringUtils.substringBefore("abc", null) = "abc" 8570 * </pre> 8571 * 8572 * @param str The String to get a substring from, may be null. 8573 * @param find The String to find, may be null. 8574 * @return The substring before the first occurrence of the specified string, {@code null} if null String input. 8575 * @since 2.0 8576 */ 8577 public static String substringBefore(final String str, final String find) { 8578 if (isEmpty(str) || find == null) { 8579 return str; 8580 } 8581 if (find.isEmpty()) { 8582 return EMPTY; 8583 } 8584 final int pos = str.indexOf(find); 8585 if (pos == INDEX_NOT_FOUND) { 8586 return str; 8587 } 8588 return str.substring(0, pos); 8589 } 8590 8591 /** 8592 * Gets the substring before the last occurrence of a separator. The separator is not returned. 8593 * 8594 * <p> 8595 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will 8596 * return the input string. 8597 * </p> 8598 * 8599 * <p> 8600 * If nothing is found, the string input is returned. 8601 * </p> 8602 * 8603 * <pre> 8604 * StringUtils.substringBeforeLast(null, *) = null 8605 * StringUtils.substringBeforeLast("", *) = "" 8606 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8607 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8608 * StringUtils.substringBeforeLast("a", "a") = "" 8609 * StringUtils.substringBeforeLast("a", "z") = "a" 8610 * StringUtils.substringBeforeLast("a", null) = "a" 8611 * StringUtils.substringBeforeLast("a", "") = "a" 8612 * </pre> 8613 * 8614 * @param str The String to get a substring from, may be null. 8615 * @param find The String to find, may be null. 8616 * @return The substring before the last occurrence of the specified string, {@code null} if null String input. 8617 * @since 2.0 8618 */ 8619 public static String substringBeforeLast(final String str, final String find) { 8620 if (isEmpty(str) || isEmpty(find)) { 8621 return str; 8622 } 8623 final int pos = str.lastIndexOf(find); 8624 if (pos == INDEX_NOT_FOUND) { 8625 return str; 8626 } 8627 return str.substring(0, pos); 8628 } 8629 8630 /** 8631 * Gets the String that is nested in between two instances of the same String. 8632 * 8633 * <p> 8634 * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}. 8635 * </p> 8636 * 8637 * <pre> 8638 * StringUtils.substringBetween(null, *) = null 8639 * StringUtils.substringBetween("", "") = "" 8640 * StringUtils.substringBetween("", "tag") = null 8641 * StringUtils.substringBetween("tagabctag", null) = null 8642 * StringUtils.substringBetween("tagabctag", "") = "" 8643 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8644 * </pre> 8645 * 8646 * @param str The String containing the substring, may be null. 8647 * @param tag The String before and after the substring, may be null. 8648 * @return The substring, {@code null} if no match. 8649 * @since 2.0 8650 */ 8651 public static String substringBetween(final String str, final String tag) { 8652 return substringBetween(str, tag, tag); 8653 } 8654 8655 /** 8656 * Gets the String that is nested in between two Strings. Only the first match is returned. 8657 * 8658 * <p> 8659 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open and close returns an 8660 * empty string. 8661 * </p> 8662 * 8663 * <pre> 8664 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8665 * StringUtils.substringBetween(null, *, *) = null 8666 * StringUtils.substringBetween(*, null, *) = null 8667 * StringUtils.substringBetween(*, *, null) = null 8668 * StringUtils.substringBetween("", "", "") = "" 8669 * StringUtils.substringBetween("", "", "]") = null 8670 * StringUtils.substringBetween("", "[", "]") = null 8671 * StringUtils.substringBetween("yabcz", "", "") = "" 8672 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8673 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8674 * </pre> 8675 * 8676 * @param str The String containing the substring, may be null. 8677 * @param open The String before the substring, may be null. 8678 * @param close The String after the substring, may be null. 8679 * @return The substring, {@code null} if no match. 8680 * @since 2.0 8681 */ 8682 public static String substringBetween(final String str, final String open, final String close) { 8683 if (!ObjectUtils.allNotNull(str, open, close)) { 8684 return null; 8685 } 8686 final int start = str.indexOf(open); 8687 if (start != INDEX_NOT_FOUND) { 8688 final int end = str.indexOf(close, start + open.length()); 8689 if (end != INDEX_NOT_FOUND) { 8690 return str.substring(start + open.length(), end); 8691 } 8692 } 8693 return null; 8694 } 8695 8696 /** 8697 * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array. 8698 * 8699 * <p> 8700 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns 8701 * {@code null} (no match). 8702 * </p> 8703 * 8704 * <pre> 8705 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8706 * StringUtils.substringsBetween(null, *, *) = null 8707 * StringUtils.substringsBetween(*, null, *) = null 8708 * StringUtils.substringsBetween(*, *, null) = null 8709 * StringUtils.substringsBetween("", "[", "]") = [] 8710 * </pre> 8711 * 8712 * @param str The String containing the substrings, null returns null, empty returns empty. 8713 * @param open The String identifying the start of the substring, empty returns null. 8714 * @param close The String identifying the end of the substring, empty returns null. 8715 * @return A String Array of substrings, or {@code null} if no match. 8716 * @since 2.3 8717 */ 8718 public static String[] substringsBetween(final String str, final String open, final String close) { 8719 if (str == null || isEmpty(open) || isEmpty(close)) { 8720 return null; 8721 } 8722 final int strLen = str.length(); 8723 if (strLen == 0) { 8724 return ArrayUtils.EMPTY_STRING_ARRAY; 8725 } 8726 final int closeLen = close.length(); 8727 final int openLen = open.length(); 8728 final List<String> list = new ArrayList<>(); 8729 int pos = 0; 8730 while (pos < strLen - closeLen) { 8731 int start = str.indexOf(open, pos); 8732 if (start < 0) { 8733 break; 8734 } 8735 start += openLen; 8736 final int end = str.indexOf(close, start); 8737 if (end < 0) { 8738 break; 8739 } 8740 list.add(str.substring(start, end)); 8741 pos = end + closeLen; 8742 } 8743 if (list.isEmpty()) { 8744 return null; 8745 } 8746 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8747 } 8748 8749 /** 8750 * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case. 8751 * 8752 * <ul> 8753 * <li>Upper case character converts to Lower case</li> 8754 * <li>Title case character converts to Lower case</li> 8755 * <li>Lower case character converts to Upper case</li> 8756 * </ul> 8757 * 8758 * <p> 8759 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}. 8760 * </p> 8761 * 8762 * <pre> 8763 * StringUtils.swapCase(null) = null 8764 * StringUtils.swapCase("") = "" 8765 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8766 * </pre> 8767 * 8768 * <p> 8769 * NOTE: This method changed in Lang version 2.0. It no longer performs a word based algorithm. If you only use ASCII, you will notice no change. That 8770 * functionality is available in org.apache.commons.lang3.text.WordUtils. 8771 * </p> 8772 * 8773 * @param str The String to swap case, may be null. 8774 * @return The changed String, {@code null} if null String input. 8775 */ 8776 public static String swapCase(final String str) { 8777 if (isEmpty(str)) { 8778 return str; 8779 } 8780 final int strLen = str.length(); 8781 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8782 int outOffset = 0; 8783 for (int i = 0; i < strLen;) { 8784 final int oldCodepoint = str.codePointAt(i); 8785 final int newCodePoint; 8786 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8787 newCodePoint = Character.toLowerCase(oldCodepoint); 8788 } else if (Character.isLowerCase(oldCodepoint)) { 8789 newCodePoint = Character.toUpperCase(oldCodepoint); 8790 } else { 8791 newCodePoint = oldCodepoint; 8792 } 8793 newCodePoints[outOffset++] = newCodePoint; 8794 i += Character.charCount(newCodePoint); 8795 } 8796 return new String(newCodePoints, 0, outOffset); 8797 } 8798 8799 /** 8800 * Converts a {@link CharSequence} into an array of code points. 8801 * 8802 * <p> 8803 * Valid pairs of surrogate code units will be converted into a single supplementary code point. Isolated surrogate code units (i.e. a high surrogate not 8804 * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is. 8805 * </p> 8806 * 8807 * <pre> 8808 * StringUtils.toCodePoints(null) = null 8809 * StringUtils.toCodePoints("") = [] // empty array 8810 * </pre> 8811 * 8812 * @param cs The character sequence to convert. 8813 * @return An array of code points. 8814 * @since 3.6 8815 */ 8816 public static int[] toCodePoints(final CharSequence cs) { 8817 if (cs == null) { 8818 return null; 8819 } 8820 if (isEmpty(cs)) { 8821 return ArrayUtils.EMPTY_INT_ARRAY; 8822 } 8823 return cs.toString().codePoints().toArray(); 8824 } 8825 8826 /** 8827 * Converts a {@code byte[]} to a String using the specified character encoding. 8828 * 8829 * @param bytes The byte array to read from. 8830 * @param charset The encoding to use, if null then use the platform default. 8831 * @return A new String. 8832 * @throws NullPointerException Thrown if {@code bytes} is null. 8833 * @since 3.2 8834 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8835 */ 8836 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8837 return new String(bytes, Charsets.toCharset(charset)); 8838 } 8839 8840 /** 8841 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8842 * 8843 * @param source A source String or null. 8844 * @return The given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8845 * @since 3.10 8846 */ 8847 public static String toRootLowerCase(final String source) { 8848 return source == null ? null : source.toLowerCase(Locale.ROOT); 8849 } 8850 8851 /** 8852 * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8853 * 8854 * @param source A source String or null. 8855 * @return The given source String as an upper-case using the {@link Locale#ROOT} locale or null. 8856 * @since 3.10 8857 */ 8858 public static String toRootUpperCase(final String source) { 8859 return source == null ? null : source.toUpperCase(Locale.ROOT); 8860 } 8861 8862 /** 8863 * Converts a {@code byte[]} to a String using the specified character encoding. 8864 * 8865 * @param bytes The byte array to read from. 8866 * @param charsetName The encoding to use, if null then use the platform default. 8867 * @return A new String. 8868 * @throws NullPointerException Thrown if the input is null. 8869 * @since 3.1 8870 * @deprecated Use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code. 8871 */ 8872 @Deprecated 8873 public static String toString(final byte[] bytes, final String charsetName) { 8874 return new String(bytes, Charsets.toCharset(charsetName)); 8875 } 8876 8877 /** 8878 * Removes control characters plus space (char <= 32) from both ends of this String, handling {@code null} by returning {@code null}. 8879 * 8880 * <p> 8881 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #strip(String)}. 8882 * </p> 8883 * 8884 * <p> 8885 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8886 * </p> 8887 * 8888 * <pre> 8889 * StringUtils.trim(null) = null 8890 * StringUtils.trim("") = "" 8891 * StringUtils.trim(" ") = "" 8892 * StringUtils.trim("abc") = "abc" 8893 * StringUtils.trim(" abc ") = "abc" 8894 * </pre> 8895 * 8896 * @param str The String to be trimmed, may be null. 8897 * @return The trimmed string, {@code null} if null String input. 8898 */ 8899 public static String trim(final String str) { 8900 return str == null ? null : str.trim(); 8901 } 8902 8903 /** 8904 * Removes {@link CharUtils#isAsciiControl(char) ASCII control characters} (char <= 31 or char == 127) from both ends of this String, handling 8905 * {@code null} by returning {@code null}. 8906 * 8907 * <p> 8908 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8909 * </p> 8910 * 8911 * <pre>{@code 8912 * StringUtils.trimAsciiControl(null) = null 8913 * StringUtils.trimAsciiControl("") = "" 8914 * StringUtils.trimAsciiControl("abc\u0000") = "abc" 8915 * StringUtils.trimAsciiControl("abc") = "abc" 8916 * StringUtils.trimAsciiControl(" abc ") = " abc " 8917 * }</pre> 8918 * 8919 * @param str The String to be trimmed, may be null. 8920 * @return The trimmed string, {@code null} if null String input. 8921 * @since 3.21.0 8922 */ 8923 public static String trimAsciiControl(final String str) { 8924 if (str == null) { 8925 return null; 8926 } 8927 int len = str.length(); 8928 int st = 0; 8929 while (st < len && CharUtils.isAsciiControl(str.charAt(st))) { 8930 st++; 8931 } 8932 while (st < len && CharUtils.isAsciiControl(str.charAt(len - 1))) { 8933 len--; 8934 } 8935 return st > 0 || len < str.length() ? str.substring(st, len) : str; 8936 } 8937 8938 /** 8939 * Removes control characters (char <= 32) from both ends of this String returning an empty String ("") if the String is empty ("") after the trim or if 8940 * it is {@code null}. 8941 * 8942 * <p> 8943 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToEmpty(String)}. 8944 * </p> 8945 * 8946 * <pre> 8947 * StringUtils.trimToEmpty(null) = "" 8948 * StringUtils.trimToEmpty("") = "" 8949 * StringUtils.trimToEmpty(" ") = "" 8950 * StringUtils.trimToEmpty("abc") = "abc" 8951 * StringUtils.trimToEmpty(" abc ") = "abc" 8952 * </pre> 8953 * 8954 * @param str The String to be trimmed, may be null. 8955 * @return The trimmed String, or an empty String if {@code null} input. 8956 * @since 2.0 8957 */ 8958 public static String trimToEmpty(final String str) { 8959 return str == null ? EMPTY : str.trim(); 8960 } 8961 8962 /** 8963 * Removes control characters (char <= 32) from both ends of this String returning {@code null} if the String is empty ("") after the trim or if it is 8964 * {@code null}. 8965 * 8966 * <p> 8967 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToNull(String)}. 8968 * </p> 8969 * 8970 * <pre> 8971 * StringUtils.trimToNull(null) = null 8972 * StringUtils.trimToNull("") = null 8973 * StringUtils.trimToNull(" ") = null 8974 * StringUtils.trimToNull("abc") = "abc" 8975 * StringUtils.trimToNull(" abc ") = "abc" 8976 * </pre> 8977 * 8978 * @param str The String to be trimmed, may be null. 8979 * @return The trimmed String, {@code null} if only chars <= 32, empty or null String input. 8980 * @since 2.0 8981 */ 8982 public static String trimToNull(final String str) { 8983 final String ts = trim(str); 8984 return isEmpty(ts) ? null : ts; 8985 } 8986 8987 /** 8988 * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for". 8989 * 8990 * <p> 8991 * Specifically: 8992 * </p> 8993 * <ul> 8994 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 8995 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 8996 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8997 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 8998 * </ul> 8999 * 9000 * <pre> 9001 * StringUtils.truncate(null, 0) = null 9002 * StringUtils.truncate(null, 2) = null 9003 * StringUtils.truncate("", 4) = "" 9004 * StringUtils.truncate("abcdefg", 4) = "abcd" 9005 * StringUtils.truncate("abcdefg", 6) = "abcdef" 9006 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 9007 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 9008 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 9009 * </pre> 9010 * 9011 * @param str The String to truncate, may be null. 9012 * @param maxWidth maximum length of result String, must be non-negative. 9013 * @return truncated String, {@code null} if null String input. 9014 * @throws IllegalArgumentException Thrown if {@code maxWidth} is less than {@code 0}. 9015 * @since 3.5 9016 */ 9017 public static String truncate(final String str, final int maxWidth) { 9018 return truncate(str, 0, maxWidth); 9019 } 9020 9021 /** 9022 * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all". 9023 * 9024 * <p> 9025 * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset. 9026 * </p> 9027 * 9028 * <p> 9029 * Specifically: 9030 * </p> 9031 * <ul> 9032 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 9033 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 9034 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 9035 * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 9036 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 9037 * </ul> 9038 * 9039 * <pre> 9040 * StringUtils.truncate(null, 0, 0) = null 9041 * StringUtils.truncate(null, 2, 4) = null 9042 * StringUtils.truncate("", 0, 10) = "" 9043 * StringUtils.truncate("", 2, 10) = "" 9044 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 9045 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 9046 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 9047 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 9048 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 9049 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 9050 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 9051 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 9052 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 9053 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 9054 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 9055 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 9056 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 9057 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 9058 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 9059 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 9060 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 9061 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 9062 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 9063 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 9064 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 9065 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 9066 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 9067 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 9068 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 9069 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 9070 * </pre> 9071 * 9072 * @param str The String to truncate, may be null. 9073 * @param offset left edge of source String. 9074 * @param maxWidth maximum length of result String, must be non-negative. 9075 * @return truncated String, {@code null} if null String input. 9076 * @throws IllegalArgumentException Thrown if {@code offset} or {@code maxWidth} is less than {@code 0}. 9077 * @since 3.5 9078 */ 9079 public static String truncate(final String str, final int offset, final int maxWidth) { 9080 if (offset < 0) { 9081 throw new IllegalArgumentException("offset cannot be negative"); 9082 } 9083 if (maxWidth < 0) { 9084 throw new IllegalArgumentException("maxWidth cannot be negative"); 9085 } 9086 if (str == null) { 9087 return null; 9088 } 9089 final int len = str.length(); 9090 int start = Math.min(offset, len); 9091 int end = Math.min(offset > len - maxWidth ? len : offset + maxWidth, len); 9092 // keep both edges off the middle of a surrogate pair so the result is never left holding a lone surrogate 9093 if (splitsSurrogatePair(str, start)) { 9094 start++; 9095 } 9096 if (splitsSurrogatePair(str, end)) { 9097 end--; 9098 } 9099 return str.substring(start, Math.max(start, end)); 9100 } 9101 9102 /** 9103 * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed. 9104 * 9105 * <p> 9106 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}. 9107 * </p> 9108 * 9109 * <pre> 9110 * StringUtils.uncapitalize(null) = null 9111 * StringUtils.uncapitalize("") = "" 9112 * StringUtils.uncapitalize("cat") = "cat" 9113 * StringUtils.uncapitalize("Cat") = "cat" 9114 * StringUtils.uncapitalize("CAT") = "cAT" 9115 * </pre> 9116 * 9117 * @param str The String to uncapitalize, may be null. 9118 * @return The uncapitalized String, {@code null} if null String input. 9119 * @see org.apache.commons.text.WordUtils#uncapitalize(String) 9120 * @see #capitalize(String) 9121 * @since 2.0 9122 */ 9123 public static String uncapitalize(final String str) { 9124 final int strLen = length(str); 9125 if (strLen == 0) { 9126 return str; 9127 } 9128 final int firstCodePoint = str.codePointAt(0); 9129 final int newCodePoint = Character.toLowerCase(firstCodePoint); 9130 if (firstCodePoint == newCodePoint) { 9131 // already uncapitalized 9132 return str; 9133 } 9134 final int[] newCodePoints = str.codePoints().toArray(); 9135 newCodePoints[0] = newCodePoint; // copy the first code point 9136 return new String(newCodePoints, 0, newCodePoints.length); 9137 } 9138 9139 /** 9140 * Unwraps a given string from a character. 9141 * 9142 * <pre> 9143 * StringUtils.unwrap(null, null) = null 9144 * StringUtils.unwrap(null, '\0') = null 9145 * StringUtils.unwrap(null, '1') = null 9146 * StringUtils.unwrap("a", 'a') = "a" 9147 * StringUtils.unwrap("aa", 'a') = "" 9148 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 9149 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 9150 * StringUtils.unwrap("A", '#') = "A" 9151 * StringUtils.unwrap("#A", '#') = "#A" 9152 * StringUtils.unwrap("A#", '#') = "A#" 9153 * </pre> 9154 * 9155 * @param str The String to be unwrapped, can be null. 9156 * @param wrapChar The character used to unwrap. 9157 * @return unwrapped String or the original string if it is not quoted properly with the wrapChar. 9158 * @since 3.6 9159 */ 9160 public static String unwrap(final String str, final char wrapChar) { 9161 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 9162 return str; 9163 } 9164 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 9165 final int startIndex = 0; 9166 final int endIndex = str.length() - 1; 9167 return str.substring(startIndex + 1, endIndex); 9168 } 9169 return str; 9170 } 9171 9172 /** 9173 * Unwraps a given string from another string. 9174 * 9175 * <pre> 9176 * StringUtils.unwrap(null, null) = null 9177 * StringUtils.unwrap(null, "") = null 9178 * StringUtils.unwrap(null, "1") = null 9179 * StringUtils.unwrap("a", "a") = "a" 9180 * StringUtils.unwrap("aa", "a") = "" 9181 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 9182 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 9183 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 9184 * StringUtils.unwrap("A", "#") = "A" 9185 * StringUtils.unwrap("#A", "#") = "#A" 9186 * StringUtils.unwrap("A#", "#") = "A#" 9187 * </pre> 9188 * 9189 * @param str The String to be unwrapped, can be null. 9190 * @param wrapToken The String used to unwrap. 9191 * @return unwrapped String or the original string if it is not quoted properly with the wrapToken. 9192 * @since 3.6 9193 */ 9194 public static String unwrap(final String str, final String wrapToken) { 9195 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) { 9196 return str; 9197 } 9198 if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) { 9199 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken)); 9200 } 9201 return str; 9202 } 9203 9204 /** 9205 * Converts a String to upper case as per {@link String#toUpperCase()}. 9206 * 9207 * <p> 9208 * A {@code null} input String returns {@code null}. 9209 * </p> 9210 * 9211 * <pre> 9212 * StringUtils.upperCase(null) = null 9213 * StringUtils.upperCase("") = "" 9214 * StringUtils.upperCase("aBc") = "ABC" 9215 * </pre> 9216 * 9217 * <p> 9218 * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale. 9219 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g. 9220 * {@link Locale#ENGLISH}). 9221 * </p> 9222 * 9223 * @param str The String to upper case, may be null. 9224 * @return The upper-cased String, {@code null} if null String input. 9225 */ 9226 public static String upperCase(final String str) { 9227 if (str == null) { 9228 return null; 9229 } 9230 return str.toUpperCase(); 9231 } 9232 9233 /** 9234 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}. 9235 * 9236 * <p> 9237 * A {@code null} input String returns {@code null}. 9238 * </p> 9239 * 9240 * <pre> 9241 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9242 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9243 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9244 * </pre> 9245 * 9246 * @param str The String to upper case, may be null. 9247 * @param locale The locale that defines the case transformation rules, must not be null. 9248 * @return The upper-cased String, {@code null} if null String input. 9249 * @since 2.5 9250 */ 9251 public static String upperCase(final String str, final Locale locale) { 9252 if (str == null) { 9253 return null; 9254 } 9255 return str.toUpperCase(LocaleUtils.toLocale(locale)); 9256 } 9257 9258 /** 9259 * Returns the string representation of the {@code char} array or null. 9260 * 9261 * @param value The character array. 9262 * @return A String or null. 9263 * @see String#valueOf(char[]) 9264 * @since 3.9 9265 */ 9266 public static String valueOf(final char[] value) { 9267 return value == null ? null : String.valueOf(value); 9268 } 9269 9270 /** 9271 * Wraps a string with a char. 9272 * 9273 * <pre> 9274 * StringUtils.wrap(null, *) = null 9275 * StringUtils.wrap("", *) = "" 9276 * StringUtils.wrap("ab", '\0') = "ab" 9277 * StringUtils.wrap("ab", 'x') = "xabx" 9278 * StringUtils.wrap("ab", '\'') = "'ab'" 9279 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9280 * </pre> 9281 * 9282 * @param str The string to be wrapped, may be {@code null}. 9283 * @param wrapWith The char that will wrap {@code str}. 9284 * @return The wrapped string, or {@code null} if {@code str == null}. 9285 * @since 3.4 9286 */ 9287 public static String wrap(final String str, final char wrapWith) { 9288 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9289 return str; 9290 } 9291 return wrapWith + str + wrapWith; 9292 } 9293 9294 /** 9295 * Wraps a String with another String. 9296 * 9297 * <p> 9298 * A {@code null} input String returns {@code null}. 9299 * </p> 9300 * 9301 * <pre> 9302 * StringUtils.wrap(null, *) = null 9303 * StringUtils.wrap("", *) = "" 9304 * StringUtils.wrap("ab", null) = "ab" 9305 * StringUtils.wrap("ab", "x") = "xabx" 9306 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9307 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9308 * StringUtils.wrap("ab", "'") = "'ab'" 9309 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9310 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9311 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9312 * </pre> 9313 * 9314 * @param str The String to be wrapper, may be null. 9315 * @param wrapWith The String that will wrap str. 9316 * @return wrapped String, {@code null} if null String input. 9317 * @since 3.4 9318 */ 9319 public static String wrap(final String str, final String wrapWith) { 9320 if (isEmpty(str) || isEmpty(wrapWith)) { 9321 return str; 9322 } 9323 return wrapWith.concat(str).concat(wrapWith); 9324 } 9325 9326 /** 9327 * Wraps a string with a char if that char is missing from the start or end of the given string. 9328 * 9329 * <p> 9330 * A new {@link String} will not be created if {@code str} is already wrapped. 9331 * </p> 9332 * 9333 * <pre> 9334 * StringUtils.wrapIfMissing(null, *) = null 9335 * StringUtils.wrapIfMissing("", *) = "" 9336 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9337 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9338 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9339 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9340 * StringUtils.wrapIfMissing("/", '/') = "/" 9341 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9342 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9343 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9344 * </pre> 9345 * 9346 * @param str The string to be wrapped, may be {@code null}. 9347 * @param wrapWith The char that will wrap {@code str}. 9348 * @return The wrapped string, or {@code null} if {@code str == null}. 9349 * @since 3.5 9350 */ 9351 public static String wrapIfMissing(final String str, final char wrapWith) { 9352 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9353 return str; 9354 } 9355 final boolean wrapStart = str.charAt(0) != wrapWith; 9356 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9357 if (!wrapStart && !wrapEnd) { 9358 return str; 9359 } 9360 final StringBuilder builder = new StringBuilder(str.length() + 2); 9361 if (wrapStart) { 9362 builder.append(wrapWith); 9363 } 9364 builder.append(str); 9365 if (wrapEnd) { 9366 builder.append(wrapWith); 9367 } 9368 return builder.toString(); 9369 } 9370 9371 /** 9372 * Wraps a string with a string if that string is missing from the start or end of the given string. 9373 * 9374 * <p> 9375 * A new {@link String} will not be created if {@code str} is already wrapped. 9376 * </p> 9377 * 9378 * <pre> 9379 * StringUtils.wrapIfMissing(null, *) = null 9380 * StringUtils.wrapIfMissing("", *) = "" 9381 * StringUtils.wrapIfMissing("ab", null) = "ab" 9382 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9383 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9384 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9385 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9386 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9387 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9388 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9389 * StringUtils.wrapIfMissing("/", "/") = "/" 9390 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9391 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9392 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9393 * </pre> 9394 * 9395 * @param str The string to be wrapped, may be {@code null}. 9396 * @param wrapWith The string that will wrap {@code str}. 9397 * @return The wrapped string, or {@code null} if {@code str == null}. 9398 * @since 3.5 9399 */ 9400 public static String wrapIfMissing(final String str, final String wrapWith) { 9401 if (isEmpty(str) || isEmpty(wrapWith)) { 9402 return str; 9403 } 9404 final boolean wrapStart = !str.startsWith(wrapWith); 9405 final boolean wrapEnd = !str.endsWith(wrapWith); 9406 if (!wrapStart && !wrapEnd) { 9407 return str; 9408 } 9409 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9410 if (wrapStart) { 9411 builder.append(wrapWith); 9412 } 9413 builder.append(str); 9414 if (wrapEnd) { 9415 builder.append(wrapWith); 9416 } 9417 return builder.toString(); 9418 } 9419 9420 /** 9421 * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}. 9422 * 9423 * <p> 9424 * This constructor is public to permit tools that require a JavaBean instance to operate. 9425 * </p> 9426 * 9427 * @deprecated TODO Make private in 4.0. 9428 */ 9429 @Deprecated 9430 public StringUtils() { 9431 // empty 9432 } 9433 9434}