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>The {@link StringUtils} class defines certain words related to 098 * String handling.</p> 099 * 100 * <ul> 101 * <li>null - {@code null}</li> 102 * <li>empty - a zero-length string ({@code ""})</li> 103 * <li>space - the space character ({@code ' '}, char 32)</li> 104 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 105 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 106 * </ul> 107 * 108 * <p>{@link StringUtils} handles {@code null} input Strings quietly. 109 * That is to say that a {@code null} input will return {@code null}. 110 * Where a {@code boolean} or {@code int} is being returned 111 * details vary by method.</p> 112 * 113 * <p>A side effect of the {@code null} handling is that a 114 * {@link NullPointerException} should be considered a bug in 115 * {@link StringUtils}.</p> 116 * 117 * <p>Methods in this class include sample code in their Javadoc comments to explain their operation. 118 * The symbol {@code *} is used to indicate any input including {@code null}.</p> 119 * 120 * <p>#ThreadSafe#</p> 121 * 122 * @see String 123 * @since 1.0 124 */ 125//@Immutable 126public class StringUtils { 127 128 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 129 // Whitespace: 130 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 131 // where WHITESPACE is a string of all whitespace characters 132 // 133 // Character access: 134 // String.charAt(n) versus toCharArray(), then array[n] 135 // String.charAt(n) is about 15% worse for a 10K string 136 // They are about equal for a length 50 string 137 // String.charAt(n) is about 4 times better for a length 3 string 138 // String.charAt(n) is best bet overall 139 // 140 // Append: 141 // String.concat about twice as fast as StringBuffer.append 142 // (not sure who tested this) 143 144 /** 145 * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 '…', this isn't it. 146 */ 147 private static final String ELLIPSIS3 = "..."; 148 149 /** 150 * A String for a space character. 151 * 152 * @since 3.2 153 */ 154 public static final String SPACE = " "; 155 156 /** 157 * The empty String {@code ""}. 158 * 159 * @since 2.0 160 */ 161 public static final String EMPTY = ""; 162 163 /** 164 * The null String {@code null}. Package-private only. 165 */ 166 static final String NULL = null; 167 168 /** 169 * A String for linefeed LF ("\n"). 170 * 171 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 172 * for Character and String Literals</a> 173 * @since 3.2 174 */ 175 public static final String LF = "\n"; 176 177 /** 178 * A String for carriage return CR ("\r"). 179 * 180 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 181 * for Character and String Literals</a> 182 * @since 3.2 183 */ 184 public static final String CR = "\r"; 185 186 /** 187 * Represents a failed index search. 188 * 189 * @since 2.1 190 */ 191 public static final int INDEX_NOT_FOUND = -1; 192 193 /** 194 * The maximum size to which the padding constant(s) can expand. 195 */ 196 private static final int PAD_LIMIT = 8192; 197 198 /** 199 * The default maximum depth at which recursive replacement will continue until no further search replacements are possible. 200 */ 201 private static final int DEFAULT_TTL = 5; 202 203 /** 204 * Pattern used in {@link #stripAccents(String)}. 205 */ 206 private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$ 207 208 /** 209 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "Now is the time for..." 210 * 211 * <p> 212 * Specifically: 213 * </p> 214 * <ul> 215 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 216 * <li>Else abbreviate it to {@code (substring(str, 0, max - 3) + "...")}.</li> 217 * <li>If {@code maxWidth} is less than {@code 4}, throw an {@link IllegalArgumentException}.</li> 218 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 219 * </ul> 220 * 221 * <pre> 222 * StringUtils.abbreviate(null, *) = null 223 * StringUtils.abbreviate("", 4) = "" 224 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 225 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 226 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 227 * StringUtils.abbreviate("abcdefg", 4) = "a..." 228 * StringUtils.abbreviate("abcdefg", 3) = Throws {@link IllegalArgumentException}. 229 * </pre> 230 * 231 * @param str the String to check, may be null. 232 * @param maxWidth maximum length of result String, must be at least 4. 233 * @return abbreviated String, {@code null} if null String input. 234 * @throws IllegalArgumentException if the width is too small. 235 * @since 2.0 236 */ 237 public static String abbreviate(final String str, final int maxWidth) { 238 return abbreviate(str, ELLIPSIS3, 0, maxWidth); 239 } 240 241 /** 242 * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "...is the time for...". 243 * 244 * <p> 245 * 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 246 * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result. 247 * </p> 248 * <p> 249 * In no case will it return a String of length greater than {@code maxWidth}. 250 * </p> 251 * 252 * <pre> 253 * StringUtils.abbreviate(null, *, *) = null 254 * StringUtils.abbreviate("", 0, 4) = "" 255 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 256 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 257 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 258 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 259 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 260 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 261 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 262 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 263 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 264 * StringUtils.abbreviate("abcdefghij", 0, 3) = Throws {@link IllegalArgumentException}. 265 * StringUtils.abbreviate("abcdefghij", 5, 6) = Throws {@link IllegalArgumentException}. 266 * </pre> 267 * 268 * @param str the String to check, may be null. 269 * @param offset left edge of source String. 270 * @param maxWidth maximum length of result String, must be at least 4. 271 * @return abbreviated String, {@code null} if null String input. 272 * @throws IllegalArgumentException if the width is too small. 273 * @since 2.0 274 */ 275 public static String abbreviate(final String str, final int offset, final int maxWidth) { 276 return abbreviate(str, ELLIPSIS3, offset, maxWidth); 277 } 278 279 /** 280 * 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..." 281 * when "..." is the replacement marker. 282 * 283 * <p> 284 * Specifically: 285 * </p> 286 * <ul> 287 * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li> 288 * <li>Else abbreviate it to {@code (substring(str, 0, max - abbrevMarker.length) + abbrevMarker)}.</li> 289 * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li> 290 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 291 * </ul> 292 * 293 * <pre> 294 * StringUtils.abbreviate(null, "...", *) = null 295 * StringUtils.abbreviate("abcdefg", null, *) = "abcdefg" 296 * StringUtils.abbreviate("", "...", 4) = "" 297 * StringUtils.abbreviate("abcdefg", ".", 5) = "abcd." 298 * StringUtils.abbreviate("abcdefg", ".", 7) = "abcdefg" 299 * StringUtils.abbreviate("abcdefg", ".", 8) = "abcdefg" 300 * StringUtils.abbreviate("abcdefg", "..", 4) = "ab.." 301 * StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 302 * StringUtils.abbreviate("abcdefg", "..", 2) = Throws {@link IllegalArgumentException}. 303 * StringUtils.abbreviate("abcdefg", "...", 3) = Throws {@link IllegalArgumentException}. 304 * </pre> 305 * 306 * @param str the String to check, may be null. 307 * @param abbrevMarker the String used as replacement marker. 308 * @param maxWidth maximum length of result String, must be at least {@code abbrevMarker.length + 1}. 309 * @return abbreviated String, {@code null} if null String input. 310 * @throws IllegalArgumentException if the width is too small. 311 * @since 3.6 312 */ 313 public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) { 314 return abbreviate(str, abbrevMarker, 0, maxWidth); 315 } 316 317 /** 318 * 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 319 * the replacement marker. 320 * <p> 321 * Works like {@code abbreviate(String, String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to 322 * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result. 323 * </p> 324 * <p> 325 * In no case will it return a String of length greater than {@code maxWidth}. 326 * </p> 327 * 328 * <pre> 329 * StringUtils.abbreviate(null, null, *, *) = null 330 * StringUtils.abbreviate("abcdefghijklmno", null, *, *) = "abcdefghijklmno" 331 * StringUtils.abbreviate("", "...", 0, 4) = "" 332 * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---" 333 * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10) = "abcdefghi," 334 * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10) = "abcdefghi," 335 * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10) = "abcdefghi," 336 * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10) = "::efghij::" 337 * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10) = "...ghij..." 338 * StringUtils.abbreviate("abcdefghijklmno", "…", 6, 10) = "…ghij…" 339 * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10) = "*ghijklmno" 340 * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10) = "'ghijklmno" 341 * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10) = "!ghijklmno" 342 * StringUtils.abbreviate("abcdefghij", "abra", 0, 4) = Throws {@link IllegalArgumentException}. 343 * StringUtils.abbreviate("abcdefghij", "...", 5, 6) = Throws {@link IllegalArgumentException}. 344 * </pre> 345 * 346 * @param str the String to check, may be null. 347 * @param abbrevMarker the String used as replacement marker, for example "...", or Unicode HORIZONTAL ELLIPSIS, U+2026 '…'. 348 * @param offset left edge of source String. 349 * @param maxWidth maximum length of result String, must be at least 4. 350 * @return abbreviated String, {@code null} if null String input. 351 * @throws IllegalArgumentException if the width is too small. 352 * @since 3.6 353 */ 354 public static String abbreviate(final String str, String abbrevMarker, int offset, final int maxWidth) { 355 if (isEmpty(str)) { 356 return str; 357 } 358 if (abbrevMarker == null) { 359 abbrevMarker = EMPTY; 360 } 361 final int abbrevMarkerLength = abbrevMarker.length(); 362 final int minAbbrevWidth = abbrevMarkerLength + 1; 363 final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1; 364 365 if (maxWidth < minAbbrevWidth) { 366 throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth)); 367 } 368 final int strLen = str.length(); 369 if (strLen <= maxWidth) { 370 return str; 371 } 372 if (strLen - offset <= maxWidth - abbrevMarkerLength) { 373 return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength)); 374 } 375 if (offset <= abbrevMarkerLength + 1) { 376 return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker; 377 } 378 if (maxWidth < minAbbrevWidthOffset) { 379 throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset)); 380 } 381 return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength); 382 } 383 384 /** 385 * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String. 386 * 387 * <p> 388 * This abbreviation only occurs if the following criteria is met: 389 * </p> 390 * <ul> 391 * <li>Neither the String for abbreviation nor the replacement String are null or empty</li> 392 * <li>The length to truncate to is less than the length of the supplied String</li> 393 * <li>The length to truncate to is greater than 0</li> 394 * <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 395 * abbreviation</li> 396 * </ul> 397 * <p> 398 * Otherwise, the returned String will be the same as the supplied String for abbreviation. 399 * </p> 400 * 401 * <pre> 402 * StringUtils.abbreviateMiddle(null, null, 0) = null 403 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 404 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 405 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 406 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 407 * </pre> 408 * 409 * @param str the String to abbreviate, may be null. 410 * @param middle the String to replace the middle characters with, may be null. 411 * @param length the length to abbreviate {@code str} to. 412 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 413 * @since 2.5 414 */ 415 public static String abbreviateMiddle(final String str, final String middle, final int length) { 416 if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) { 417 return str; 418 } 419 final int targetString = length - middle.length(); 420 final int startOffset = targetString / 2 + targetString % 2; 421 final int endOffset = str.length() - targetString / 2; 422 return str.substring(0, startOffset) + middle + str.substring(endOffset); 423 } 424 425 /** 426 * Appends the suffix to the end of the string if the string does not already end with any of the suffixes. 427 * 428 * <pre> 429 * StringUtils.appendIfMissing(null, null) = null 430 * StringUtils.appendIfMissing("abc", null) = "abc" 431 * StringUtils.appendIfMissing("", "xyz" = "xyz" 432 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 433 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 434 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 435 * </pre> 436 * <p> 437 * With additional suffixes, 438 * </p> 439 * 440 * <pre> 441 * StringUtils.appendIfMissing(null, null, null) = null 442 * StringUtils.appendIfMissing("abc", null, null) = "abc" 443 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 444 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 445 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 446 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 447 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 448 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 449 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 450 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 451 * </pre> 452 * 453 * @param str The string. 454 * @param suffix The suffix to append to the end of the string. 455 * @param suffixes Additional suffixes that are valid terminators. 456 * @return A new String if suffix was appended, the same string otherwise. 457 * @since 3.2 458 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}. 459 */ 460 @Deprecated 461 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 462 return Strings.CS.appendIfMissing(str, suffix, suffixes); 463 } 464 465 /** 466 * Appends the suffix to the end of the string if the string does not 467 * already end, case-insensitive, with any of the suffixes. 468 * 469 * <pre> 470 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 471 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 472 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 473 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 474 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 475 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 476 * </pre> 477 * <p>With additional suffixes,</p> 478 * <pre> 479 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 480 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 481 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 482 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 483 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 484 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "abcxyz" 485 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 486 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 487 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 488 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 489 * </pre> 490 * 491 * @param str The string. 492 * @param suffix The suffix to append to the end of the string. 493 * @param suffixes Additional suffixes that are valid terminators. 494 * @return A new String if suffix was appended, the same string otherwise. 495 * @since 3.2 496 * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}. 497 */ 498 @Deprecated 499 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 500 return Strings.CI.appendIfMissing(str, suffix, suffixes); 501 } 502 503 /** 504 * Computes the capacity required for a StringBuilder to hold {@code items} of {@code maxElementChars} characters plus the separators between them. The 505 * separator is assumed to be 1 character. 506 * 507 * @param count The number of items. 508 * @param maxElementChars The maximum number of characters per item. 509 * @return A StringBuilder with the appropriate capacity. 510 */ 511 private static StringBuilder capacity(final int count, final byte maxElementChars) { 512 return new StringBuilder(count * maxElementChars + count - 1); 513 } 514 515 /** 516 * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed. 517 * 518 * <p> 519 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}. 520 * </p> 521 * 522 * <pre> 523 * StringUtils.capitalize(null) = null 524 * StringUtils.capitalize("") = "" 525 * StringUtils.capitalize("cat") = "Cat" 526 * StringUtils.capitalize("cAt") = "CAt" 527 * StringUtils.capitalize("'cat'") = "'cat'" 528 * </pre> 529 * 530 * @param str the String to capitalize, may be null. 531 * @return the capitalized String, {@code null} if null String input. 532 * @see org.apache.commons.text.WordUtils#capitalize(String) 533 * @see #uncapitalize(String) 534 * @since 2.0 535 */ 536 public static String capitalize(final String str) { 537 if (isEmpty(str)) { 538 return str; 539 } 540 final int firstCodepoint = str.codePointAt(0); 541 final int newCodePoint = Character.toTitleCase(firstCodepoint); 542 if (firstCodepoint == newCodePoint) { 543 // already capitalized 544 return str; 545 } 546 final int[] newCodePoints = str.codePoints().toArray(); 547 newCodePoints[0] = newCodePoint; // copy the first code point 548 return new String(newCodePoints, 0, newCodePoints.length); 549 } 550 551 /** 552 * Centers a String in a larger String of size {@code size} using the space character (' '). 553 * 554 * <p> 555 * 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 556 * zero. 557 * </p> 558 * 559 * <p> 560 * Equivalent to {@code center(str, size, " ")}. 561 * </p> 562 * 563 * <pre> 564 * StringUtils.center(null, *) = null 565 * StringUtils.center("", 4) = " " 566 * StringUtils.center("ab", -1) = "ab" 567 * StringUtils.center("ab", 4) = " ab " 568 * StringUtils.center("abcd", 2) = "abcd" 569 * StringUtils.center("a", 4) = " a " 570 * </pre> 571 * 572 * @param str the String to center, may be null. 573 * @param size the int size of new String, negative treated as zero. 574 * @return centered String, {@code null} if null String input. 575 */ 576 public static String center(final String str, final int size) { 577 return center(str, size, ' '); 578 } 579 580 /** 581 * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with. 582 * 583 * <p> 584 * 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. 585 * </p> 586 * 587 * <pre> 588 * StringUtils.center(null, *, *) = null 589 * StringUtils.center("", 4, ' ') = " " 590 * StringUtils.center("ab", -1, ' ') = "ab" 591 * StringUtils.center("ab", 4, ' ') = " ab " 592 * StringUtils.center("abcd", 2, ' ') = "abcd" 593 * StringUtils.center("a", 4, ' ') = " a " 594 * StringUtils.center("a", 4, 'y') = "yayy" 595 * </pre> 596 * 597 * @param str the String to center, may be null. 598 * @param size the int size of new String, negative treated as zero. 599 * @param padChar the character to pad the new String with. 600 * @return centered String, {@code null} if null String input. 601 * @since 2.0 602 */ 603 public static String center(String str, final int size, final char padChar) { 604 if (str == null || size <= 0) { 605 return str; 606 } 607 final int strLen = str.length(); 608 final int pads = size - strLen; 609 if (pads <= 0) { 610 return str; 611 } 612 str = leftPad(str, strLen + pads / 2, padChar); 613 return rightPad(str, size, padChar); 614 } 615 616 /** 617 * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with. 618 * 619 * <p> 620 * 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. 621 * </p> 622 * 623 * <pre> 624 * StringUtils.center(null, *, *) = null 625 * StringUtils.center("", 4, " ") = " " 626 * StringUtils.center("ab", -1, " ") = "ab" 627 * StringUtils.center("ab", 4, " ") = " ab " 628 * StringUtils.center("abcd", 2, " ") = "abcd" 629 * StringUtils.center("a", 4, " ") = " a " 630 * StringUtils.center("a", 4, "yz") = "yayz" 631 * StringUtils.center("abc", 7, null) = " abc " 632 * StringUtils.center("abc", 7, "") = " abc " 633 * </pre> 634 * 635 * @param str the String to center, may be null. 636 * @param size the int size of new String, negative treated as zero. 637 * @param padStr the String to pad the new String with, must not be null or empty. 638 * @return centered String, {@code null} if null String input. 639 * @throws IllegalArgumentException if padStr is {@code null} or empty. 640 */ 641 public static String center(String str, final int size, String padStr) { 642 if (str == null || size <= 0) { 643 return str; 644 } 645 if (isEmpty(padStr)) { 646 padStr = SPACE; 647 } 648 final int strLen = str.length(); 649 final int pads = size - strLen; 650 if (pads <= 0) { 651 return str; 652 } 653 str = leftPad(str, strLen + pads / 2, padStr); 654 return rightPad(str, size, padStr); 655 } 656 657 /** 658 * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is "{@code \n}", "{@code \r}", or 659 * "{@code \r\n}". 660 * 661 * <p> 662 * NOTE: This method changed in 2.0. It now more closely matches Perl chomp. 663 * </p> 664 * 665 * <pre> 666 * StringUtils.chomp(null) = null 667 * StringUtils.chomp("") = "" 668 * StringUtils.chomp("abc \r") = "abc " 669 * StringUtils.chomp("abc\n") = "abc" 670 * StringUtils.chomp("abc\r\n") = "abc" 671 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 672 * StringUtils.chomp("abc\n\r") = "abc\n" 673 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 674 * StringUtils.chomp("\r") = "" 675 * StringUtils.chomp("\n") = "" 676 * StringUtils.chomp("\r\n") = "" 677 * </pre> 678 * 679 * @param str the String to chomp a newline from, may be null. 680 * @return String without newline, {@code null} if null String input. 681 */ 682 public static String chomp(final String str) { 683 if (isEmpty(str)) { 684 return str; 685 } 686 if (str.length() == 1) { 687 final char ch = str.charAt(0); 688 if (ch == CharUtils.CR || ch == CharUtils.LF) { 689 return EMPTY; 690 } 691 return str; 692 } 693 int lastIdx = str.length() - 1; 694 final char last = str.charAt(lastIdx); 695 if (last == CharUtils.LF) { 696 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 697 lastIdx--; 698 } 699 } else if (last != CharUtils.CR) { 700 lastIdx++; 701 } 702 return str.substring(0, lastIdx); 703 } 704 705 /** 706 * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone. 707 * 708 * <p> 709 * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use 710 * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}. 711 * </p> 712 * 713 * <pre> 714 * StringUtils.chomp(null, *) = null 715 * StringUtils.chomp("", *) = "" 716 * StringUtils.chomp("foobar", "bar") = "foo" 717 * StringUtils.chomp("foobar", "baz") = "foobar" 718 * StringUtils.chomp("foo", "foo") = "" 719 * StringUtils.chomp("foo ", "foo") = "foo " 720 * StringUtils.chomp(" foo", "foo") = " " 721 * StringUtils.chomp("foo", "foooo") = "foo" 722 * StringUtils.chomp("foo", "") = "foo" 723 * StringUtils.chomp("foo", null) = "foo" 724 * </pre> 725 * 726 * @param str the String to chomp from, may be null. 727 * @param separator separator String, may be null. 728 * @return String without trailing separator, {@code null} if null String input. 729 * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead. 730 */ 731 @Deprecated 732 public static String chomp(final String str, final String separator) { 733 return Strings.CS.removeEnd(str, separator); 734 } 735 736 /** 737 * Removes the last character from a String. 738 * 739 * <p> 740 * If the String ends in {@code \r\n}, then remove both of them. 741 * </p> 742 * 743 * <pre> 744 * StringUtils.chop(null) = null 745 * StringUtils.chop("") = "" 746 * StringUtils.chop("abc \r") = "abc " 747 * StringUtils.chop("abc\n") = "abc" 748 * StringUtils.chop("abc\r\n") = "abc" 749 * StringUtils.chop("abc") = "ab" 750 * StringUtils.chop("abc\nabc") = "abc\nab" 751 * StringUtils.chop("a") = "" 752 * StringUtils.chop("\r") = "" 753 * StringUtils.chop("\n") = "" 754 * StringUtils.chop("\r\n") = "" 755 * </pre> 756 * 757 * @param str the String to chop last character from, may be null. 758 * @return String without last character, {@code null} if null String input. 759 */ 760 public static String chop(final String str) { 761 if (str == null) { 762 return null; 763 } 764 final int strLen = str.length(); 765 if (strLen < 2) { 766 return EMPTY; 767 } 768 final int lastIdx = strLen - 1; 769 final String ret = str.substring(0, lastIdx); 770 final char last = str.charAt(lastIdx); 771 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 772 return ret.substring(0, lastIdx - 1); 773 } 774 return ret; 775 } 776 777 /** 778 * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning : 779 * <ul> 780 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 781 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 782 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 783 * </ul> 784 * 785 * <p> 786 * This is a {@code null} safe version of: 787 * </p> 788 * 789 * <pre> 790 * str1.compareTo(str2) 791 * </pre> 792 * 793 * <p> 794 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. 795 * </p> 796 * 797 * <pre>{@code 798 * StringUtils.compare(null, null) = 0 799 * StringUtils.compare(null , "a") < 0 800 * StringUtils.compare("a", null) > 0 801 * StringUtils.compare("abc", "abc") = 0 802 * StringUtils.compare("a", "b") < 0 803 * StringUtils.compare("b", "a") > 0 804 * StringUtils.compare("a", "B") > 0 805 * StringUtils.compare("ab", "abc") < 0 806 * }</pre> 807 * 808 * @param str1 the String to compare from. 809 * @param str2 the String to compare to. 810 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal or greater than {@code str2}. 811 * @see #compare(String, String, boolean) 812 * @see String#compareTo(String) 813 * @since 3.5 814 * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}. 815 */ 816 @Deprecated 817 public static int compare(final String str1, final String str2) { 818 return Strings.CS.compare(str1, str2); 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} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. 839 * </p> 840 * 841 * <pre>{@code 842 * StringUtils.compare(null, null, *) = 0 843 * StringUtils.compare(null , "a", true) < 0 844 * StringUtils.compare(null , "a", false) > 0 845 * StringUtils.compare("a", null, true) > 0 846 * StringUtils.compare("a", null, false) < 0 847 * StringUtils.compare("abc", "abc", *) = 0 848 * StringUtils.compare("a", "b", *) < 0 849 * StringUtils.compare("b", "a", *) > 0 850 * StringUtils.compare("a", "B", *) > 0 851 * StringUtils.compare("ab", "abc", *) < 0 852 * }</pre> 853 * 854 * @param str1 the String to compare from. 855 * @param str2 the String to compare to. 856 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 857 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}. 858 * @see String#compareTo(String) 859 * @since 3.5 860 */ 861 public static int compare(final String str1, final String str2, final boolean nullIsLess) { 862 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 863 return 0; 864 } 865 if (str1 == null) { 866 return nullIsLess ? -1 : 1; 867 } 868 if (str2 == null) { 869 return nullIsLess ? 1 : -1; 870 } 871 return str1.compareTo(str2); 872 } 873 874 /** 875 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 876 * <ul> 877 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 878 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 879 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 880 * </ul> 881 * 882 * <p> 883 * This is a {@code null} safe version of: 884 * </p> 885 * 886 * <pre> 887 * str1.compareToIgnoreCase(str2) 888 * </pre> 889 * 890 * <p> 891 * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive. 892 * </p> 893 * 894 * <pre>{@code 895 * StringUtils.compareIgnoreCase(null, null) = 0 896 * StringUtils.compareIgnoreCase(null , "a") < 0 897 * StringUtils.compareIgnoreCase("a", null) > 0 898 * StringUtils.compareIgnoreCase("abc", "abc") = 0 899 * StringUtils.compareIgnoreCase("abc", "ABC") = 0 900 * StringUtils.compareIgnoreCase("a", "b") < 0 901 * StringUtils.compareIgnoreCase("b", "a") > 0 902 * StringUtils.compareIgnoreCase("a", "B") < 0 903 * StringUtils.compareIgnoreCase("A", "b") < 0 904 * StringUtils.compareIgnoreCase("ab", "ABC") < 0 905 * }</pre> 906 * 907 * @param str1 the String to compare from. 908 * @param str2 the String to compare to. 909 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 910 * @see #compareIgnoreCase(String, String, boolean) 911 * @see String#compareToIgnoreCase(String) 912 * @since 3.5 913 * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}. 914 */ 915 @Deprecated 916 public static int compareIgnoreCase(final String str1, final String str2) { 917 return Strings.CI.compare(str1, str2); 918 } 919 920 /** 921 * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning : 922 * <ul> 923 * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> 924 * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> 925 * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> 926 * </ul> 927 * 928 * <p> 929 * This is a {@code null} safe version of : 930 * </p> 931 * <pre> 932 * str1.compareToIgnoreCase(str2) 933 * </pre> 934 * 935 * <p> 936 * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case 937 * insensitive. 938 * </p> 939 * 940 * <pre>{@code 941 * StringUtils.compareIgnoreCase(null, null, *) = 0 942 * StringUtils.compareIgnoreCase(null , "a", true) < 0 943 * StringUtils.compareIgnoreCase(null , "a", false) > 0 944 * StringUtils.compareIgnoreCase("a", null, true) > 0 945 * StringUtils.compareIgnoreCase("a", null, false) < 0 946 * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 947 * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 948 * StringUtils.compareIgnoreCase("a", "b", *) < 0 949 * StringUtils.compareIgnoreCase("b", "a", *) > 0 950 * StringUtils.compareIgnoreCase("a", "B", *) < 0 951 * StringUtils.compareIgnoreCase("A", "b", *) < 0 952 * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 953 * }</pre> 954 * 955 * @param str1 the String to compare from. 956 * @param str2 the String to compare to. 957 * @param nullIsLess whether consider {@code null} value less than non-{@code null} value. 958 * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences. 959 * @see String#compareToIgnoreCase(String) 960 * @since 3.5 961 */ 962 public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { 963 if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null 964 return 0; 965 } 966 if (str1 == null) { 967 return nullIsLess ? -1 : 1; 968 } 969 if (str2 == null) { 970 return nullIsLess ? 1 : -1; 971 } 972 return str1.compareToIgnoreCase(str2); 973 } 974 975 /** 976 * Tests if CharSequence contains a search CharSequence, handling {@code null}. 977 * This method uses {@link String#indexOf(String)} if possible. 978 * 979 * <p>A {@code null} CharSequence will return {@code false}.</p> 980 * 981 * <pre> 982 * StringUtils.contains(null, *) = false 983 * StringUtils.contains(*, null) = false 984 * StringUtils.contains("", "") = true 985 * StringUtils.contains("abc", "") = true 986 * StringUtils.contains("abc", "a") = true 987 * StringUtils.contains("abc", "z") = false 988 * </pre> 989 * 990 * @param seq the CharSequence to check, may be null 991 * @param searchSeq the CharSequence to find, may be null 992 * @return true if the CharSequence contains the search CharSequence, 993 * false if not or {@code null} string input 994 * @since 2.0 995 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 996 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}. 997 */ 998 @Deprecated 999 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 1000 return Strings.CS.contains(seq, searchSeq); 1001 } 1002 1003 /** 1004 * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible. 1005 * 1006 * <p> 1007 * A {@code null} or empty ("") CharSequence will return {@code false}. 1008 * </p> 1009 * 1010 * <pre> 1011 * StringUtils.contains(null, *) = false 1012 * StringUtils.contains("", *) = false 1013 * StringUtils.contains("abc", 'a') = true 1014 * StringUtils.contains("abc", 'z') = false 1015 * </pre> 1016 * 1017 * @param seq the CharSequence to check, may be null 1018 * @param searchChar the character to find 1019 * @return true if the CharSequence contains the search character, false if not or {@code null} string input 1020 * @since 2.0 1021 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1022 */ 1023 public static boolean contains(final CharSequence seq, final int searchChar) { 1024 if (isEmpty(seq)) { 1025 return false; 1026 } 1027 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1028 } 1029 1030 /** 1031 * Tests if the CharSequence contains any character in the given set of characters. 1032 * 1033 * <p> 1034 * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}. 1035 * </p> 1036 * 1037 * <pre> 1038 * StringUtils.containsAny(null, *) = false 1039 * StringUtils.containsAny("", *) = false 1040 * StringUtils.containsAny(*, null) = false 1041 * StringUtils.containsAny(*, []) = false 1042 * StringUtils.containsAny("zzabyycdxx", 'z', 'a') = true 1043 * StringUtils.containsAny("zzabyycdxx", 'b', 'y') = true 1044 * StringUtils.containsAny("zzabyycdxx", 'z', 'y') = true 1045 * StringUtils.containsAny("aba", 'z]) = false 1046 * </pre> 1047 * 1048 * @param cs the CharSequence to check, may be null. 1049 * @param searchChars the chars to search for, may be null. 1050 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input. 1051 * @since 2.4 1052 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1053 */ 1054 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1055 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1056 return false; 1057 } 1058 final int csLength = cs.length(); 1059 final int searchLength = searchChars.length; 1060 final int csLast = csLength - 1; 1061 final int searchLast = searchLength - 1; 1062 for (int i = 0; i < csLength; i++) { 1063 final char ch = cs.charAt(i); 1064 for (int j = 0; j < searchLength; j++) { 1065 if (searchChars[j] == ch) { 1066 if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1067 return true; 1068 } 1069 } 1070 } 1071 } 1072 return false; 1073 } 1074 1075 /** 1076 * Tests if the CharSequence contains any character in the given set of characters. 1077 * 1078 * <p> 1079 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}. 1080 * </p> 1081 * 1082 * <pre> 1083 * StringUtils.containsAny(null, *) = false 1084 * StringUtils.containsAny("", *) = false 1085 * StringUtils.containsAny(*, null) = false 1086 * StringUtils.containsAny(*, "") = false 1087 * StringUtils.containsAny("zzabyycdxx", "za") = true 1088 * StringUtils.containsAny("zzabyycdxx", "by") = true 1089 * StringUtils.containsAny("zzabyycdxx", "zy") = true 1090 * StringUtils.containsAny("zzabyycdxx", "\tx") = true 1091 * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true 1092 * StringUtils.containsAny("aba", "z") = false 1093 * </pre> 1094 * 1095 * @param cs the CharSequence to check, may be null. 1096 * @param searchChars the chars to search for, may be null. 1097 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input. 1098 * @since 2.4 1099 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1100 */ 1101 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1102 if (searchChars == null) { 1103 return false; 1104 } 1105 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1106 } 1107 1108 /** 1109 * Tests if the CharSequence contains any of the CharSequences in the given array. 1110 * 1111 * <p> 1112 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1113 * return {@code false}. 1114 * </p> 1115 * 1116 * <pre> 1117 * StringUtils.containsAny(null, *) = false 1118 * StringUtils.containsAny("", *) = false 1119 * StringUtils.containsAny(*, null) = false 1120 * StringUtils.containsAny(*, []) = false 1121 * StringUtils.containsAny("abcd", "ab", null) = true 1122 * StringUtils.containsAny("abcd", "ab", "cd") = true 1123 * StringUtils.containsAny("abc", "d", "abc") = true 1124 * </pre> 1125 * 1126 * @param cs The CharSequence to check, may be null. 1127 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1128 * null as well. 1129 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise. 1130 * @since 3.4 1131 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}. 1132 */ 1133 @Deprecated 1134 public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) { 1135 return Strings.CS.containsAny(cs, searchCharSequences); 1136 } 1137 1138 /** 1139 * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case. 1140 * 1141 * <p> 1142 * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will 1143 * return {@code false}. 1144 * </p> 1145 * 1146 * <pre> 1147 * StringUtils.containsAny(null, *) = false 1148 * StringUtils.containsAny("", *) = false 1149 * StringUtils.containsAny(*, null) = false 1150 * StringUtils.containsAny(*, []) = false 1151 * StringUtils.containsAny("abcd", "ab", null) = true 1152 * StringUtils.containsAny("abcd", "ab", "cd") = true 1153 * StringUtils.containsAny("abc", "d", "abc") = true 1154 * StringUtils.containsAny("abc", "D", "ABC") = true 1155 * StringUtils.containsAny("ABC", "d", "abc") = true 1156 * </pre> 1157 * 1158 * @param cs The CharSequence to check, may be null. 1159 * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be 1160 * null as well. 1161 * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise 1162 * @since 3.12.0 1163 * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}. 1164 */ 1165 @Deprecated 1166 public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) { 1167 return Strings.CI.containsAny(cs, searchCharSequences); 1168 } 1169 1170 /** 1171 * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by 1172 * {@link String#equalsIgnoreCase(String)}. 1173 * 1174 * <p> 1175 * A {@code null} CharSequence will return {@code false}. 1176 * </p> 1177 * 1178 * <pre> 1179 * StringUtils.containsIgnoreCase(null, *) = false 1180 * StringUtils.containsIgnoreCase(*, null) = false 1181 * StringUtils.containsIgnoreCase("", "") = true 1182 * StringUtils.containsIgnoreCase("abc", "") = true 1183 * StringUtils.containsIgnoreCase("abc", "a") = true 1184 * StringUtils.containsIgnoreCase("abc", "z") = false 1185 * StringUtils.containsIgnoreCase("abc", "A") = true 1186 * StringUtils.containsIgnoreCase("abc", "Z") = false 1187 * </pre> 1188 * 1189 * @param str the CharSequence to check, may be null. 1190 * @param searchStr the CharSequence to find, may be null. 1191 * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input. 1192 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence). 1193 * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}. 1194 */ 1195 @Deprecated 1196 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1197 return Strings.CI.contains(str, searchStr); 1198 } 1199 1200 /** 1201 * Tests that the CharSequence does not contain certain characters. 1202 * 1203 * <p> 1204 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0) 1205 * always returns true. 1206 * </p> 1207 * 1208 * <pre> 1209 * StringUtils.containsNone(null, *) = true 1210 * StringUtils.containsNone(*, null) = true 1211 * StringUtils.containsNone("", *) = true 1212 * StringUtils.containsNone("ab", '') = true 1213 * StringUtils.containsNone("abab", 'x', 'y', 'z') = true 1214 * StringUtils.containsNone("ab1", 'x', 'y', 'z') = true 1215 * StringUtils.containsNone("abz", 'x', 'y', 'z') = false 1216 * </pre> 1217 * 1218 * @param cs the CharSequence to check, may be null. 1219 * @param searchChars an array of invalid chars, may be null. 1220 * @return true if it contains none of the invalid chars, or is null. 1221 * @since 2.0 1222 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1223 */ 1224 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1225 if (cs == null || searchChars == null) { 1226 return true; 1227 } 1228 final int csLen = cs.length(); 1229 final int csLast = csLen - 1; 1230 final int searchLen = searchChars.length; 1231 final int searchLast = searchLen - 1; 1232 for (int i = 0; i < csLen; i++) { 1233 final char ch = cs.charAt(i); 1234 for (int j = 0; j < searchLen; j++) { 1235 if (searchChars[j] == ch) { 1236 if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1237 return false; 1238 } 1239 } 1240 } 1241 } 1242 return true; 1243 } 1244 1245 /** 1246 * Tests that the CharSequence does not contain certain characters. 1247 * 1248 * <p> 1249 * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always 1250 * returns true. 1251 * </p> 1252 * 1253 * <pre> 1254 * StringUtils.containsNone(null, *) = true 1255 * StringUtils.containsNone(*, null) = true 1256 * StringUtils.containsNone("", *) = true 1257 * StringUtils.containsNone("ab", "") = true 1258 * StringUtils.containsNone("abab", "xyz") = true 1259 * StringUtils.containsNone("ab1", "xyz") = true 1260 * StringUtils.containsNone("abz", "xyz") = false 1261 * </pre> 1262 * 1263 * @param cs the CharSequence to check, may be null. 1264 * @param invalidChars a String of invalid chars, may be null. 1265 * @return true if it contains none of the invalid chars, or is null. 1266 * @since 2.0 1267 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1268 */ 1269 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1270 if (invalidChars == null) { 1271 return true; 1272 } 1273 return containsNone(cs, invalidChars.toCharArray()); 1274 } 1275 1276 /** 1277 * Tests if the CharSequence contains only certain characters. 1278 * 1279 * <p> 1280 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0) 1281 * always returns {@code true}. 1282 * </p> 1283 * 1284 * <pre> 1285 * StringUtils.containsOnly(null, *) = false 1286 * StringUtils.containsOnly(*, null) = false 1287 * StringUtils.containsOnly("", *) = true 1288 * StringUtils.containsOnly("ab", '') = false 1289 * StringUtils.containsOnly("abab", 'a', 'b', 'c') = true 1290 * StringUtils.containsOnly("ab1", 'a', 'b', 'c') = false 1291 * StringUtils.containsOnly("abz", 'a', 'b', 'c') = false 1292 * </pre> 1293 * 1294 * @param cs the String to check, may be null. 1295 * @param valid an array of valid chars, may be null. 1296 * @return true if it only contains valid chars and is non-null. 1297 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1298 */ 1299 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1300 // All these pre-checks are to maintain API with an older version 1301 if (valid == null || cs == null) { 1302 return false; 1303 } 1304 if (cs.length() == 0) { 1305 return true; 1306 } 1307 if (valid.length == 0) { 1308 return false; 1309 } 1310 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1311 } 1312 1313 /** 1314 * Tests if the CharSequence contains only certain characters. 1315 * 1316 * <p> 1317 * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0) 1318 * always returns {@code true}. 1319 * </p> 1320 * 1321 * <pre> 1322 * StringUtils.containsOnly(null, *) = false 1323 * StringUtils.containsOnly(*, null) = false 1324 * StringUtils.containsOnly("", *) = true 1325 * StringUtils.containsOnly("ab", "") = false 1326 * StringUtils.containsOnly("abab", "abc") = true 1327 * StringUtils.containsOnly("ab1", "abc") = false 1328 * StringUtils.containsOnly("abz", "abc") = false 1329 * </pre> 1330 * 1331 * @param cs the CharSequence to check, may be null. 1332 * @param validChars a String of valid chars, may be null. 1333 * @return true if it only contains valid chars and is non-null. 1334 * @since 2.0 1335 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1336 */ 1337 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1338 if (cs == null || validChars == null) { 1339 return false; 1340 } 1341 return containsOnly(cs, validChars.toCharArray()); 1342 } 1343 1344 /** 1345 * Tests whether the given CharSequence contains any whitespace characters. 1346 * 1347 * <p> 1348 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1349 * </p> 1350 * 1351 * <pre> 1352 * StringUtils.containsWhitespace(null) = false 1353 * StringUtils.containsWhitespace("") = false 1354 * StringUtils.containsWhitespace("ab") = false 1355 * StringUtils.containsWhitespace(" ab") = true 1356 * StringUtils.containsWhitespace("a b") = true 1357 * StringUtils.containsWhitespace("ab ") = true 1358 * </pre> 1359 * 1360 * @param seq the CharSequence to check (may be {@code null}). 1361 * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character. 1362 * @since 3.0 1363 */ 1364 public static boolean containsWhitespace(final CharSequence seq) { 1365 if (isEmpty(seq)) { 1366 return false; 1367 } 1368 final int strLen = seq.length(); 1369 for (int i = 0; i < strLen; i++) { 1370 if (Character.isWhitespace(seq.charAt(i))) { 1371 return true; 1372 } 1373 } 1374 return false; 1375 } 1376 1377 private static void convertRemainingAccentCharacters(final StringBuilder decomposed) { 1378 for (int i = 0; i < decomposed.length(); i++) { 1379 final char charAt = decomposed.charAt(i); 1380 switch (charAt) { 1381 case '\u0141': 1382 decomposed.setCharAt(i, 'L'); 1383 break; 1384 case '\u0142': 1385 decomposed.setCharAt(i, 'l'); 1386 break; 1387 // D with stroke 1388 case '\u0110': 1389 // LATIN CAPITAL LETTER D WITH STROKE 1390 decomposed.setCharAt(i, 'D'); 1391 break; 1392 case '\u0111': 1393 // LATIN SMALL LETTER D WITH STROKE 1394 decomposed.setCharAt(i, 'd'); 1395 break; 1396 // I with bar 1397 case '\u0197': 1398 decomposed.setCharAt(i, 'I'); 1399 break; 1400 case '\u0268': 1401 decomposed.setCharAt(i, 'i'); 1402 break; 1403 case '\u1D7B': 1404 decomposed.setCharAt(i, 'I'); 1405 break; 1406 case '\u1DA4': 1407 decomposed.setCharAt(i, 'i'); 1408 break; 1409 case '\u1DA7': 1410 decomposed.setCharAt(i, 'I'); 1411 break; 1412 // U with bar 1413 case '\u0244': 1414 // LATIN CAPITAL LETTER U BAR 1415 decomposed.setCharAt(i, 'U'); 1416 break; 1417 case '\u0289': 1418 // LATIN SMALL LETTER U BAR 1419 decomposed.setCharAt(i, 'u'); 1420 break; 1421 case '\u1D7E': 1422 // LATIN SMALL CAPITAL LETTER U WITH STROKE 1423 decomposed.setCharAt(i, 'U'); 1424 break; 1425 case '\u1DB6': 1426 // MODIFIER LETTER SMALL U BAR 1427 decomposed.setCharAt(i, 'u'); 1428 break; 1429 // T with stroke 1430 case '\u0166': 1431 // LATIN CAPITAL LETTER T WITH STROKE 1432 decomposed.setCharAt(i, 'T'); 1433 break; 1434 case '\u0167': 1435 // LATIN SMALL LETTER T WITH STROKE 1436 decomposed.setCharAt(i, 't'); 1437 break; 1438 default: 1439 break; 1440 } 1441 } 1442 } 1443 1444 /** 1445 * Counts how many times the char appears in the given string. 1446 * 1447 * <p> 1448 * A {@code null} or empty ("") String input returns {@code 0}. 1449 * </p> 1450 * 1451 * <pre> 1452 * StringUtils.countMatches(null, *) = 0 1453 * StringUtils.countMatches("", *) = 0 1454 * StringUtils.countMatches("abba", 0) = 0 1455 * StringUtils.countMatches("abba", 'a') = 2 1456 * StringUtils.countMatches("abba", 'b') = 2 1457 * StringUtils.countMatches("abba", 'x') = 0 1458 * </pre> 1459 * 1460 * @param str the CharSequence to check, may be null. 1461 * @param ch the char to count. 1462 * @return the number of occurrences, 0 if the CharSequence is {@code null}. 1463 * @since 3.4 1464 */ 1465 public static int countMatches(final CharSequence str, final char ch) { 1466 if (isEmpty(str)) { 1467 return 0; 1468 } 1469 int count = 0; 1470 // We could also call str.toCharArray() for faster lookups but that would generate more garbage. 1471 for (int i = 0; i < str.length(); i++) { 1472 if (ch == str.charAt(i)) { 1473 count++; 1474 } 1475 } 1476 return count; 1477 } 1478 1479 /** 1480 * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches. 1481 * 1482 * <p> 1483 * A {@code null} or empty ("") String input returns {@code 0}. 1484 * </p> 1485 * 1486 * <pre> 1487 * StringUtils.countMatches(null, *) = 0 1488 * StringUtils.countMatches("", *) = 0 1489 * StringUtils.countMatches("abba", null) = 0 1490 * StringUtils.countMatches("abba", "") = 0 1491 * StringUtils.countMatches("abba", "a") = 2 1492 * StringUtils.countMatches("abba", "ab") = 1 1493 * StringUtils.countMatches("abba", "xxx") = 0 1494 * StringUtils.countMatches("ababa", "aba") = 1 1495 * </pre> 1496 * 1497 * @param str the CharSequence to check, may be null. 1498 * @param sub the substring to count, may be null. 1499 * @return the number of occurrences, 0 if either CharSequence is {@code null}. 1500 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 1501 */ 1502 public static int countMatches(final CharSequence str, final CharSequence sub) { 1503 if (isEmpty(str) || isEmpty(sub)) { 1504 return 0; 1505 } 1506 int count = 0; 1507 int idx = 0; 1508 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 1509 count++; 1510 idx += sub.length(); 1511 } 1512 return count; 1513 } 1514 1515 /** 1516 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1517 * {@code null}), the value of {@code defaultStr}. 1518 * 1519 * <p> 1520 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1521 * </p> 1522 * 1523 * <pre> 1524 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 1525 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 1526 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 1527 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 1528 * StringUtils.defaultIfBlank("", null) = null 1529 * </pre> 1530 * 1531 * @param <T> the specific kind of CharSequence. 1532 * @param str the CharSequence to check, may be null. 1533 * @param defaultStr the default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 1534 * {@code null}); may be null. 1535 * @return the passed in CharSequence, or the default. 1536 * @see StringUtils#defaultString(String, String) 1537 * @see #isBlank(CharSequence) 1538 */ 1539 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 1540 return isBlank(str) ? defaultStr : str; 1541 } 1542 1543 /** 1544 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}. 1545 * 1546 * <pre> 1547 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 1548 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 1549 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 1550 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 1551 * StringUtils.defaultIfEmpty("", null) = null 1552 * </pre> 1553 * 1554 * @param <T> the specific kind of CharSequence. 1555 * @param str the CharSequence to check, may be null. 1556 * @param defaultStr the default CharSequence to return if the input is empty ("") or {@code null}, may be null. 1557 * @return the passed in CharSequence, or the default. 1558 * @see StringUtils#defaultString(String, String) 1559 */ 1560 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 1561 return isEmpty(str) ? defaultStr : str; 1562 } 1563 1564 /** 1565 * Returns either the passed in String, or if the String is {@code null}, an empty String (""). 1566 * 1567 * <pre> 1568 * StringUtils.defaultString(null) = "" 1569 * StringUtils.defaultString("") = "" 1570 * StringUtils.defaultString("bat") = "bat" 1571 * </pre> 1572 * 1573 * @param str the String to check, may be null. 1574 * @return the passed in String, or the empty String if it was {@code null}. 1575 * @see Objects#toString(Object, String) 1576 * @see String#valueOf(Object) 1577 */ 1578 public static String defaultString(final String str) { 1579 return Objects.toString(str, EMPTY); 1580 } 1581 1582 /** 1583 * Returns either the given String, or if the String is {@code null}, {@code nullDefault}. 1584 * 1585 * <pre> 1586 * StringUtils.defaultString(null, "NULL") = "NULL" 1587 * StringUtils.defaultString("", "NULL") = "" 1588 * StringUtils.defaultString("bat", "NULL") = "bat" 1589 * </pre> 1590 * <p> 1591 * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}: 1592 * </p> 1593 * 1594 * <pre> 1595 * Objects.toString(null, "NULL") = "NULL" 1596 * Objects.toString("", "NULL") = "" 1597 * Objects.toString("bat", "NULL") = "bat" 1598 * </pre> 1599 * 1600 * @param str the String to check, may be null. 1601 * @param nullDefault the default String to return if the input is {@code null}, may be null. 1602 * @return the passed in String, or the default if it was {@code null}. 1603 * @see Objects#toString(Object, String) 1604 * @see String#valueOf(Object) 1605 * @deprecated Use {@link Objects#toString(Object, String)}. 1606 */ 1607 @Deprecated 1608 public static String defaultString(final String str, final String nullDefault) { 1609 return Objects.toString(str, nullDefault); 1610 } 1611 1612 /** 1613 * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}. 1614 * 1615 * <pre> 1616 * StringUtils.deleteWhitespace(null) = null 1617 * StringUtils.deleteWhitespace("") = "" 1618 * StringUtils.deleteWhitespace("abc") = "abc" 1619 * StringUtils.deleteWhitespace(" ab c ") = "abc" 1620 * </pre> 1621 * 1622 * @param str the String to delete whitespace from, may be null. 1623 * @return the String without whitespaces, {@code null} if null String input. 1624 */ 1625 public static String deleteWhitespace(final String str) { 1626 if (isEmpty(str)) { 1627 return str; 1628 } 1629 final int sz = str.length(); 1630 final char[] chs = new char[sz]; 1631 int count = 0; 1632 for (int i = 0; i < sz; i++) { 1633 if (!Character.isWhitespace(str.charAt(i))) { 1634 chs[count++] = str.charAt(i); 1635 } 1636 } 1637 if (count == sz) { 1638 return str; 1639 } 1640 if (count == 0) { 1641 return EMPTY; 1642 } 1643 return new String(chs, 0, count); 1644 } 1645 1646 /** 1647 * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's 1648 * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c". 1649 * 1650 * <p> 1651 * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}. 1652 * </p> 1653 * 1654 * <pre> 1655 * StringUtils.difference(null, null) = null 1656 * StringUtils.difference("", "") = "" 1657 * StringUtils.difference("", "abc") = "abc" 1658 * StringUtils.difference("abc", "") = "" 1659 * StringUtils.difference("abc", "abc") = "" 1660 * StringUtils.difference("abc", "ab") = "" 1661 * StringUtils.difference("ab", "abxyz") = "xyz" 1662 * StringUtils.difference("abcde", "abxyz") = "xyz" 1663 * StringUtils.difference("abcde", "xyz") = "xyz" 1664 * </pre> 1665 * 1666 * @param str1 the first String, may be null. 1667 * @param str2 the second String, may be null. 1668 * @return the portion of str2 where it differs from str1; returns the empty String if they are equal. 1669 * @see #indexOfDifference(CharSequence,CharSequence) 1670 * @since 2.0 1671 */ 1672 public static String difference(final String str1, final String str2) { 1673 if (str1 == null) { 1674 return str2; 1675 } 1676 if (str2 == null) { 1677 return str1; 1678 } 1679 final int at = indexOfDifference(str1, str2); 1680 if (at == INDEX_NOT_FOUND) { 1681 return EMPTY; 1682 } 1683 return str2.substring(at); 1684 } 1685 1686 /** 1687 * Tests if a CharSequence ends with a specified suffix. 1688 * 1689 * <p> 1690 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 1691 * </p> 1692 * 1693 * <pre> 1694 * StringUtils.endsWith(null, null) = true 1695 * StringUtils.endsWith(null, "def") = false 1696 * StringUtils.endsWith("abcdef", null) = false 1697 * StringUtils.endsWith("abcdef", "def") = true 1698 * StringUtils.endsWith("ABCDEF", "def") = false 1699 * StringUtils.endsWith("ABCDEF", "cde") = false 1700 * StringUtils.endsWith("ABCDEF", "") = true 1701 * </pre> 1702 * 1703 * @param str the CharSequence to check, may be null. 1704 * @param suffix the suffix to find, may be null. 1705 * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}. 1706 * @see String#endsWith(String) 1707 * @since 2.4 1708 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 1709 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}. 1710 */ 1711 @Deprecated 1712 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 1713 return Strings.CS.endsWith(str, suffix); 1714 } 1715 1716 /** 1717 * Tests if a CharSequence ends with any of the provided case-sensitive suffixes. 1718 * 1719 * <pre> 1720 * StringUtils.endsWithAny(null, null) = false 1721 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 1722 * StringUtils.endsWithAny("abcxyz", null) = false 1723 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 1724 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 1725 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 1726 * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true 1727 * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false 1728 * </pre> 1729 * 1730 * @param sequence the CharSequence to check, may be null. 1731 * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}. 1732 * @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 1733 * of the provided case-sensitive {@code searchStrings}. 1734 * @see StringUtils#endsWith(CharSequence, CharSequence) 1735 * @since 3.0 1736 * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}. 1737 */ 1738 @Deprecated 1739 public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 1740 return Strings.CS.endsWithAny(sequence, searchStrings); 1741 } 1742 1743 /** 1744 * Case-insensitive check if a CharSequence ends with a specified suffix. 1745 * 1746 * <p> 1747 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 1748 * </p> 1749 * 1750 * <pre> 1751 * StringUtils.endsWithIgnoreCase(null, null) = true 1752 * StringUtils.endsWithIgnoreCase(null, "def") = false 1753 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 1754 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 1755 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 1756 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 1757 * </pre> 1758 * 1759 * @param str the CharSequence to check, may be null 1760 * @param suffix the suffix to find, may be null 1761 * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null} 1762 * @see String#endsWith(String) 1763 * @since 2.4 1764 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 1765 * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)}. 1766 */ 1767 @Deprecated 1768 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 1769 return Strings.CI.endsWith(str, suffix); 1770 } 1771 1772 /** 1773 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters. 1774 * 1775 * <p> 1776 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>. 1777 * </p> 1778 * 1779 * <pre> 1780 * StringUtils.equals(null, null) = true 1781 * StringUtils.equals(null, "abc") = false 1782 * StringUtils.equals("abc", null) = false 1783 * StringUtils.equals("abc", "abc") = true 1784 * StringUtils.equals("abc", "ABC") = false 1785 * </pre> 1786 * 1787 * @param cs1 the first CharSequence, may be {@code null}. 1788 * @param cs2 the second CharSequence, may be {@code null}. 1789 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}. 1790 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 1791 * @see Object#equals(Object) 1792 * @see #equalsIgnoreCase(CharSequence, CharSequence) 1793 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}. 1794 */ 1795 @Deprecated 1796 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 1797 return Strings.CS.equals(cs1, cs2); 1798 } 1799 1800 /** 1801 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the 1802 * {@code searchStrings}. 1803 * 1804 * <pre> 1805 * StringUtils.equalsAny(null, (CharSequence[]) null) = false 1806 * StringUtils.equalsAny(null, null, null) = true 1807 * StringUtils.equalsAny(null, "abc", "def") = false 1808 * StringUtils.equalsAny("abc", null, "def") = false 1809 * StringUtils.equalsAny("abc", "abc", "def") = true 1810 * StringUtils.equalsAny("abc", "ABC", "DEF") = false 1811 * </pre> 1812 * 1813 * @param string to compare, may be {@code null}. 1814 * @param searchStrings a vararg of strings, may be {@code null}. 1815 * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is 1816 * null or contains no matches. 1817 * @since 3.5 1818 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}. 1819 */ 1820 @Deprecated 1821 public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) { 1822 return Strings.CS.equalsAny(string, searchStrings); 1823 } 1824 1825 /** 1826 * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, 1827 * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case. 1828 * 1829 * <pre> 1830 * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false 1831 * StringUtils.equalsAnyIgnoreCase(null, null, null) = true 1832 * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false 1833 * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false 1834 * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true 1835 * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true 1836 * </pre> 1837 * 1838 * @param string to compare, may be {@code null}. 1839 * @param searchStrings a vararg of strings, may be {@code null}. 1840 * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings}; 1841 * {@code false} if {@code searchStrings} is null or contains no matches. 1842 * @since 3.5 1843 * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI.equalsAny(CharSequence, CharSequence...)}. 1844 */ 1845 @Deprecated 1846 public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) { 1847 return Strings.CI.equalsAny(string, searchStrings); 1848 } 1849 1850 /** 1851 * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case. 1852 * 1853 * <p> 1854 * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>. 1855 * </p> 1856 * 1857 * <pre> 1858 * StringUtils.equalsIgnoreCase(null, null) = true 1859 * StringUtils.equalsIgnoreCase(null, "abc") = false 1860 * StringUtils.equalsIgnoreCase("abc", null) = false 1861 * StringUtils.equalsIgnoreCase("abc", "abc") = true 1862 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 1863 * </pre> 1864 * 1865 * @param cs1 the first CharSequence, may be {@code null}. 1866 * @param cs2 the second CharSequence, may be {@code null}. 1867 * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}. 1868 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 1869 * @see #equals(CharSequence, CharSequence) 1870 * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}. 1871 */ 1872 @Deprecated 1873 public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) { 1874 return Strings.CI.equals(cs1, cs2); 1875 } 1876 1877 /** 1878 * Returns the first value in the array which is not empty (""), {@code null} or whitespace only. 1879 * 1880 * <p> 1881 * Whitespace is defined by {@link Character#isWhitespace(char)}. 1882 * </p> 1883 * 1884 * <p> 1885 * If all values are blank or the array is {@code null} or empty then {@code null} is returned. 1886 * </p> 1887 * 1888 * <pre> 1889 * StringUtils.firstNonBlank(null, null, null) = null 1890 * StringUtils.firstNonBlank(null, "", " ") = null 1891 * StringUtils.firstNonBlank("abc") = "abc" 1892 * StringUtils.firstNonBlank(null, "xyz") = "xyz" 1893 * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz" 1894 * StringUtils.firstNonBlank(null, "xyz", "abc") = "xyz" 1895 * StringUtils.firstNonBlank() = null 1896 * </pre> 1897 * 1898 * @param <T> the specific kind of CharSequence. 1899 * @param values the values to test, may be {@code null} or empty. 1900 * @return the first value from {@code values} which is not blank, or {@code null} if there are no non-blank values. 1901 * @since 3.8 1902 */ 1903 @SafeVarargs 1904 public static <T extends CharSequence> T firstNonBlank(final T... values) { 1905 if (values != null) { 1906 for (final T val : values) { 1907 if (isNotBlank(val)) { 1908 return val; 1909 } 1910 } 1911 } 1912 return null; 1913 } 1914 1915 /** 1916 * Returns the first value in the array which is not empty. 1917 * 1918 * <p> 1919 * If all values are empty or the array is {@code null} or empty then {@code null} is returned. 1920 * </p> 1921 * 1922 * <pre> 1923 * StringUtils.firstNonEmpty(null, null, null) = null 1924 * StringUtils.firstNonEmpty(null, null, "") = null 1925 * StringUtils.firstNonEmpty(null, "", " ") = " " 1926 * StringUtils.firstNonEmpty("abc") = "abc" 1927 * StringUtils.firstNonEmpty(null, "xyz") = "xyz" 1928 * StringUtils.firstNonEmpty("", "xyz") = "xyz" 1929 * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz" 1930 * StringUtils.firstNonEmpty() = null 1931 * </pre> 1932 * 1933 * @param <T> the specific kind of CharSequence. 1934 * @param values the values to test, may be {@code null} or empty. 1935 * @return the first value from {@code values} which is not empty, or {@code null} if there are no non-empty values. 1936 * @since 3.8 1937 */ 1938 @SafeVarargs 1939 public static <T extends CharSequence> T firstNonEmpty(final T... values) { 1940 if (values != null) { 1941 for (final T val : values) { 1942 if (isNotEmpty(val)) { 1943 return val; 1944 } 1945 } 1946 } 1947 return null; 1948 } 1949 1950 /** 1951 * Calls {@link String#getBytes(Charset)} in a null-safe manner. 1952 * 1953 * @param string input string. 1954 * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset. 1955 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise. 1956 * @see String#getBytes(Charset) 1957 * @since 3.10 1958 */ 1959 public static byte[] getBytes(final String string, final Charset charset) { 1960 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset)); 1961 } 1962 1963 /** 1964 * Calls {@link String#getBytes(String)} in a null-safe manner. 1965 * 1966 * @param string input string. 1967 * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset. 1968 * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise. 1969 * @throws UnsupportedEncodingException Thrown when the named charset is not supported. 1970 * @see String#getBytes(String) 1971 * @since 3.10 1972 */ 1973 public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException { 1974 return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset)); 1975 } 1976 1977 /** 1978 * Compares all Strings in an array and returns the initial sequence of characters that is common to all of them. 1979 * 1980 * <p> 1981 * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -> "i am a "} 1982 * </p> 1983 * 1984 * <pre> 1985 * StringUtils.getCommonPrefix(null) = "" 1986 * StringUtils.getCommonPrefix(new String[] {}) = "" 1987 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 1988 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 1989 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 1990 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 1991 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 1992 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 1993 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 1994 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 1995 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 1996 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 1997 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 1998 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 1999 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 2000 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 2001 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 2002 * </pre> 2003 * 2004 * @param strs array of String objects, entries may be null. 2005 * @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 2006 * if there is no common prefix. 2007 * @since 2.4 2008 */ 2009 public static String getCommonPrefix(final String... strs) { 2010 if (ArrayUtils.isEmpty(strs)) { 2011 return EMPTY; 2012 } 2013 final int smallestIndexOfDiff = indexOfDifference(strs); 2014 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 2015 // all strings were identical 2016 if (strs[0] == null) { 2017 return EMPTY; 2018 } 2019 return strs[0]; 2020 } 2021 if (smallestIndexOfDiff == 0) { 2022 // there were no common initial characters 2023 return EMPTY; 2024 } 2025 // we found a common initial character sequence 2026 return strs[0].substring(0, smallestIndexOfDiff); 2027 } 2028 2029 /** 2030 * Checks if a String {@code str} contains Unicode digits, if yes then concatenate all the digits in {@code str} and return it as a String. 2031 * 2032 * <p> 2033 * An empty ("") String will be returned if no digits found in {@code str}. 2034 * </p> 2035 * 2036 * <pre> 2037 * StringUtils.getDigits(null) = null 2038 * StringUtils.getDigits("") = "" 2039 * StringUtils.getDigits("abc") = "" 2040 * StringUtils.getDigits("1000$") = "1000" 2041 * StringUtils.getDigits("1123~45") = "112345" 2042 * StringUtils.getDigits("(541) 754-3010") = "5417543010" 2043 * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969" 2044 * </pre> 2045 * 2046 * @param str the String to extract digits from, may be null. 2047 * @return String with only digits, or an empty ("") String if no digits found, or {@code null} String if {@code str} is null. 2048 * @since 3.6 2049 */ 2050 public static String getDigits(final String str) { 2051 if (isEmpty(str)) { 2052 return str; 2053 } 2054 final int len = str.length(); 2055 final char[] buffer = new char[len]; 2056 int count = 0; 2057 2058 for (int i = 0; i < len; i++) { 2059 final char tempChar = str.charAt(i); 2060 if (Character.isDigit(tempChar)) { 2061 buffer[count++] = tempChar; 2062 } 2063 } 2064 return new String(buffer, 0, count); 2065 } 2066 2067 /** 2068 * Gets the Fuzzy Distance which indicates the similarity score between two Strings. 2069 * 2070 * <p> 2071 * 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 2072 * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity. 2073 * </p> 2074 * 2075 * <pre> 2076 * StringUtils.getFuzzyDistance(null, null, null) = Throws {@link IllegalArgumentException} 2077 * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0 2078 * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0 2079 * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1 2080 * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1 2081 * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2 2082 * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4 2083 * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3 2084 * </pre> 2085 * 2086 * @param term a full term that should be matched against, must not be null. 2087 * @param query the query that will be matched against a term, must not be null. 2088 * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case. 2089 * @return result score. 2090 * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}. 2091 * @since 3.4 2092 * @deprecated As of 3.6, use Apache Commons Text 2093 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html"> 2094 * FuzzyScore</a> instead. 2095 */ 2096 @Deprecated 2097 public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) { 2098 if (term == null || query == null) { 2099 throw new IllegalArgumentException("Strings must not be null"); 2100 } 2101 if (locale == null) { 2102 throw new IllegalArgumentException("Locale must not be null"); 2103 } 2104 // fuzzy logic is case-insensitive. We normalize the Strings to lower 2105 // case right from the start. Turning characters to lower case 2106 // via Character.toLowerCase(char) is unfortunately insufficient 2107 // as it does not accept a locale. 2108 final String termLowerCase = term.toString().toLowerCase(locale); 2109 final String queryLowerCase = query.toString().toLowerCase(locale); 2110 // the resulting score 2111 int score = 0; 2112 // the position in the term which will be scanned next for potential 2113 // query character matches 2114 int termIndex = 0; 2115 // index of the previously matched character in the term 2116 int previousMatchingCharacterIndex = Integer.MIN_VALUE; 2117 for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) { 2118 final char queryChar = queryLowerCase.charAt(queryIndex); 2119 boolean termCharacterMatchFound = false; 2120 for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) { 2121 final char termChar = termLowerCase.charAt(termIndex); 2122 if (queryChar == termChar) { 2123 // simple character matches result in one point 2124 score++; 2125 // subsequent character matches further improve 2126 // the score. 2127 if (previousMatchingCharacterIndex + 1 == termIndex) { 2128 score += 2; 2129 } 2130 previousMatchingCharacterIndex = termIndex; 2131 // we can leave the nested loop. Every character in the 2132 // query can match at most one character in the term. 2133 termCharacterMatchFound = true; 2134 } 2135 } 2136 } 2137 return score; 2138 } 2139 2140 /** 2141 * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or 2142 * {@code null}), the value supplied by {@code defaultStrSupplier}. 2143 * 2144 * <p> 2145 * Whitespace is defined by {@link Character#isWhitespace(char)}. 2146 * </p> 2147 * 2148 * <p> 2149 * Caller responsible for thread-safety and exception handling of default value supplier 2150 * </p> 2151 * 2152 * <pre> 2153 * {@code 2154 * StringUtils.getIfBlank(null, () -> "NULL") = "NULL" 2155 * StringUtils.getIfBlank("", () -> "NULL") = "NULL" 2156 * StringUtils.getIfBlank(" ", () -> "NULL") = "NULL" 2157 * StringUtils.getIfBlank("bat", () -> "NULL") = "bat" 2158 * StringUtils.getIfBlank("", () -> null) = null 2159 * StringUtils.getIfBlank("", null) = null 2160 * }</pre> 2161 * 2162 * @param <T> the specific kind of CharSequence. 2163 * @param str the CharSequence to check, may be null. 2164 * @param defaultSupplier the supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty 2165 * ({@code ""}), or {@code null}); may be null. 2166 * @return the passed in CharSequence, or the default 2167 * @see StringUtils#defaultString(String, String) 2168 * @see #isBlank(CharSequence) 2169 * @since 3.10 2170 */ 2171 public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) { 2172 return isBlank(str) ? Suppliers.get(defaultSupplier) : str; 2173 } 2174 2175 /** 2176 * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}. 2177 * 2178 * <p> 2179 * Caller responsible for thread-safety and exception handling of default value supplier 2180 * </p> 2181 * 2182 * <pre> 2183 * {@code 2184 * StringUtils.getIfEmpty(null, () -> "NULL") = "NULL" 2185 * StringUtils.getIfEmpty("", () -> "NULL") = "NULL" 2186 * StringUtils.getIfEmpty(" ", () -> "NULL") = " " 2187 * StringUtils.getIfEmpty("bat", () -> "NULL") = "bat" 2188 * StringUtils.getIfEmpty("", () -> null) = null 2189 * StringUtils.getIfEmpty("", null) = null 2190 * } 2191 * </pre> 2192 * 2193 * @param <T> the specific kind of CharSequence. 2194 * @param str the CharSequence to check, may be null. 2195 * @param defaultSupplier the supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null. 2196 * @return the passed in CharSequence, or the default. 2197 * @see StringUtils#defaultString(String, String) 2198 * @since 3.10 2199 */ 2200 public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) { 2201 return isEmpty(str) ? Suppliers.get(defaultSupplier) : str; 2202 } 2203 2204 /** 2205 * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings. 2206 * 2207 * <p> 2208 * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for 2209 * matching initial characters. 2210 * </p> 2211 * 2212 * <p> 2213 * This implementation is based on the Jaro Winkler similarity algorithm from 2214 * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>. 2215 * </p> 2216 * 2217 * <pre> 2218 * StringUtils.getJaroWinklerDistance(null, null) = Throws {@link IllegalArgumentException} 2219 * StringUtils.getJaroWinklerDistance("", "") = 0.0 2220 * StringUtils.getJaroWinklerDistance("", "a") = 0.0 2221 * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0 2222 * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93 2223 * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0 2224 * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44 2225 * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44 2226 * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0 2227 * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88 2228 * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93 2229 * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95 2230 * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92 2231 * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88 2232 * </pre> 2233 * 2234 * @param first the first String, must not be null. 2235 * @param second the second String, must not be null. 2236 * @return result distance. 2237 * @throws IllegalArgumentException if either String input {@code null}. 2238 * @since 3.3 2239 * @deprecated As of 3.6, use Apache Commons Text 2240 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html"> 2241 * JaroWinklerDistance</a> instead. 2242 */ 2243 @Deprecated 2244 public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) { 2245 final double DEFAULT_SCALING_FACTOR = 0.1; 2246 2247 if (first == null || second == null) { 2248 throw new IllegalArgumentException("Strings must not be null"); 2249 } 2250 2251 final int[] mtp = matches(first, second); 2252 final double m = mtp[0]; 2253 if (m == 0) { 2254 return 0D; 2255 } 2256 final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3; 2257 final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j); 2258 return Math.round(jw * 100.0D) / 100.0D; 2259 } 2260 2261 /** 2262 * Gets the Levenshtein distance between two Strings. 2263 * 2264 * <p> 2265 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2266 * substitution). 2267 * </p> 2268 * 2269 * <p> 2270 * The implementation uses a single-dimensional array of length s.length() + 1. See 2271 * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html"> 2272 * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details. 2273 * </p> 2274 * 2275 * <pre> 2276 * StringUtils.getLevenshteinDistance(null, *) = Throws {@link IllegalArgumentException} 2277 * StringUtils.getLevenshteinDistance(*, null) = Throws {@link IllegalArgumentException} 2278 * StringUtils.getLevenshteinDistance("", "") = 0 2279 * StringUtils.getLevenshteinDistance("", "a") = 1 2280 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 2281 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 2282 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 2283 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 2284 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 2285 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 2286 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 2287 * </pre> 2288 * 2289 * @param s the first String, must not be null. 2290 * @param t the second String, must not be null. 2291 * @return result distance. 2292 * @throws IllegalArgumentException if either String input {@code null}. 2293 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence) 2294 * @deprecated As of 3.6, use Apache Commons Text 2295 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2296 * LevenshteinDistance</a> instead. 2297 */ 2298 @Deprecated 2299 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 2300 if (s == null || t == null) { 2301 throw new IllegalArgumentException("Strings must not be null"); 2302 } 2303 2304 int n = s.length(); 2305 int m = t.length(); 2306 2307 if (n == 0) { 2308 return m; 2309 } 2310 if (m == 0) { 2311 return n; 2312 } 2313 2314 if (n > m) { 2315 // swap the input strings to consume less memory 2316 final CharSequence tmp = s; 2317 s = t; 2318 t = tmp; 2319 n = m; 2320 m = t.length(); 2321 } 2322 2323 final int[] p = new int[n + 1]; 2324 // indexes into strings s and t 2325 int i; // iterates through s 2326 int j; // iterates through t 2327 int upperleft; 2328 int upper; 2329 2330 char jOfT; // jth character of t 2331 int cost; 2332 2333 for (i = 0; i <= n; i++) { 2334 p[i] = i; 2335 } 2336 2337 for (j = 1; j <= m; j++) { 2338 upperleft = p[0]; 2339 jOfT = t.charAt(j - 1); 2340 p[0] = j; 2341 2342 for (i = 1; i <= n; i++) { 2343 upper = p[i]; 2344 cost = s.charAt(i - 1) == jOfT ? 0 : 1; 2345 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 2346 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost); 2347 upperleft = upper; 2348 } 2349 } 2350 2351 return p[n]; 2352 } 2353 2354 /** 2355 * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold. 2356 * 2357 * <p> 2358 * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or 2359 * substitution). 2360 * </p> 2361 * 2362 * <p> 2363 * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance 2364 * algorithm. 2365 * </p> 2366 * 2367 * <pre> 2368 * StringUtils.getLevenshteinDistance(null, *, *) = Throws {@link IllegalArgumentException} 2369 * StringUtils.getLevenshteinDistance(*, null, *) = Throws {@link IllegalArgumentException} 2370 * StringUtils.getLevenshteinDistance(*, *, -1) = Throws {@link IllegalArgumentException} 2371 * StringUtils.getLevenshteinDistance("", "", 0) = 0 2372 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 2373 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 2374 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 2375 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 2376 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 2377 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 2378 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 2379 * </pre> 2380 * 2381 * @param s the first String, must not be null. 2382 * @param t the second String, must not be null. 2383 * @param threshold the target threshold, must not be negative. 2384 * @return result distance, or {@code -1} if the distance would be greater than the threshold. 2385 * @throws IllegalArgumentException if either String input {@code null} or negative threshold. 2386 * @deprecated As of 3.6, use Apache Commons Text 2387 * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html"> 2388 * LevenshteinDistance</a> instead. 2389 */ 2390 @Deprecated 2391 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 2392 if (s == null || t == null) { 2393 throw new IllegalArgumentException("Strings must not be null"); 2394 } 2395 if (threshold < 0) { 2396 throw new IllegalArgumentException("Threshold must not be negative"); 2397 } 2398 2399 /* 2400 This implementation only computes the distance if it's less than or equal to the 2401 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 2402 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 2403 computing a diagonal stripe of width 2k + 1 of the cost table. 2404 It is also possible to use this to compute the unbounded Levenshtein distance by starting 2405 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 2406 d is the distance. 2407 2408 One subtlety comes from needing to ignore entries on the border of our stripe 2409 for example, 2410 p[] = |#|#|#|* 2411 d[] = *|#|#|#| 2412 We must ignore the entry to the left of the leftmost member 2413 We must ignore the entry above the rightmost member 2414 2415 Another subtlety comes from our stripe running off the matrix if the strings aren't 2416 of the same size. Since string s is always swapped to be the shorter of the two, 2417 the stripe will always run off to the upper right instead of the lower left of the matrix. 2418 2419 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 2420 In this case we're going to walk a stripe of length 3. The matrix would look like so: 2421 2422 1 2 3 4 5 2423 1 |#|#| | | | 2424 2 |#|#|#| | | 2425 3 | |#|#|#| | 2426 4 | | |#|#|#| 2427 5 | | | |#|#| 2428 6 | | | | |#| 2429 7 | | | | | | 2430 2431 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 2432 into one of length 7 in edit distance of 1. 2433 2434 Additionally, this implementation decreases memory usage by using two 2435 single-dimensional arrays and swapping them back and forth instead of allocating 2436 an entire n by m matrix. This requires a few minor changes, such as immediately returning 2437 when it's detected that the stripe has run off the matrix and initially filling the arrays with 2438 large values so that entries we don't compute are ignored. 2439 2440 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 2441 */ 2442 2443 int n = s.length(); // length of s 2444 int m = t.length(); // length of t 2445 2446 // if one string is empty, the edit distance is necessarily the length of the other 2447 if (n == 0) { 2448 return m <= threshold ? m : -1; 2449 } 2450 if (m == 0) { 2451 return n <= threshold ? n : -1; 2452 } 2453 if (Math.abs(n - m) > threshold) { 2454 // no need to calculate the distance if the length difference is greater than the threshold 2455 return -1; 2456 } 2457 2458 if (n > m) { 2459 // swap the two strings to consume less memory 2460 final CharSequence tmp = s; 2461 s = t; 2462 t = tmp; 2463 n = m; 2464 m = t.length(); 2465 } 2466 2467 int[] p = new int[n + 1]; // 'previous' cost array, horizontally 2468 int[] d = new int[n + 1]; // cost array, horizontally 2469 int[] tmp; // placeholder to assist in swapping p and d 2470 2471 // fill in starting table values 2472 final int boundary = Math.min(n, threshold) + 1; 2473 for (int i = 0; i < boundary; i++) { 2474 p[i] = i; 2475 } 2476 // these fills ensure that the value above the rightmost entry of our 2477 // stripe will be ignored in following loop iterations 2478 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 2479 Arrays.fill(d, Integer.MAX_VALUE); 2480 2481 // iterates through t 2482 for (int j = 1; j <= m; j++) { 2483 final char jOfT = t.charAt(j - 1); // jth character of t 2484 d[0] = j; 2485 2486 // compute stripe indices, constrain to array size 2487 final int min = Math.max(1, j - threshold); 2488 final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); 2489 2490 // the stripe may lead off of the table if s and t are of different sizes 2491 if (min > max) { 2492 return -1; 2493 } 2494 2495 // ignore entry left of leftmost 2496 if (min > 1) { 2497 d[min - 1] = Integer.MAX_VALUE; 2498 } 2499 2500 // iterates through [min, max] in s 2501 for (int i = min; i <= max; i++) { 2502 if (s.charAt(i - 1) == jOfT) { 2503 // diagonally left and up 2504 d[i] = p[i - 1]; 2505 } else { 2506 // 1 + minimum of cell to the left, to the top, diagonally left and up 2507 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 2508 } 2509 } 2510 2511 // copy current distance counts to 'previous row' distance counts 2512 tmp = p; 2513 p = d; 2514 d = tmp; 2515 } 2516 2517 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 2518 // distance 2519 if (p[n] <= threshold) { 2520 return p[n]; 2521 } 2522 return -1; 2523 } 2524 2525 /** 2526 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2527 * 2528 * <p> 2529 * A {@code null} CharSequence will return {@code -1}. 2530 * </p> 2531 * 2532 * <pre> 2533 * StringUtils.indexOf(null, *) = -1 2534 * StringUtils.indexOf(*, null) = -1 2535 * StringUtils.indexOf("", "") = 0 2536 * StringUtils.indexOf("", *) = -1 (except when * = "") 2537 * StringUtils.indexOf("aabaabaa", "a") = 0 2538 * StringUtils.indexOf("aabaabaa", "b") = 2 2539 * StringUtils.indexOf("aabaabaa", "ab") = 1 2540 * StringUtils.indexOf("aabaabaa", "") = 0 2541 * </pre> 2542 * 2543 * @param seq the CharSequence to check, may be null. 2544 * @param searchSeq the CharSequence to find, may be null. 2545 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 2546 * @since 2.0 2547 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 2548 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}. 2549 */ 2550 @Deprecated 2551 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 2552 return Strings.CS.indexOf(seq, searchSeq); 2553 } 2554 2555 /** 2556 * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible. 2557 * 2558 * <p> 2559 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 2560 * start position greater than the string length only matches an empty search CharSequence. 2561 * </p> 2562 * 2563 * <pre> 2564 * StringUtils.indexOf(null, *, *) = -1 2565 * StringUtils.indexOf(*, null, *) = -1 2566 * StringUtils.indexOf("", "", 0) = 0 2567 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 2568 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 2569 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 2570 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 2571 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 2572 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 2573 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 2574 * StringUtils.indexOf("aabaabaa", "", 2) = 2 2575 * StringUtils.indexOf("abc", "", 9) = 3 2576 * </pre> 2577 * 2578 * @param seq the CharSequence to check, may be null. 2579 * @param searchSeq the CharSequence to find, may be null. 2580 * @param startPos the start position, negative treated as zero. 2581 * @return the first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 2582 * @since 2.0 2583 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 2584 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}. 2585 */ 2586 @Deprecated 2587 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 2588 return Strings.CS.indexOf(seq, searchSeq, startPos); 2589 } 2590 2591 /** 2592 * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the 2593 * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is 2594 * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that: 2595 * 2596 * <pre> 2597 * this.charAt(<em>k</em>) == searchChar 2598 * </pre> 2599 * 2600 * <p> 2601 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2602 * </p> 2603 * 2604 * <pre> 2605 * this.codePointAt(<em>k</em>) == searchChar 2606 * </pre> 2607 * 2608 * <p> 2609 * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned. 2610 * </p> 2611 * 2612 * <p> 2613 * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}. 2614 * </p> 2615 * 2616 * <pre> 2617 * StringUtils.indexOf(null, *) = -1 2618 * StringUtils.indexOf("", *) = -1 2619 * StringUtils.indexOf("aabaabaa", 'a') = 0 2620 * StringUtils.indexOf("aabaabaa", 'b') = 2 2621 * StringUtils.indexOf("aaaaaaaa", 'Z') = -1 2622 * </pre> 2623 * 2624 * @param seq the CharSequence to check, may be null. 2625 * @param searchChar the character to find. 2626 * @return the first index of the search character, -1 if no match or {@code null} string input. 2627 * @since 2.0 2628 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 2629 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2630 */ 2631 public static int indexOf(final CharSequence seq, final int searchChar) { 2632 if (isEmpty(seq)) { 2633 return INDEX_NOT_FOUND; 2634 } 2635 return CharSequenceUtils.indexOf(seq, searchChar, 0); 2636 } 2637 2638 /** 2639 * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index. 2640 * <p> 2641 * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no 2642 * 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 2643 * (inclusive), this is the smallest value <em>k</em> such that: 2644 * </p> 2645 * 2646 * <pre> 2647 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2648 * </pre> 2649 * 2650 * <p> 2651 * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that: 2652 * </p> 2653 * 2654 * <pre> 2655 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> >= startPos) 2656 * </pre> 2657 * 2658 * <p> 2659 * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned. 2660 * </p> 2661 * 2662 * <p> 2663 * 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 2664 * 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: 2665 * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}. 2666 * </p> 2667 * <p> 2668 * All indices are specified in {@code char} values (Unicode code units). 2669 * </p> 2670 * 2671 * <pre> 2672 * StringUtils.indexOf(null, *, *) = -1 2673 * StringUtils.indexOf("", *, *) = -1 2674 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 2675 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 2676 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 2677 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 2678 * </pre> 2679 * 2680 * @param seq the CharSequence to check, may be null. 2681 * @param searchChar the character to find. 2682 * @param startPos the start position, negative treated as zero. 2683 * @return the first index of the search character (always ≥ startPos), -1 if no match or {@code null} string input. 2684 * @since 2.0 2685 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 2686 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 2687 */ 2688 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 2689 if (isEmpty(seq)) { 2690 return INDEX_NOT_FOUND; 2691 } 2692 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 2693 } 2694 2695 /** 2696 * Search a CharSequence to find the first index of any character in the given set of characters. 2697 * 2698 * <p> 2699 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2700 * </p> 2701 * 2702 * <pre> 2703 * StringUtils.indexOfAny(null, *) = -1 2704 * StringUtils.indexOfAny("", *) = -1 2705 * StringUtils.indexOfAny(*, null) = -1 2706 * StringUtils.indexOfAny(*, []) = -1 2707 * StringUtils.indexOfAny("zzabyycdxx", 'z', 'a') = 0 2708 * StringUtils.indexOfAny("zzabyycdxx", 'b', 'y') = 3 2709 * StringUtils.indexOfAny("aba", 'z') = -1 2710 * </pre> 2711 * 2712 * @param cs the CharSequence to check, may be null. 2713 * @param searchChars the chars to search for, may be null. 2714 * @return the index of any of the chars, -1 if no match or null input. 2715 * @since 2.0 2716 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2717 */ 2718 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 2719 return indexOfAny(cs, 0, searchChars); 2720 } 2721 2722 /** 2723 * Find the first index of any of a set of potential substrings. 2724 * 2725 * <p> 2726 * 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 2727 * 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 2728 * possible. 2729 * </p> 2730 * 2731 * <pre> 2732 * StringUtils.indexOfAny(null, *) = -1 2733 * StringUtils.indexOfAny(*, null) = -1 2734 * StringUtils.indexOfAny(*, []) = -1 2735 * StringUtils.indexOfAny("zzabyycdxx", "ab", "cd") = 2 2736 * StringUtils.indexOfAny("zzabyycdxx", "cd", "ab") = 2 2737 * StringUtils.indexOfAny("zzabyycdxx", "mn", "op") = -1 2738 * StringUtils.indexOfAny("zzabyycdxx", "zab", "aby") = 1 2739 * StringUtils.indexOfAny("zzabyycdxx", "") = 0 2740 * StringUtils.indexOfAny("", "") = 0 2741 * StringUtils.indexOfAny("", "a") = -1 2742 * </pre> 2743 * 2744 * @param str the CharSequence to check, may be null. 2745 * @param searchStrs the CharSequences to search for, may be null. 2746 * @return the first index of any of the searchStrs in str, -1 if no match. 2747 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 2748 */ 2749 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2750 if (str == null || searchStrs == null) { 2751 return INDEX_NOT_FOUND; 2752 } 2753 // String's can't have a MAX_VALUEth index. 2754 int ret = Integer.MAX_VALUE; 2755 int tmp; 2756 for (final CharSequence search : searchStrs) { 2757 if (search == null) { 2758 continue; 2759 } 2760 tmp = CharSequenceUtils.indexOf(str, search, 0); 2761 if (tmp == INDEX_NOT_FOUND) { 2762 continue; 2763 } 2764 if (tmp < ret) { 2765 ret = tmp; 2766 } 2767 } 2768 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 2769 } 2770 2771 /** 2772 * Search a CharSequence to find the first index of any character in the given set of characters. 2773 * 2774 * <p> 2775 * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2776 * </p> 2777 * <p> 2778 * The following is the same as {@code indexOfAny(cs, 0, searchChars)}. 2779 * </p> 2780 * <pre> 2781 * StringUtils.indexOfAny(null, 0, *) = -1 2782 * StringUtils.indexOfAny("", 0, *) = -1 2783 * StringUtils.indexOfAny(*, 0, null) = -1 2784 * StringUtils.indexOfAny(*, 0, []) = -1 2785 * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0 2786 * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3 2787 * StringUtils.indexOfAny("aba", 0, ['z']) = -1 2788 * </pre> 2789 * 2790 * @param cs the CharSequence to check, may be null. 2791 * @param csStart Start searching the input {@code cs} at this index. 2792 * @param searchChars the chars to search for, may be null. 2793 * @return the index of any of the chars, -1 if no match or null input. 2794 * @since 2.0 2795 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 2796 */ 2797 public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) { 2798 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2799 return INDEX_NOT_FOUND; 2800 } 2801 final int csLen = cs.length(); 2802 final int csLast = csLen - 1; 2803 final int searchLen = searchChars.length; 2804 final int searchLast = searchLen - 1; 2805 for (int i = csStart; i < csLen; i++) { 2806 final char ch = cs.charAt(i); 2807 for (int j = 0; j < searchLen; j++) { 2808 if (searchChars[j] == ch) { 2809 // ch is a supplementary character 2810 if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch) || searchChars[j + 1] == cs.charAt(i + 1)) { 2811 return i; 2812 } 2813 } 2814 } 2815 } 2816 return INDEX_NOT_FOUND; 2817 } 2818 2819 /** 2820 * Search a CharSequence to find the first index of any character in the given set of characters. 2821 * 2822 * <p> 2823 * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}. 2824 * </p> 2825 * 2826 * <pre> 2827 * StringUtils.indexOfAny(null, *) = -1 2828 * StringUtils.indexOfAny("", *) = -1 2829 * StringUtils.indexOfAny(*, null) = -1 2830 * StringUtils.indexOfAny(*, "") = -1 2831 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 2832 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 2833 * StringUtils.indexOfAny("aba", "z") = -1 2834 * </pre> 2835 * 2836 * @param cs the CharSequence to check, may be null. 2837 * @param searchChars the chars to search for, may be null. 2838 * @return the index of any of the chars, -1 if no match or null input. 2839 * @since 2.0 2840 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 2841 */ 2842 public static int indexOfAny(final CharSequence cs, final String searchChars) { 2843 if (isEmpty(cs) || isEmpty(searchChars)) { 2844 return INDEX_NOT_FOUND; 2845 } 2846 return indexOfAny(cs, searchChars.toCharArray()); 2847 } 2848 2849 /** 2850 * 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 2851 * (cs.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2852 * 2853 * <p> 2854 * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. 2855 * </p> 2856 * 2857 * <pre> 2858 * StringUtils.indexOfAnyBut(null, *) = -1 2859 * StringUtils.indexOfAnyBut("", *) = -1 2860 * StringUtils.indexOfAnyBut(*, null) = -1 2861 * StringUtils.indexOfAnyBut(*, []) = -1 2862 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 2863 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 2864 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 2865 * </pre> 2866 * 2867 * @param cs the CharSequence to check, may be null. 2868 * @param searchChars the chars to search for, may be null. 2869 * @return the index of any of the chars, -1 if no match or null input. 2870 * @since 2.0 2871 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 2872 */ 2873 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 2874 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 2875 return INDEX_NOT_FOUND; 2876 } 2877 return indexOfAnyBut(cs, CharBuffer.wrap(searchChars)); 2878 } 2879 2880 /** 2881 * 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 2882 * (seq.codePointAt(i) ∉ { x ∈ codepoints(searchChars) }) 2883 * 2884 * <p> 2885 * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}. 2886 * </p> 2887 * 2888 * <pre> 2889 * StringUtils.indexOfAnyBut(null, *) = -1 2890 * StringUtils.indexOfAnyBut("", *) = -1 2891 * StringUtils.indexOfAnyBut(*, null) = -1 2892 * StringUtils.indexOfAnyBut(*, "") = -1 2893 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 2894 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 2895 * StringUtils.indexOfAnyBut("aba", "ab") = -1 2896 * </pre> 2897 * 2898 * @param seq the CharSequence to check, may be null. 2899 * @param searchChars the chars to search for, may be null. 2900 * @return the index of any of the chars, -1 if no match or null input. 2901 * @since 2.0 2902 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 2903 */ 2904 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 2905 if (isEmpty(seq) || isEmpty(searchChars)) { 2906 return INDEX_NOT_FOUND; 2907 } 2908 final Set<Integer> searchSetCodePoints = searchChars.codePoints() 2909 .boxed().collect(Collectors.toSet()); 2910 // advance character index from one interpreted codepoint to the next 2911 for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) { 2912 final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx); 2913 if (!searchSetCodePoints.contains(curSeqCodePoint)) { 2914 return curSeqCharIdx; 2915 } 2916 curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates 2917 } 2918 return INDEX_NOT_FOUND; 2919 } 2920 2921 /** 2922 * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ. 2923 * 2924 * <p> 2925 * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7} 2926 * </p> 2927 * 2928 * <pre> 2929 * StringUtils.indexOfDifference(null) = -1 2930 * StringUtils.indexOfDifference(new String[] {}) = -1 2931 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 2932 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 2933 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 2934 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 2935 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 2936 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 2937 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 2938 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 2939 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 2940 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 2941 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 2942 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 2943 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 2944 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 2945 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 2946 * </pre> 2947 * 2948 * @param css array of CharSequences, entries may be null. 2949 * @return the index where the strings begin to differ; -1 if they are all equal. 2950 * @since 2.4 2951 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 2952 */ 2953 public static int indexOfDifference(final CharSequence... css) { 2954 if (ArrayUtils.getLength(css) <= 1) { 2955 return INDEX_NOT_FOUND; 2956 } 2957 boolean anyStringNull = false; 2958 boolean allStringsNull = true; 2959 final int arrayLen = css.length; 2960 int shortestStrLen = Integer.MAX_VALUE; 2961 int longestStrLen = 0; 2962 // find the min and max string lengths; this avoids checking to make 2963 // sure we are not exceeding the length of the string each time through 2964 // the bottom loop. 2965 for (final CharSequence cs : css) { 2966 if (cs == null) { 2967 anyStringNull = true; 2968 shortestStrLen = 0; 2969 } else { 2970 allStringsNull = false; 2971 shortestStrLen = Math.min(cs.length(), shortestStrLen); 2972 longestStrLen = Math.max(cs.length(), longestStrLen); 2973 } 2974 } 2975 // handle lists containing all nulls or all empty strings 2976 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 2977 return INDEX_NOT_FOUND; 2978 } 2979 // handle lists containing some nulls or some empty strings 2980 if (shortestStrLen == 0) { 2981 return 0; 2982 } 2983 // find the position with the first difference across all strings 2984 int firstDiff = -1; 2985 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 2986 final char comparisonChar = css[0].charAt(stringPos); 2987 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 2988 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 2989 firstDiff = stringPos; 2990 break; 2991 } 2992 } 2993 if (firstDiff != -1) { 2994 break; 2995 } 2996 } 2997 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 2998 // we compared all of the characters up to the length of the 2999 // shortest string and didn't find a match, but the string lengths 3000 // vary, so return the length of the shortest string. 3001 return shortestStrLen; 3002 } 3003 return firstDiff; 3004 } 3005 3006 /** 3007 * Compares two CharSequences, and returns the index at which the CharSequences begin to differ. 3008 * 3009 * <p> 3010 * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7} 3011 * </p> 3012 * 3013 * <pre> 3014 * StringUtils.indexOfDifference(null, null) = -1 3015 * StringUtils.indexOfDifference("", "") = -1 3016 * StringUtils.indexOfDifference("", "abc") = 0 3017 * StringUtils.indexOfDifference("abc", "") = 0 3018 * StringUtils.indexOfDifference("abc", "abc") = -1 3019 * StringUtils.indexOfDifference("ab", "abxyz") = 2 3020 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 3021 * StringUtils.indexOfDifference("abcde", "xyz") = 0 3022 * </pre> 3023 * 3024 * @param cs1 the first CharSequence, may be null. 3025 * @param cs2 the second CharSequence, may be null. 3026 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal. 3027 * @since 2.0 3028 * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence) 3029 */ 3030 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 3031 if (cs1 == cs2) { 3032 return INDEX_NOT_FOUND; 3033 } 3034 if (cs1 == null || cs2 == null) { 3035 return 0; 3036 } 3037 int i; 3038 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 3039 if (cs1.charAt(i) != cs2.charAt(i)) { 3040 break; 3041 } 3042 } 3043 if (i < cs2.length() || i < cs1.length()) { 3044 return i; 3045 } 3046 return INDEX_NOT_FOUND; 3047 } 3048 3049 /** 3050 * Case in-sensitive find of the first index within a CharSequence. 3051 * 3052 * <p> 3053 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3054 * start position greater than the string length only matches an empty search CharSequence. 3055 * </p> 3056 * 3057 * <pre> 3058 * StringUtils.indexOfIgnoreCase(null, *) = -1 3059 * StringUtils.indexOfIgnoreCase(*, null) = -1 3060 * StringUtils.indexOfIgnoreCase("", "") = 0 3061 * StringUtils.indexOfIgnoreCase(" ", " ") = 0 3062 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 3063 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 3064 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 3065 * </pre> 3066 * 3067 * @param str the CharSequence to check, may be null. 3068 * @param searchStr the CharSequence to find, may be null. 3069 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 3070 * @since 2.5 3071 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 3072 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}. 3073 */ 3074 @Deprecated 3075 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 3076 return Strings.CI.indexOf(str, searchStr); 3077 } 3078 3079 /** 3080 * Case in-sensitive find of the first index within a CharSequence from the specified position. 3081 * 3082 * <p> 3083 * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A 3084 * start position greater than the string length only matches an empty search CharSequence. 3085 * </p> 3086 * 3087 * <pre> 3088 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 3089 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 3090 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 3091 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 3092 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 3093 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 3094 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 3095 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 3096 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 3097 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 3098 * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1 3099 * </pre> 3100 * 3101 * @param str the CharSequence to check, may be null. 3102 * @param searchStr the CharSequence to find, may be null. 3103 * @param startPos the start position, negative treated as zero. 3104 * @return the first index of the search CharSequence (always ≥ startPos), -1 if no match or {@code null} string input. 3105 * @since 2.5 3106 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 3107 * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}. 3108 */ 3109 @Deprecated 3110 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 3111 return Strings.CI.indexOf(str, searchStr, startPos); 3112 } 3113 3114 /** 3115 * Tests if all of the CharSequences are empty (""), null or whitespace only. 3116 * 3117 * <p> 3118 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3119 * </p> 3120 * 3121 * <pre> 3122 * StringUtils.isAllBlank(null) = true 3123 * StringUtils.isAllBlank(null, "foo") = false 3124 * StringUtils.isAllBlank(null, null) = true 3125 * StringUtils.isAllBlank("", "bar") = false 3126 * StringUtils.isAllBlank("bob", "") = false 3127 * StringUtils.isAllBlank(" bob ", null) = false 3128 * StringUtils.isAllBlank(" ", "bar") = false 3129 * StringUtils.isAllBlank("foo", "bar") = false 3130 * StringUtils.isAllBlank(new String[] {}) = true 3131 * </pre> 3132 * 3133 * @param css the CharSequences to check, may be null or empty. 3134 * @return {@code true} if all of the CharSequences are empty or null or whitespace only. 3135 * @since 3.6 3136 */ 3137 public static boolean isAllBlank(final CharSequence... css) { 3138 if (ArrayUtils.isEmpty(css)) { 3139 return true; 3140 } 3141 for (final CharSequence cs : css) { 3142 if (isNotBlank(cs)) { 3143 return false; 3144 } 3145 } 3146 return true; 3147 } 3148 3149 /** 3150 * Tests if all of the CharSequences are empty ("") or null. 3151 * 3152 * <pre> 3153 * StringUtils.isAllEmpty(null) = true 3154 * StringUtils.isAllEmpty(null, "") = true 3155 * StringUtils.isAllEmpty(new String[] {}) = true 3156 * StringUtils.isAllEmpty(null, "foo") = false 3157 * StringUtils.isAllEmpty("", "bar") = false 3158 * StringUtils.isAllEmpty("bob", "") = false 3159 * StringUtils.isAllEmpty(" bob ", null) = false 3160 * StringUtils.isAllEmpty(" ", "bar") = false 3161 * StringUtils.isAllEmpty("foo", "bar") = false 3162 * </pre> 3163 * 3164 * @param css the CharSequences to check, may be null or empty. 3165 * @return {@code true} if all of the CharSequences are empty or null. 3166 * @since 3.6 3167 */ 3168 public static boolean isAllEmpty(final CharSequence... css) { 3169 if (ArrayUtils.isEmpty(css)) { 3170 return true; 3171 } 3172 for (final CharSequence cs : css) { 3173 if (isNotEmpty(cs)) { 3174 return false; 3175 } 3176 } 3177 return true; 3178 } 3179 3180 /** 3181 * Tests if the CharSequence contains only lowercase characters. 3182 * 3183 * <p> 3184 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3185 * </p> 3186 * 3187 * <pre> 3188 * StringUtils.isAllLowerCase(null) = false 3189 * StringUtils.isAllLowerCase("") = false 3190 * StringUtils.isAllLowerCase(" ") = false 3191 * StringUtils.isAllLowerCase("abc") = true 3192 * StringUtils.isAllLowerCase("abC") = false 3193 * StringUtils.isAllLowerCase("ab c") = false 3194 * StringUtils.isAllLowerCase("ab1c") = false 3195 * StringUtils.isAllLowerCase("ab/c") = false 3196 * </pre> 3197 * 3198 * @param cs the CharSequence to check, may be null. 3199 * @return {@code true} if only contains lowercase characters, and is non-null. 3200 * @since 2.5 3201 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 3202 */ 3203 public static boolean isAllLowerCase(final CharSequence cs) { 3204 if (isEmpty(cs)) { 3205 return false; 3206 } 3207 final int sz = cs.length(); 3208 for (int i = 0; i < sz; i++) { 3209 if (!Character.isLowerCase(cs.charAt(i))) { 3210 return false; 3211 } 3212 } 3213 return true; 3214 } 3215 3216 /** 3217 * Tests if the CharSequence contains only uppercase characters. 3218 * 3219 * <p>{@code null} will return {@code false}. 3220 * An empty String (length()=0) will return {@code false}.</p> 3221 * 3222 * <pre> 3223 * StringUtils.isAllUpperCase(null) = false 3224 * StringUtils.isAllUpperCase("") = false 3225 * StringUtils.isAllUpperCase(" ") = false 3226 * StringUtils.isAllUpperCase("ABC") = true 3227 * StringUtils.isAllUpperCase("aBC") = false 3228 * StringUtils.isAllUpperCase("A C") = false 3229 * StringUtils.isAllUpperCase("A1C") = false 3230 * StringUtils.isAllUpperCase("A/C") = false 3231 * </pre> 3232 * 3233 * @param cs the CharSequence to check, may be null. 3234 * @return {@code true} if only contains uppercase characters, and is non-null. 3235 * @since 2.5 3236 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 3237 */ 3238 public static boolean isAllUpperCase(final CharSequence cs) { 3239 if (isEmpty(cs)) { 3240 return false; 3241 } 3242 final int sz = cs.length(); 3243 for (int i = 0; i < sz; i++) { 3244 if (!Character.isUpperCase(cs.charAt(i))) { 3245 return false; 3246 } 3247 } 3248 return true; 3249 } 3250 3251 /** 3252 * Tests if the CharSequence contains only Unicode letters. 3253 * 3254 * <p> 3255 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3256 * </p> 3257 * 3258 * <pre> 3259 * StringUtils.isAlpha(null) = false 3260 * StringUtils.isAlpha("") = false 3261 * StringUtils.isAlpha(" ") = false 3262 * StringUtils.isAlpha("abc") = true 3263 * StringUtils.isAlpha("ab2c") = false 3264 * StringUtils.isAlpha("ab-c") = false 3265 * </pre> 3266 * 3267 * @param cs the CharSequence to check, may be null. 3268 * @return {@code true} if only contains letters, and is non-null. 3269 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 3270 * @since 3.0 Changed "" to return false and not true 3271 */ 3272 public static boolean isAlpha(final CharSequence cs) { 3273 if (isEmpty(cs)) { 3274 return false; 3275 } 3276 final int sz = cs.length(); 3277 for (int i = 0; i < sz; i++) { 3278 if (!Character.isLetter(cs.charAt(i))) { 3279 return false; 3280 } 3281 } 3282 return true; 3283 } 3284 3285 /** 3286 * Tests if the CharSequence contains only Unicode letters or digits. 3287 * 3288 * <p> 3289 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3290 * </p> 3291 * 3292 * <pre> 3293 * StringUtils.isAlphanumeric(null) = false 3294 * StringUtils.isAlphanumeric("") = false 3295 * StringUtils.isAlphanumeric(" ") = false 3296 * StringUtils.isAlphanumeric("abc") = true 3297 * StringUtils.isAlphanumeric("ab c") = false 3298 * StringUtils.isAlphanumeric("ab2c") = true 3299 * StringUtils.isAlphanumeric("ab-c") = false 3300 * </pre> 3301 * 3302 * @param cs the CharSequence to check, may be null. 3303 * @return {@code true} if only contains letters or digits, and is non-null. 3304 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 3305 * @since 3.0 Changed "" to return false and not true 3306 */ 3307 public static boolean isAlphanumeric(final CharSequence cs) { 3308 if (isEmpty(cs)) { 3309 return false; 3310 } 3311 final int sz = cs.length(); 3312 for (int i = 0; i < sz; i++) { 3313 if (!Character.isLetterOrDigit(cs.charAt(i))) { 3314 return false; 3315 } 3316 } 3317 return true; 3318 } 3319 3320 /** 3321 * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}). 3322 * 3323 * <p> 3324 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3325 * </p> 3326 * 3327 * <pre> 3328 * StringUtils.isAlphanumericSpace(null) = false 3329 * StringUtils.isAlphanumericSpace("") = true 3330 * StringUtils.isAlphanumericSpace(" ") = true 3331 * StringUtils.isAlphanumericSpace("abc") = true 3332 * StringUtils.isAlphanumericSpace("ab c") = true 3333 * StringUtils.isAlphanumericSpace("ab2c") = true 3334 * StringUtils.isAlphanumericSpace("ab-c") = false 3335 * </pre> 3336 * 3337 * @param cs the CharSequence to check, may be null. 3338 * @return {@code true} if only contains letters, digits or space, and is non-null. 3339 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 3340 */ 3341 public static boolean isAlphanumericSpace(final CharSequence cs) { 3342 if (cs == null) { 3343 return false; 3344 } 3345 final int sz = cs.length(); 3346 for (int i = 0; i < sz; i++) { 3347 final char nowChar = cs.charAt(i); 3348 if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar)) { 3349 return false; 3350 } 3351 } 3352 return true; 3353 } 3354 3355 /** 3356 * Tests if the CharSequence contains only Unicode letters and space (' '). 3357 * 3358 * <p> 3359 * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}. 3360 * </p> 3361 * 3362 * <pre> 3363 * StringUtils.isAlphaSpace(null) = false 3364 * StringUtils.isAlphaSpace("") = true 3365 * StringUtils.isAlphaSpace(" ") = true 3366 * StringUtils.isAlphaSpace("abc") = true 3367 * StringUtils.isAlphaSpace("ab c") = true 3368 * StringUtils.isAlphaSpace("ab2c") = false 3369 * StringUtils.isAlphaSpace("ab-c") = false 3370 * </pre> 3371 * 3372 * @param cs the CharSequence to check, may be null. 3373 * @return {@code true} if only contains letters and space, and is non-null. 3374 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 3375 */ 3376 public static boolean isAlphaSpace(final CharSequence cs) { 3377 if (cs == null) { 3378 return false; 3379 } 3380 final int sz = cs.length(); 3381 for (int i = 0; i < sz; i++) { 3382 final char nowChar = cs.charAt(i); 3383 if (nowChar != ' ' && !Character.isLetter(nowChar)) { 3384 return false; 3385 } 3386 } 3387 return true; 3388 } 3389 3390 /** 3391 * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3392 * 3393 * <p> 3394 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3395 * </p> 3396 * 3397 * <pre> 3398 * StringUtils.isAnyBlank((String) null) = true 3399 * StringUtils.isAnyBlank((String[]) null) = false 3400 * StringUtils.isAnyBlank(null, "foo") = true 3401 * StringUtils.isAnyBlank(null, null) = true 3402 * StringUtils.isAnyBlank("", "bar") = true 3403 * StringUtils.isAnyBlank("bob", "") = true 3404 * StringUtils.isAnyBlank(" bob ", null) = true 3405 * StringUtils.isAnyBlank(" ", "bar") = true 3406 * StringUtils.isAnyBlank(new String[] {}) = false 3407 * StringUtils.isAnyBlank(new String[]{""}) = true 3408 * StringUtils.isAnyBlank("foo", "bar") = false 3409 * </pre> 3410 * 3411 * @param css the CharSequences to check, may be null or empty. 3412 * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3413 * @see #isBlank(CharSequence) 3414 * @since 3.2 3415 */ 3416 public static boolean isAnyBlank(final CharSequence... css) { 3417 if (ArrayUtils.isEmpty(css)) { 3418 return false; 3419 } 3420 for (final CharSequence cs : css) { 3421 if (isBlank(cs)) { 3422 return true; 3423 } 3424 } 3425 return false; 3426 } 3427 3428 /** 3429 * Tests if any of the CharSequences are empty ("") or null. 3430 * 3431 * <pre> 3432 * StringUtils.isAnyEmpty((String) null) = true 3433 * StringUtils.isAnyEmpty((String[]) null) = false 3434 * StringUtils.isAnyEmpty(null, "foo") = true 3435 * StringUtils.isAnyEmpty("", "bar") = true 3436 * StringUtils.isAnyEmpty("bob", "") = true 3437 * StringUtils.isAnyEmpty(" bob ", null) = true 3438 * StringUtils.isAnyEmpty(" ", "bar") = false 3439 * StringUtils.isAnyEmpty("foo", "bar") = false 3440 * StringUtils.isAnyEmpty(new String[]{}) = false 3441 * StringUtils.isAnyEmpty(new String[]{""}) = true 3442 * </pre> 3443 * 3444 * @param css the CharSequences to check, may be null or empty. 3445 * @return {@code true} if any of the CharSequences are empty or null. 3446 * @since 3.2 3447 */ 3448 public static boolean isAnyEmpty(final CharSequence... css) { 3449 if (ArrayUtils.isEmpty(css)) { 3450 return false; 3451 } 3452 for (final CharSequence cs : css) { 3453 if (isEmpty(cs)) { 3454 return true; 3455 } 3456 } 3457 return false; 3458 } 3459 3460 /** 3461 * Tests if the CharSequence contains only ASCII printable characters. 3462 * 3463 * <p> 3464 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3465 * </p> 3466 * 3467 * <pre> 3468 * StringUtils.isAsciiPrintable(null) = false 3469 * StringUtils.isAsciiPrintable("") = true 3470 * StringUtils.isAsciiPrintable(" ") = true 3471 * StringUtils.isAsciiPrintable("Ceki") = true 3472 * StringUtils.isAsciiPrintable("ab2c") = true 3473 * StringUtils.isAsciiPrintable("!ab-c~") = true 3474 * StringUtils.isAsciiPrintable("\u0020") = true 3475 * StringUtils.isAsciiPrintable("\u0021") = true 3476 * StringUtils.isAsciiPrintable("\u007e") = true 3477 * StringUtils.isAsciiPrintable("\u007f") = false 3478 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 3479 * </pre> 3480 * 3481 * @param cs the CharSequence to check, may be null. 3482 * @return {@code true} if every character is in the range 32 through 126. 3483 * @since 2.1 3484 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 3485 */ 3486 public static boolean isAsciiPrintable(final CharSequence cs) { 3487 if (cs == null) { 3488 return false; 3489 } 3490 final int sz = cs.length(); 3491 for (int i = 0; i < sz; i++) { 3492 if (!CharUtils.isAsciiPrintable(cs.charAt(i))) { 3493 return false; 3494 } 3495 } 3496 return true; 3497 } 3498 3499 /** 3500 * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}. 3501 * 3502 * <pre> 3503 * StringUtils.isBlank(null) = true 3504 * StringUtils.isBlank("") = true 3505 * StringUtils.isBlank(" ") = true 3506 * StringUtils.isBlank("bob") = false 3507 * StringUtils.isBlank(" bob ") = false 3508 * </pre> 3509 * 3510 * @param cs the CharSequence to check, may be null. 3511 * @return {@code true} if the CharSequence is null, empty or whitespace only. 3512 * @since 2.0 3513 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 3514 */ 3515 public static boolean isBlank(final CharSequence cs) { 3516 final int strLen = length(cs); 3517 for (int i = 0; i < strLen; i++) { 3518 if (!Character.isWhitespace(cs.charAt(i))) { 3519 return false; 3520 } 3521 } 3522 return true; 3523 } 3524 3525 /** 3526 * Tests if a CharSequence is empty ("") or null. 3527 * 3528 * <pre> 3529 * StringUtils.isEmpty(null) = true 3530 * StringUtils.isEmpty("") = true 3531 * StringUtils.isEmpty(" ") = false 3532 * StringUtils.isEmpty("bob") = false 3533 * StringUtils.isEmpty(" bob ") = false 3534 * </pre> 3535 * 3536 * <p> 3537 * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank(). 3538 * </p> 3539 * 3540 * @param cs the CharSequence to check, may be null. 3541 * @return {@code true} if the CharSequence is empty or null. 3542 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 3543 */ 3544 public static boolean isEmpty(final CharSequence cs) { 3545 return cs == null || cs.length() == 0; 3546 } 3547 3548 /** 3549 * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters. 3550 * 3551 * <p> 3552 * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}. 3553 * </p> 3554 * 3555 * <pre> 3556 * StringUtils.isMixedCase(null) = false 3557 * StringUtils.isMixedCase("") = false 3558 * StringUtils.isMixedCase(" ") = false 3559 * StringUtils.isMixedCase("ABC") = false 3560 * StringUtils.isMixedCase("abc") = false 3561 * StringUtils.isMixedCase("aBc") = true 3562 * StringUtils.isMixedCase("A c") = true 3563 * StringUtils.isMixedCase("A1c") = true 3564 * StringUtils.isMixedCase("a/C") = true 3565 * StringUtils.isMixedCase("aC\t") = true 3566 * </pre> 3567 * 3568 * @param cs the CharSequence to check, may be null. 3569 * @return {@code true} if the CharSequence contains both uppercase and lowercase characters. 3570 * @since 3.5 3571 */ 3572 public static boolean isMixedCase(final CharSequence cs) { 3573 if (isEmpty(cs) || cs.length() == 1) { 3574 return false; 3575 } 3576 boolean containsUppercase = false; 3577 boolean containsLowercase = false; 3578 final int sz = cs.length(); 3579 for (int i = 0; i < sz; i++) { 3580 final char nowChar = cs.charAt(i); 3581 if (Character.isUpperCase(nowChar)) { 3582 containsUppercase = true; 3583 } else if (Character.isLowerCase(nowChar)) { 3584 containsLowercase = true; 3585 } 3586 if (containsUppercase && containsLowercase) { 3587 return true; 3588 } 3589 } 3590 return false; 3591 } 3592 3593 /** 3594 * Tests if none of the CharSequences are empty (""), null or whitespace only. 3595 * 3596 * <p> 3597 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3598 * </p> 3599 * 3600 * <pre> 3601 * StringUtils.isNoneBlank((String) null) = false 3602 * StringUtils.isNoneBlank((String[]) null) = true 3603 * StringUtils.isNoneBlank(null, "foo") = false 3604 * StringUtils.isNoneBlank(null, null) = false 3605 * StringUtils.isNoneBlank("", "bar") = false 3606 * StringUtils.isNoneBlank("bob", "") = false 3607 * StringUtils.isNoneBlank(" bob ", null) = false 3608 * StringUtils.isNoneBlank(" ", "bar") = false 3609 * StringUtils.isNoneBlank(new String[] {}) = true 3610 * StringUtils.isNoneBlank(new String[]{""}) = false 3611 * StringUtils.isNoneBlank("foo", "bar") = true 3612 * </pre> 3613 * 3614 * @param css the CharSequences to check, may be null or empty. 3615 * @return {@code true} if none of the CharSequences are empty or null or whitespace only. 3616 * @since 3.2 3617 */ 3618 public static boolean isNoneBlank(final CharSequence... css) { 3619 return !isAnyBlank(css); 3620 } 3621 3622 /** 3623 * Tests if none of the CharSequences are empty ("") or null. 3624 * 3625 * <pre> 3626 * StringUtils.isNoneEmpty((String) null) = false 3627 * StringUtils.isNoneEmpty((String[]) null) = true 3628 * StringUtils.isNoneEmpty(null, "foo") = false 3629 * StringUtils.isNoneEmpty("", "bar") = false 3630 * StringUtils.isNoneEmpty("bob", "") = false 3631 * StringUtils.isNoneEmpty(" bob ", null) = false 3632 * StringUtils.isNoneEmpty(new String[] {}) = true 3633 * StringUtils.isNoneEmpty(new String[]{""}) = false 3634 * StringUtils.isNoneEmpty(" ", "bar") = true 3635 * StringUtils.isNoneEmpty("foo", "bar") = true 3636 * </pre> 3637 * 3638 * @param css the CharSequences to check, may be null or empty. 3639 * @return {@code true} if none of the CharSequences are empty or null. 3640 * @since 3.2 3641 */ 3642 public static boolean isNoneEmpty(final CharSequence... css) { 3643 return !isAnyEmpty(css); 3644 } 3645 3646 /** 3647 * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3648 * 3649 * <p> 3650 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3651 * </p> 3652 * 3653 * <pre> 3654 * StringUtils.isNotBlank(null) = false 3655 * StringUtils.isNotBlank("") = false 3656 * StringUtils.isNotBlank(" ") = false 3657 * StringUtils.isNotBlank("bob") = true 3658 * StringUtils.isNotBlank(" bob ") = true 3659 * </pre> 3660 * 3661 * @param cs the CharSequence to check, may be null. 3662 * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}). 3663 * @see #isBlank(CharSequence) 3664 * @since 2.0 3665 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 3666 */ 3667 public static boolean isNotBlank(final CharSequence cs) { 3668 return !isBlank(cs); 3669 } 3670 3671 /** 3672 * Tests if a CharSequence is not empty ("") and not null. 3673 * 3674 * <pre> 3675 * StringUtils.isNotEmpty(null) = false 3676 * StringUtils.isNotEmpty("") = false 3677 * StringUtils.isNotEmpty(" ") = true 3678 * StringUtils.isNotEmpty("bob") = true 3679 * StringUtils.isNotEmpty(" bob ") = true 3680 * </pre> 3681 * 3682 * @param cs the CharSequence to check, may be null. 3683 * @return {@code true} if the CharSequence is not empty and not null. 3684 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 3685 */ 3686 public static boolean isNotEmpty(final CharSequence cs) { 3687 return !isEmpty(cs); 3688 } 3689 3690 /** 3691 * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false. 3692 * 3693 * <p> 3694 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}. 3695 * </p> 3696 * 3697 * <p> 3698 * 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 3699 * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively. 3700 * </p> 3701 * 3702 * <pre> 3703 * StringUtils.isNumeric(null) = false 3704 * StringUtils.isNumeric("") = false 3705 * StringUtils.isNumeric(" ") = false 3706 * StringUtils.isNumeric("123") = true 3707 * StringUtils.isNumeric("\u0967\u0968\u0969") = true 3708 * StringUtils.isNumeric("12 3") = false 3709 * StringUtils.isNumeric("ab2c") = false 3710 * StringUtils.isNumeric("12-3") = false 3711 * StringUtils.isNumeric("12.3") = false 3712 * StringUtils.isNumeric("-123") = false 3713 * StringUtils.isNumeric("+123") = false 3714 * </pre> 3715 * 3716 * @param cs the CharSequence to check, may be null. 3717 * @return {@code true} if only contains digits, and is non-null. 3718 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 3719 * @since 3.0 Changed "" to return false and not true 3720 */ 3721 public static boolean isNumeric(final CharSequence cs) { 3722 if (isEmpty(cs)) { 3723 return false; 3724 } 3725 final int sz = cs.length(); 3726 for (int i = 0; i < sz; i++) { 3727 if (!Character.isDigit(cs.charAt(i))) { 3728 return false; 3729 } 3730 } 3731 return true; 3732 } 3733 3734 /** 3735 * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false. 3736 * 3737 * <p> 3738 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3739 * </p> 3740 * 3741 * <pre> 3742 * StringUtils.isNumericSpace(null) = false 3743 * StringUtils.isNumericSpace("") = true 3744 * StringUtils.isNumericSpace(" ") = true 3745 * StringUtils.isNumericSpace("123") = true 3746 * StringUtils.isNumericSpace("12 3") = true 3747 * StringUtils.isNumericSpace("\u0967\u0968\u0969") = true 3748 * StringUtils.isNumericSpace("\u0967\u0968 \u0969") = true 3749 * StringUtils.isNumericSpace("ab2c") = false 3750 * StringUtils.isNumericSpace("12-3") = false 3751 * StringUtils.isNumericSpace("12.3") = false 3752 * </pre> 3753 * 3754 * @param cs the CharSequence to check, may be null. 3755 * @return {@code true} if only contains digits or space, and is non-null. 3756 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 3757 */ 3758 public static boolean isNumericSpace(final CharSequence cs) { 3759 if (cs == null) { 3760 return false; 3761 } 3762 final int sz = cs.length(); 3763 for (int i = 0; i < sz; i++) { 3764 final char nowChar = cs.charAt(i); 3765 if (nowChar != ' ' && !Character.isDigit(nowChar)) { 3766 return false; 3767 } 3768 } 3769 return true; 3770 } 3771 3772 /** 3773 * Tests if the CharSequence contains only whitespace. 3774 * 3775 * <p> 3776 * Whitespace is defined by {@link Character#isWhitespace(char)}. 3777 * </p> 3778 * 3779 * <p> 3780 * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}. 3781 * </p> 3782 * 3783 * <pre> 3784 * StringUtils.isWhitespace(null) = false 3785 * StringUtils.isWhitespace("") = true 3786 * StringUtils.isWhitespace(" ") = true 3787 * StringUtils.isWhitespace("abc") = false 3788 * StringUtils.isWhitespace("ab2c") = false 3789 * StringUtils.isWhitespace("ab-c") = false 3790 * </pre> 3791 * 3792 * @param cs the CharSequence to check, may be null. 3793 * @return {@code true} if only contains whitespace, and is non-null. 3794 * @since 2.0 3795 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 3796 */ 3797 public static boolean isWhitespace(final CharSequence cs) { 3798 if (cs == null) { 3799 return false; 3800 } 3801 final int sz = cs.length(); 3802 for (int i = 0; i < sz; i++) { 3803 if (!Character.isWhitespace(cs.charAt(i))) { 3804 return false; 3805 } 3806 } 3807 return true; 3808 } 3809 3810 /** 3811 * Joins the elements of the provided array into a single String containing the provided list of elements. 3812 * 3813 * <p> 3814 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 3815 * </p> 3816 * 3817 * <pre> 3818 * StringUtils.join(null, *) = null 3819 * StringUtils.join([], *) = "" 3820 * StringUtils.join([null], *) = "" 3821 * StringUtils.join([false, false], ';') = "false;false" 3822 * </pre> 3823 * 3824 * @param array the array of values to join together, may be null. 3825 * @param delimiter the separator character to use. 3826 * @return the joined String, {@code null} if null array input. 3827 * @since 3.12.0 3828 */ 3829 public static String join(final boolean[] array, final char delimiter) { 3830 if (array == null) { 3831 return null; 3832 } 3833 return join(array, delimiter, 0, array.length); 3834 } 3835 3836 /** 3837 * Joins the elements of the provided array into a single String containing the provided list of elements. 3838 * 3839 * <p> 3840 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3841 * by empty strings. 3842 * </p> 3843 * 3844 * <pre> 3845 * StringUtils.join(null, *) = null 3846 * StringUtils.join([], *) = "" 3847 * StringUtils.join([null], *) = "" 3848 * StringUtils.join([true, false, true], ';') = "true;false;true" 3849 * </pre> 3850 * 3851 * @param array 3852 * the array of values to join together, may be null. 3853 * @param delimiter 3854 * the separator character to use. 3855 * @param startIndex 3856 * the first index to start joining from. It is an error to pass in a start index past the end of the 3857 * array. 3858 * @param endIndex 3859 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3860 * the array. 3861 * @return the joined String, {@code null} if null array input. 3862 * @since 3.12.0 3863 */ 3864 public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) { 3865 // See StringUtilsJoinBenchmark 3866 if (array == null) { 3867 return null; 3868 } 3869 final int count = endIndex - startIndex; 3870 if (count <= 0) { 3871 return EMPTY; 3872 } 3873 final byte maxElementChars = 5; // "false" 3874 final StringBuilder stringBuilder = capacity(count, maxElementChars); 3875 stringBuilder.append(array[startIndex]); 3876 for (int i = startIndex + 1; i < endIndex; i++) { 3877 stringBuilder.append(delimiter).append(array[i]); 3878 } 3879 return stringBuilder.toString(); 3880 } 3881 3882 /** 3883 * Joins the elements of the provided array into a single String containing the provided list of elements. 3884 * 3885 * <p> 3886 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3887 * by empty strings. 3888 * </p> 3889 * 3890 * <pre> 3891 * StringUtils.join(null, *) = null 3892 * StringUtils.join([], *) = "" 3893 * StringUtils.join([null], *) = "" 3894 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3895 * StringUtils.join([1, 2, 3], null) = "123" 3896 * </pre> 3897 * 3898 * @param array 3899 * the array of values to join together, may be null. 3900 * @param delimiter 3901 * the separator character to use. 3902 * @return the joined String, {@code null} if null array input. 3903 * @since 3.2 3904 */ 3905 public static String join(final byte[] array, final char delimiter) { 3906 if (array == null) { 3907 return null; 3908 } 3909 return join(array, delimiter, 0, array.length); 3910 } 3911 3912 /** 3913 * Joins the elements of the provided array into a single String containing the provided list of elements. 3914 * 3915 * <p> 3916 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3917 * by empty strings. 3918 * </p> 3919 * 3920 * <pre> 3921 * StringUtils.join(null, *) = null 3922 * StringUtils.join([], *) = "" 3923 * StringUtils.join([null], *) = "" 3924 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3925 * StringUtils.join([1, 2, 3], null) = "123" 3926 * </pre> 3927 * 3928 * @param array 3929 * the array of values to join together, may be null. 3930 * @param delimiter 3931 * the separator character to use. 3932 * @param startIndex 3933 * the first index to start joining from. It is an error to pass in a start index past the end of the 3934 * array. 3935 * @param endIndex 3936 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3937 * the array. 3938 * @return the joined String, {@code null} if null array input. 3939 * @since 3.2 3940 */ 3941 public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) { 3942 // See StringUtilsJoinBenchmark 3943 if (array == null) { 3944 return null; 3945 } 3946 final int count = endIndex - startIndex; 3947 if (count <= 0) { 3948 return EMPTY; 3949 } 3950 final byte maxElementChars = 4; // "-128" 3951 final StringBuilder stringBuilder = capacity(count, maxElementChars); 3952 stringBuilder.append(array[startIndex]); 3953 for (int i = startIndex + 1; i < endIndex; i++) { 3954 stringBuilder.append(delimiter).append(array[i]); 3955 } 3956 return stringBuilder.toString(); 3957 } 3958 3959 /** 3960 * Joins the elements of the provided array into a single String containing the provided list of elements. 3961 * 3962 * <p> 3963 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3964 * by empty strings. 3965 * </p> 3966 * 3967 * <pre> 3968 * StringUtils.join(null, *) = null 3969 * StringUtils.join([], *) = "" 3970 * StringUtils.join([null], *) = "" 3971 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3972 * StringUtils.join([1, 2, 3], null) = "123" 3973 * </pre> 3974 * 3975 * @param array 3976 * the array of values to join together, may be null. 3977 * @param delimiter 3978 * the separator character to use. 3979 * @return the joined String, {@code null} if null array input. 3980 * @since 3.2 3981 */ 3982 public static String join(final char[] array, final char delimiter) { 3983 if (array == null) { 3984 return null; 3985 } 3986 return join(array, delimiter, 0, array.length); 3987 } 3988 3989 /** 3990 * Joins the elements of the provided array into a single String containing the provided list of elements. 3991 * 3992 * <p> 3993 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3994 * by empty strings. 3995 * </p> 3996 * 3997 * <pre> 3998 * StringUtils.join(null, *) = null 3999 * StringUtils.join([], *) = "" 4000 * StringUtils.join([null], *) = "" 4001 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4002 * StringUtils.join([1, 2, 3], null) = "123" 4003 * </pre> 4004 * 4005 * @param array 4006 * the array of values to join together, may be null. 4007 * @param delimiter 4008 * the separator character to use. 4009 * @param startIndex 4010 * the first index to start joining from. It is an error to pass in a start index past the end of the 4011 * array. 4012 * @param endIndex 4013 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4014 * the array. 4015 * @return the joined String, {@code null} if null array input. 4016 * @since 3.2 4017 */ 4018 public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) { 4019 // See StringUtilsJoinBenchmark 4020 if (array == null) { 4021 return null; 4022 } 4023 final int count = endIndex - startIndex; 4024 if (count <= 0) { 4025 return EMPTY; 4026 } 4027 final byte maxElementChars = 1; 4028 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4029 stringBuilder.append(array[startIndex]); 4030 for (int i = startIndex + 1; i < endIndex; i++) { 4031 stringBuilder.append(delimiter).append(array[i]); 4032 } 4033 return stringBuilder.toString(); 4034 } 4035 4036 /** 4037 * Joins the elements of the provided array into a single String containing the provided list of elements. 4038 * 4039 * <p> 4040 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4041 * by empty strings. 4042 * </p> 4043 * 4044 * <pre> 4045 * StringUtils.join(null, *) = null 4046 * StringUtils.join([], *) = "" 4047 * StringUtils.join([null], *) = "" 4048 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4049 * StringUtils.join([1, 2, 3], null) = "123" 4050 * </pre> 4051 * 4052 * @param array 4053 * the array of values to join together, may be null. 4054 * @param delimiter 4055 * the separator character to use. 4056 * @return the joined String, {@code null} if null array input. 4057 * @since 3.2 4058 */ 4059 public static String join(final double[] array, final char delimiter) { 4060 if (array == null) { 4061 return null; 4062 } 4063 return join(array, delimiter, 0, array.length); 4064 } 4065 4066 /** 4067 * Joins the elements of the provided array into a single String containing the provided list of elements. 4068 * 4069 * <p> 4070 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4071 * by empty strings. 4072 * </p> 4073 * 4074 * <pre> 4075 * StringUtils.join(null, *) = null 4076 * StringUtils.join([], *) = "" 4077 * StringUtils.join([null], *) = "" 4078 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4079 * StringUtils.join([1, 2, 3], null) = "123" 4080 * </pre> 4081 * 4082 * @param array 4083 * the array of values to join together, may be null. 4084 * @param delimiter 4085 * the separator character to use. 4086 * @param startIndex 4087 * the first index to start joining from. It is an error to pass in a start index past the end of the 4088 * array. 4089 * @param endIndex 4090 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4091 * the array. 4092 * @return the joined String, {@code null} if null array input. 4093 * @since 3.2 4094 */ 4095 public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) { 4096 // See StringUtilsJoinBenchmark 4097 if (array == null) { 4098 return null; 4099 } 4100 final int count = endIndex - startIndex; 4101 if (count <= 0) { 4102 return EMPTY; 4103 } 4104 final byte maxElementChars = 22; // "1.7976931348623157E308" 4105 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4106 stringBuilder.append(array[startIndex]); 4107 for (int i = startIndex + 1; i < endIndex; i++) { 4108 stringBuilder.append(delimiter).append(array[i]); 4109 } 4110 return stringBuilder.toString(); 4111 } 4112 4113 /** 4114 * Joins the elements of the provided array into a single String containing the provided list of elements. 4115 * 4116 * <p> 4117 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4118 * by empty strings. 4119 * </p> 4120 * 4121 * <pre> 4122 * StringUtils.join(null, *) = null 4123 * StringUtils.join([], *) = "" 4124 * StringUtils.join([null], *) = "" 4125 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4126 * StringUtils.join([1, 2, 3], null) = "123" 4127 * </pre> 4128 * 4129 * @param array 4130 * the array of values to join together, may be null. 4131 * @param delimiter 4132 * the separator character to use. 4133 * @return the joined String, {@code null} if null array input 4134 * @since 3.2 4135 */ 4136 public static String join(final float[] array, final char delimiter) { 4137 if (array == null) { 4138 return null; 4139 } 4140 return join(array, delimiter, 0, array.length); 4141 } 4142 4143 /** 4144 * Joins the elements of the provided array into a single String containing the provided list of elements. 4145 * 4146 * <p> 4147 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4148 * by empty strings. 4149 * </p> 4150 * 4151 * <pre> 4152 * StringUtils.join(null, *) = null 4153 * StringUtils.join([], *) = "" 4154 * StringUtils.join([null], *) = "" 4155 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4156 * StringUtils.join([1, 2, 3], null) = "123" 4157 * </pre> 4158 * 4159 * @param array 4160 * the array of values to join together, may be null. 4161 * @param delimiter 4162 * the separator character to use. 4163 * @param startIndex 4164 * the first index to start joining from. It is an error to pass in a start index past the end of the 4165 * array. 4166 * @param endIndex 4167 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4168 * the array. 4169 * @return the joined String, {@code null} if null array input. 4170 * @since 3.2 4171 */ 4172 public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) { 4173 // See StringUtilsJoinBenchmark 4174 if (array == null) { 4175 return null; 4176 } 4177 final int count = endIndex - startIndex; 4178 if (count <= 0) { 4179 return EMPTY; 4180 } 4181 final byte maxElementChars = 12; // "3.4028235E38" 4182 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4183 stringBuilder.append(array[startIndex]); 4184 for (int i = startIndex + 1; i < endIndex; i++) { 4185 stringBuilder.append(delimiter).append(array[i]); 4186 } 4187 return stringBuilder.toString(); 4188 } 4189 4190 /** 4191 * Joins the elements of the provided array into a single String containing the provided list of elements. 4192 * 4193 * <p> 4194 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4195 * by empty strings. 4196 * </p> 4197 * 4198 * <pre> 4199 * StringUtils.join(null, *) = null 4200 * StringUtils.join([], *) = "" 4201 * StringUtils.join([null], *) = "" 4202 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4203 * StringUtils.join([1, 2, 3], null) = "123" 4204 * </pre> 4205 * 4206 * @param array 4207 * the array of values to join together, may be null. 4208 * @param separator 4209 * the separator character to use. 4210 * @return the joined String, {@code null} if null array input. 4211 * @since 3.2 4212 */ 4213 public static String join(final int[] array, final char separator) { 4214 if (array == null) { 4215 return null; 4216 } 4217 return join(array, separator, 0, array.length); 4218 } 4219 4220 /** 4221 * Joins the elements of the provided array into a single String containing the provided list of elements. 4222 * 4223 * <p> 4224 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4225 * by empty strings. 4226 * </p> 4227 * 4228 * <pre> 4229 * StringUtils.join(null, *) = null 4230 * StringUtils.join([], *) = "" 4231 * StringUtils.join([null], *) = "" 4232 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4233 * StringUtils.join([1, 2, 3], null) = "123" 4234 * </pre> 4235 * 4236 * @param array 4237 * the array of values to join together, may be null. 4238 * @param delimiter 4239 * the separator character to use. 4240 * @param startIndex 4241 * the first index to start joining from. It is an error to pass in a start index past the end of the 4242 * array. 4243 * @param endIndex 4244 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4245 * the array. 4246 * @return the joined String, {@code null} if null array input. 4247 * @since 3.2 4248 */ 4249 public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) { 4250 // See StringUtilsJoinBenchmark 4251 if (array == null) { 4252 return null; 4253 } 4254 final int count = endIndex - startIndex; 4255 if (count <= 0) { 4256 return EMPTY; 4257 } 4258 final byte maxElementChars = 11; // "-2147483648" 4259 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4260 stringBuilder.append(array[startIndex]); 4261 for (int i = startIndex + 1; i < endIndex; i++) { 4262 stringBuilder.append(delimiter).append(array[i]); 4263 } 4264 return stringBuilder.toString(); 4265 } 4266 4267 /** 4268 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4269 * 4270 * <p> 4271 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4272 * </p> 4273 * 4274 * <p> 4275 * See the examples here: {@link #join(Object[],char)}. 4276 * </p> 4277 * 4278 * @param iterable the {@link Iterable} providing the values to join together, may be null. 4279 * @param separator the separator character to use. 4280 * @return the joined String, {@code null} if null iterator input. 4281 * @since 2.3 4282 */ 4283 public static String join(final Iterable<?> iterable, final char separator) { 4284 return iterable != null ? join(iterable.iterator(), separator) : null; 4285 } 4286 4287 /** 4288 * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements. 4289 * 4290 * <p> 4291 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4292 * </p> 4293 * 4294 * <p> 4295 * See the examples here: {@link #join(Object[],String)}. 4296 * </p> 4297 * 4298 * @param iterable the {@link Iterable} providing the values to join together, may be null. 4299 * @param separator the separator character to use, null treated as "". 4300 * @return the joined String, {@code null} if null iterator input. 4301 * @since 2.3 4302 */ 4303 public static String join(final Iterable<?> iterable, final String separator) { 4304 return iterable != null ? join(iterable.iterator(), separator) : null; 4305 } 4306 4307 /** 4308 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4309 * 4310 * <p> 4311 * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings. 4312 * </p> 4313 * 4314 * <p> 4315 * See the examples here: {@link #join(Object[],char)}. 4316 * </p> 4317 * 4318 * @param iterator the {@link Iterator} of values to join together, may be null. 4319 * @param separator the separator character to use. 4320 * @return the joined String, {@code null} if null iterator input. 4321 * @since 2.0 4322 */ 4323 public static String join(final Iterator<?> iterator, final char separator) { 4324 // handle null, zero and one elements before building a buffer 4325 if (iterator == null) { 4326 return null; 4327 } 4328 if (!iterator.hasNext()) { 4329 return EMPTY; 4330 } 4331 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString)); 4332 } 4333 4334 /** 4335 * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements. 4336 * 4337 * <p> 4338 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). 4339 * </p> 4340 * 4341 * <p> 4342 * See the examples here: {@link #join(Object[],String)}. 4343 * </p> 4344 * 4345 * @param iterator the {@link Iterator} of values to join together, may be null. 4346 * @param separator the separator character to use, null treated as "". 4347 * @return the joined String, {@code null} if null iterator input. 4348 */ 4349 public static String join(final Iterator<?> iterator, final String separator) { 4350 // handle null, zero and one elements before building a buffer 4351 if (iterator == null) { 4352 return null; 4353 } 4354 if (!iterator.hasNext()) { 4355 return EMPTY; 4356 } 4357 return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString)); 4358 } 4359 4360 /** 4361 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4362 * 4363 * <p> 4364 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4365 * </p> 4366 * 4367 * <pre> 4368 * StringUtils.join(null, *) = null 4369 * StringUtils.join([], *) = "" 4370 * StringUtils.join([null], *) = "" 4371 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4372 * StringUtils.join(["a", "b", "c"], null) = "abc" 4373 * StringUtils.join([null, "", "a"], ';') = ";;a" 4374 * </pre> 4375 * 4376 * @param list the {@link List} of values to join together, may be null. 4377 * @param separator the separator character to use. 4378 * @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. 4379 * @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. 4380 * @return the joined String, {@code null} if null list input. 4381 * @since 3.8 4382 */ 4383 public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) { 4384 if (list == null) { 4385 return null; 4386 } 4387 final int noOfItems = endIndex - startIndex; 4388 if (noOfItems <= 0) { 4389 return EMPTY; 4390 } 4391 final List<?> subList = list.subList(startIndex, endIndex); 4392 return join(subList.iterator(), separator); 4393 } 4394 4395 /** 4396 * Joins the elements of the provided {@link List} into a single String containing the provided list of elements. 4397 * 4398 * <p> 4399 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4400 * </p> 4401 * 4402 * <pre> 4403 * StringUtils.join(null, *) = null 4404 * StringUtils.join([], *) = "" 4405 * StringUtils.join([null], *) = "" 4406 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4407 * StringUtils.join(["a", "b", "c"], null) = "abc" 4408 * StringUtils.join([null, "", "a"], ';') = ";;a" 4409 * </pre> 4410 * 4411 * @param list the {@link List} of values to join together, may be null. 4412 * @param separator the separator character to use. 4413 * @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. 4414 * @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. 4415 * @return the joined String, {@code null} if null list input. 4416 * @since 3.8 4417 */ 4418 public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) { 4419 if (list == null) { 4420 return null; 4421 } 4422 final int noOfItems = endIndex - startIndex; 4423 if (noOfItems <= 0) { 4424 return EMPTY; 4425 } 4426 final List<?> subList = list.subList(startIndex, endIndex); 4427 return join(subList.iterator(), separator); 4428 } 4429 4430 /** 4431 * Joins the elements of the provided array into a single String containing the provided list of elements. 4432 * 4433 * <p> 4434 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4435 * by empty strings. 4436 * </p> 4437 * 4438 * <pre> 4439 * StringUtils.join(null, *) = null 4440 * StringUtils.join([], *) = "" 4441 * StringUtils.join([null], *) = "" 4442 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4443 * StringUtils.join([1, 2, 3], null) = "123" 4444 * </pre> 4445 * 4446 * @param array 4447 * the array of values to join together, may be null. 4448 * @param separator 4449 * the separator character to use. 4450 * @return the joined String, {@code null} if null array input. 4451 * @since 3.2 4452 */ 4453 public static String join(final long[] array, final char separator) { 4454 if (array == null) { 4455 return null; 4456 } 4457 return join(array, separator, 0, array.length); 4458 } 4459 4460 /** 4461 * Joins the elements of the provided array into a single String containing the provided list of elements. 4462 * 4463 * <p> 4464 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4465 * by empty strings. 4466 * </p> 4467 * 4468 * <pre> 4469 * StringUtils.join(null, *) = null 4470 * StringUtils.join([], *) = "" 4471 * StringUtils.join([null], *) = "" 4472 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4473 * StringUtils.join([1, 2, 3], null) = "123" 4474 * </pre> 4475 * 4476 * @param array 4477 * the array of values to join together, may be null. 4478 * @param delimiter 4479 * the separator character to use. 4480 * @param startIndex 4481 * the first index to start joining from. It is an error to pass in a start index past the end of the 4482 * array. 4483 * @param endIndex 4484 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4485 * the array. 4486 * @return the joined String, {@code null} if null array input. 4487 * @since 3.2 4488 */ 4489 public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) { 4490 // See StringUtilsJoinBenchmark 4491 if (array == null) { 4492 return null; 4493 } 4494 final int count = endIndex - startIndex; 4495 if (count <= 0) { 4496 return EMPTY; 4497 } 4498 final byte maxElementChars = 20; // "-9223372036854775808" 4499 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4500 stringBuilder.append(array[startIndex]); 4501 for (int i = startIndex + 1; i < endIndex; i++) { 4502 stringBuilder.append(delimiter).append(array[i]); 4503 } 4504 return stringBuilder.toString(); 4505 } 4506 4507 /** 4508 * Joins the elements of the provided array into a single String containing the provided list of elements. 4509 * 4510 * <p> 4511 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4512 * </p> 4513 * 4514 * <pre> 4515 * StringUtils.join(null, *) = null 4516 * StringUtils.join([], *) = "" 4517 * StringUtils.join([null], *) = "" 4518 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4519 * StringUtils.join(["a", "b", "c"], null) = "abc" 4520 * StringUtils.join([null, "", "a"], ';') = ";;a" 4521 * </pre> 4522 * 4523 * @param array the array of values to join together, may be null. 4524 * @param delimiter the separator character to use. 4525 * @return the joined String, {@code null} if null array input. 4526 * @since 2.0 4527 */ 4528 public static String join(final Object[] array, final char delimiter) { 4529 if (array == null) { 4530 return null; 4531 } 4532 return join(array, delimiter, 0, array.length); 4533 } 4534 4535 /** 4536 * Joins the elements of the provided array into a single String containing the provided list of elements. 4537 * 4538 * <p> 4539 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings. 4540 * </p> 4541 * 4542 * <pre> 4543 * StringUtils.join(null, *) = null 4544 * StringUtils.join([], *) = "" 4545 * StringUtils.join([null], *) = "" 4546 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 4547 * StringUtils.join(["a", "b", "c"], null) = "abc" 4548 * StringUtils.join([null, "", "a"], ';') = ";;a" 4549 * </pre> 4550 * 4551 * @param array the array of values to join together, may be null. 4552 * @param delimiter the separator character to use. 4553 * @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. 4554 * @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. 4555 * @return the joined String, {@code null} if null array input. 4556 * @since 2.0 4557 */ 4558 public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { 4559 return join(array, String.valueOf(delimiter), startIndex, endIndex); 4560 } 4561 4562 /** 4563 * Joins the elements of the provided array into a single String containing the provided list of elements. 4564 * 4565 * <p> 4566 * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the 4567 * array are represented by empty strings. 4568 * </p> 4569 * 4570 * <pre> 4571 * StringUtils.join(null, *) = null 4572 * StringUtils.join([], *) = "" 4573 * StringUtils.join([null], *) = "" 4574 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 4575 * StringUtils.join(["a", "b", "c"], null) = "abc" 4576 * StringUtils.join(["a", "b", "c"], "") = "abc" 4577 * StringUtils.join([null, "", "a"], ',') = ",,a" 4578 * </pre> 4579 * 4580 * @param array the array of values to join together, may be null. 4581 * @param delimiter the separator character to use, null treated as "". 4582 * @return the joined String, {@code null} if null array input. 4583 */ 4584 public static String join(final Object[] array, final String delimiter) { 4585 return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null; 4586 } 4587 4588 /** 4589 * Joins the elements of the provided array into a single String containing the provided list of elements. 4590 * 4591 * <p> 4592 * 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 4593 * array are represented by empty strings. 4594 * </p> 4595 * 4596 * <pre> 4597 * StringUtils.join(null, *, *, *) = null 4598 * StringUtils.join([], *, *, *) = "" 4599 * StringUtils.join([null], *, *, *) = "" 4600 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 4601 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 4602 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 4603 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 4604 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 4605 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 4606 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 4607 * </pre> 4608 * 4609 * @param array the array of values to join together, may be null. 4610 * @param delimiter the separator character to use, null treated as "". 4611 * @param startIndex the first index to start joining from. 4612 * @param endIndex the index to stop joining from (exclusive). 4613 * @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 4614 * given by {@code endIndex - startIndex}. 4615 * @throws ArrayIndexOutOfBoundsException ife<br> 4616 * {@code startIndex < 0} or <br> 4617 * {@code startIndex >= array.length()} or <br> 4618 * {@code endIndex < 0} or <br> 4619 * {@code endIndex > array.length()} 4620 */ 4621 public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) { 4622 return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex)) 4623 .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null; 4624 } 4625 4626 /** 4627 * Joins the elements of the provided array into a single String containing the provided list of elements. 4628 * 4629 * <p> 4630 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4631 * by empty strings. 4632 * </p> 4633 * 4634 * <pre> 4635 * StringUtils.join(null, *) = null 4636 * StringUtils.join([], *) = "" 4637 * StringUtils.join([null], *) = "" 4638 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4639 * StringUtils.join([1, 2, 3], null) = "123" 4640 * </pre> 4641 * 4642 * @param array 4643 * the array of values to join together, may be null. 4644 * @param delimiter 4645 * the separator character to use. 4646 * @return the joined String, {@code null} if null array input. 4647 * @since 3.2 4648 */ 4649 public static String join(final short[] array, final char delimiter) { 4650 if (array == null) { 4651 return null; 4652 } 4653 return join(array, delimiter, 0, array.length); 4654 } 4655 4656 /** 4657 * Joins the elements of the provided array into a single String containing the provided list of elements. 4658 * 4659 * <p> 4660 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 4661 * by empty strings. 4662 * </p> 4663 * 4664 * <pre> 4665 * StringUtils.join(null, *) = null 4666 * StringUtils.join([], *) = "" 4667 * StringUtils.join([null], *) = "" 4668 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 4669 * StringUtils.join([1, 2, 3], null) = "123" 4670 * </pre> 4671 * 4672 * @param array 4673 * the array of values to join together, may be null. 4674 * @param delimiter 4675 * the separator character to use. 4676 * @param startIndex 4677 * the first index to start joining from. It is an error to pass in a start index past the end of the 4678 * array. 4679 * @param endIndex 4680 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 4681 * the array. 4682 * @return the joined String, {@code null} if null array input. 4683 * @since 3.2 4684 */ 4685 public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) { 4686 // See StringUtilsJoinBenchmark 4687 if (array == null) { 4688 return null; 4689 } 4690 final int count = endIndex - startIndex; 4691 if (count <= 0) { 4692 return EMPTY; 4693 } 4694 final byte maxElementChars = 6; // "-32768" 4695 final StringBuilder stringBuilder = capacity(count, maxElementChars); 4696 stringBuilder.append(array[startIndex]); 4697 for (int i = startIndex + 1; i < endIndex; i++) { 4698 stringBuilder.append(delimiter).append(array[i]); 4699 } 4700 return stringBuilder.toString(); 4701 } 4702 4703 /** 4704 * Joins the elements of the provided array into a single String containing the provided list of elements. 4705 * 4706 * <p> 4707 * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings. 4708 * </p> 4709 * 4710 * <pre> 4711 * StringUtils.join(null) = null 4712 * StringUtils.join([]) = "" 4713 * StringUtils.join([null]) = "" 4714 * StringUtils.join("a", "b", "c") = "abc" 4715 * StringUtils.join(null, "", "a") = "a" 4716 * </pre> 4717 * 4718 * @param <T> the specific type of values to join together. 4719 * @param elements the values to join together, may be null. 4720 * @return the joined String, {@code null} if null array input. 4721 * @since 2.0 4722 * @since 3.0 Changed signature to use varargs 4723 */ 4724 @SafeVarargs 4725 public static <T> String join(final T... elements) { 4726 return join(elements, null); 4727 } 4728 4729 /** 4730 * Joins the elements of the provided varargs into a single String containing the provided elements. 4731 * 4732 * <p> 4733 * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings (""). 4734 * </p> 4735 * 4736 * <pre> 4737 * StringUtils.joinWith(",", "a", "b") = "a,b" 4738 * StringUtils.joinWith(",", "a", "b","") = "a,b," 4739 * StringUtils.joinWith(",", "a", null, "b") = "a,,b" 4740 * StringUtils.joinWith(null, "a", "b") = "ab" 4741 * </pre> 4742 * 4743 * @param delimiter the separator character to use, null treated as "". 4744 * @param array the varargs providing the values to join together. {@code null} elements are treated as "". 4745 * @return the joined String. 4746 * @throws IllegalArgumentException if a null varargs is provided. 4747 * @since 3.5 4748 */ 4749 public static String joinWith(final String delimiter, final Object... array) { 4750 if (array == null) { 4751 throw new IllegalArgumentException("Object varargs must not be null"); 4752 } 4753 return join(array, delimiter); 4754 } 4755 4756 /** 4757 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible. 4758 * 4759 * <p> 4760 * A {@code null} CharSequence will return {@code -1}. 4761 * </p> 4762 * 4763 * <pre> 4764 * StringUtils.lastIndexOf(null, *) = -1 4765 * StringUtils.lastIndexOf(*, null) = -1 4766 * StringUtils.lastIndexOf("", "") = 0 4767 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 4768 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 4769 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 4770 * StringUtils.lastIndexOf("aabaabaa", "") = 8 4771 * </pre> 4772 * 4773 * @param seq the CharSequence to check, may be null. 4774 * @param searchSeq the CharSequence to find, may be null. 4775 * @return the last index of the search String, -1 if no match or {@code null} string input. 4776 * @since 2.0 4777 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 4778 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}. 4779 */ 4780 @Deprecated 4781 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 4782 return Strings.CS.lastIndexOf(seq, searchSeq); 4783 } 4784 4785 /** 4786 * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible. 4787 * 4788 * <p> 4789 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4790 * 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 4791 * backwards; matches starting after the start position are ignored. 4792 * </p> 4793 * 4794 * <pre> 4795 * StringUtils.lastIndexOf(null, *, *) = -1 4796 * StringUtils.lastIndexOf(*, null, *) = -1 4797 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 4798 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 4799 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 4800 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 4801 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 4802 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 4803 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 4804 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 4805 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 4806 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 4807 * </pre> 4808 * 4809 * @param seq the CharSequence to check, may be null. 4810 * @param searchSeq the CharSequence to find, may be null. 4811 * @param startPos the start position, negative treated as zero. 4812 * @return the last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} string input. 4813 * @since 2.0 4814 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 4815 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}. 4816 */ 4817 @Deprecated 4818 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 4819 return Strings.CS.lastIndexOf(seq, searchSeq, startPos); 4820 } 4821 4822 /** 4823 * 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 4824 * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that: 4825 * 4826 * <pre> 4827 * this.charAt(<em>k</em>) == searchChar 4828 * </pre> 4829 * 4830 * <p> 4831 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4832 * </p> 4833 * 4834 * <pre> 4835 * this.codePointAt(<em>k</em>) == searchChar 4836 * </pre> 4837 * 4838 * <p> 4839 * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("") 4840 * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character. 4841 * </p> 4842 * 4843 * <pre> 4844 * StringUtils.lastIndexOf(null, *) = -1 4845 * StringUtils.lastIndexOf("", *) = -1 4846 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 4847 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 4848 * </pre> 4849 * 4850 * @param seq the {@link CharSequence} to check, may be null. 4851 * @param searchChar the character to find. 4852 * @return the last index of the search character, -1 if no match or {@code null} string input. 4853 * @since 2.0 4854 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 4855 * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String} 4856 */ 4857 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 4858 if (isEmpty(seq)) { 4859 return INDEX_NOT_FOUND; 4860 } 4861 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 4862 } 4863 4864 /** 4865 * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of 4866 * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that: 4867 * 4868 * <pre> 4869 * (this.charAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4870 * </pre> 4871 * 4872 * <p> 4873 * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that: 4874 * </p> 4875 * 4876 * <pre> 4877 * (this.codePointAt(<em>k</em>) == searchChar) && (<em>k</em> <= startPos) 4878 * </pre> 4879 * 4880 * <p> 4881 * 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 4882 * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The 4883 * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored. 4884 * </p> 4885 * 4886 * <p> 4887 * All indices are specified in {@code char} values (Unicode code units). 4888 * </p> 4889 * 4890 * <pre> 4891 * StringUtils.lastIndexOf(null, *, *) = -1 4892 * StringUtils.lastIndexOf("", *, *) = -1 4893 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 4894 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 4895 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 4896 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 4897 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 4898 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 4899 * </pre> 4900 * 4901 * @param seq the CharSequence to check, may be null. 4902 * @param searchChar the character to find. 4903 * @param startPos the start position. 4904 * @return the last index of the search character (always ≤ startPos), -1 if no match or {@code null} string input. 4905 * @since 2.0 4906 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 4907 */ 4908 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 4909 if (isEmpty(seq)) { 4910 return INDEX_NOT_FOUND; 4911 } 4912 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 4913 } 4914 4915 /** 4916 * Finds the latest index of any substring in a set of potential substrings. 4917 * 4918 * <p> 4919 * 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 4920 * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses 4921 * {@link String#indexOf(String)} if possible 4922 * </p> 4923 * 4924 * <pre> 4925 * StringUtils.lastIndexOfAny(null, *) = -1 4926 * StringUtils.lastIndexOfAny(*, null) = -1 4927 * StringUtils.lastIndexOfAny(*, []) = -1 4928 * StringUtils.lastIndexOfAny(*, [null]) = -1 4929 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6 4930 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6 4931 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4932 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1 4933 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""]) = 10 4934 * </pre> 4935 * 4936 * @param str the CharSequence to check, may be null. 4937 * @param searchStrs the CharSequences to search for, may be null. 4938 * @return the last index of any of the CharSequences, -1 if no match. 4939 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 4940 */ 4941 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 4942 if (str == null || searchStrs == null) { 4943 return INDEX_NOT_FOUND; 4944 } 4945 int ret = INDEX_NOT_FOUND; 4946 int tmp; 4947 for (final CharSequence search : searchStrs) { 4948 if (search == null) { 4949 continue; 4950 } 4951 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 4952 if (tmp > ret) { 4953 ret = tmp; 4954 } 4955 } 4956 return ret; 4957 } 4958 4959 /** 4960 * Case in-sensitive find of the last index within a CharSequence. 4961 * 4962 * <p> 4963 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4964 * the start position is negative. A start position greater than the string length searches the whole string. 4965 * </p> 4966 * 4967 * <pre> 4968 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 4969 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 4970 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 4971 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 4972 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 4973 * </pre> 4974 * 4975 * @param str the CharSequence to check, may be null. 4976 * @param searchStr the CharSequence to find, may be null. 4977 * @return the first index of the search CharSequence, -1 if no match or {@code null} string input. 4978 * @since 2.5 4979 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 4980 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}. 4981 */ 4982 @Deprecated 4983 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 4984 return Strings.CI.lastIndexOf(str, searchStr); 4985 } 4986 4987 /** 4988 * Case in-sensitive find of the last index within a CharSequence from the specified position. 4989 * 4990 * <p> 4991 * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless 4992 * 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 4993 * backwards; matches starting after the start position are ignored. 4994 * </p> 4995 * 4996 * <pre> 4997 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 4998 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 4999 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 5000 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 5001 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 5002 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 5003 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 5004 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 5005 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 5006 * </pre> 5007 * 5008 * @param str the CharSequence to check, may be null. 5009 * @param searchStr the CharSequence to find, may be null. 5010 * @param startPos the start position. 5011 * @return the last index of the search CharSequence (always ≤ startPos), -1 if no match or {@code null} input. 5012 * @since 2.5 5013 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 5014 * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}. 5015 */ 5016 @Deprecated 5017 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) { 5018 return Strings.CI.lastIndexOf(str, searchStr, startPos); 5019 } 5020 5021 /** 5022 * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}. 5023 * 5024 * <p> 5025 * A {@code null} String will return {@code -1}. 5026 * </p> 5027 * 5028 * <pre> 5029 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 5030 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 5031 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 5032 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 5033 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 5034 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 5035 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 5036 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 5037 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 5038 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 5039 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 5040 * </pre> 5041 * 5042 * <p> 5043 * Note that 'tail(CharSequence str, int n)' may be implemented as: 5044 * </p> 5045 * 5046 * <pre> 5047 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 5048 * </pre> 5049 * 5050 * @param str the CharSequence to check, may be null. 5051 * @param searchStr the CharSequence to find, may be null. 5052 * @param ordinal the n-th last {@code searchStr} to find. 5053 * @return the n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5054 * @since 2.5 5055 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 5056 */ 5057 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5058 return ordinalIndexOf(str, searchStr, ordinal, true); 5059 } 5060 5061 /** 5062 * Gets the leftmost {@code len} characters of a String. 5063 * 5064 * <p> 5065 * 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 5066 * if len is negative. 5067 * </p> 5068 * 5069 * <pre> 5070 * StringUtils.left(null, *) = null 5071 * StringUtils.left(*, -ve) = "" 5072 * StringUtils.left("", *) = "" 5073 * StringUtils.left("abc", 0) = "" 5074 * StringUtils.left("abc", 2) = "ab" 5075 * StringUtils.left("abc", 4) = "abc" 5076 * </pre> 5077 * 5078 * @param str the String to get the leftmost characters from, may be null. 5079 * @param len the length of the required String. 5080 * @return the leftmost characters, {@code null} if null String input. 5081 */ 5082 public static String left(final String str, final int len) { 5083 if (str == null) { 5084 return null; 5085 } 5086 if (len < 0) { 5087 return EMPTY; 5088 } 5089 if (str.length() <= len) { 5090 return str; 5091 } 5092 return str.substring(0, len); 5093 } 5094 5095 /** 5096 * Left pad a String with spaces (' '). 5097 * 5098 * <p> 5099 * The String is padded to the size of {@code size}. 5100 * </p> 5101 * 5102 * <pre> 5103 * StringUtils.leftPad(null, *) = null 5104 * StringUtils.leftPad("", 3) = " " 5105 * StringUtils.leftPad("bat", 3) = "bat" 5106 * StringUtils.leftPad("bat", 5) = " bat" 5107 * StringUtils.leftPad("bat", 1) = "bat" 5108 * StringUtils.leftPad("bat", -1) = "bat" 5109 * </pre> 5110 * 5111 * @param str the String to pad out, may be null. 5112 * @param size the size to pad to. 5113 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5114 */ 5115 public static String leftPad(final String str, final int size) { 5116 return leftPad(str, size, ' '); 5117 } 5118 5119 /** 5120 * Left pad a String with a specified character. 5121 * 5122 * <p> 5123 * Pad to a size of {@code size}. 5124 * </p> 5125 * 5126 * <pre> 5127 * StringUtils.leftPad(null, *, *) = null 5128 * StringUtils.leftPad("", 3, 'z') = "zzz" 5129 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5130 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5131 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5132 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5133 * </pre> 5134 * 5135 * @param str the String to pad out, may be null. 5136 * @param size the size to pad to. 5137 * @param padChar the character to pad with. 5138 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5139 * @since 2.0 5140 */ 5141 public static String leftPad(final String str, final int size, final char padChar) { 5142 if (str == null) { 5143 return null; 5144 } 5145 final int pads = size - str.length(); 5146 if (pads <= 0) { 5147 return str; // returns original String when possible 5148 } 5149 if (pads > PAD_LIMIT) { 5150 return leftPad(str, size, String.valueOf(padChar)); 5151 } 5152 return repeat(padChar, pads).concat(str); 5153 } 5154 5155 /** 5156 * Left pad a String with a specified String. 5157 * 5158 * <p> 5159 * Pad to a size of {@code size}. 5160 * </p> 5161 * 5162 * <pre> 5163 * StringUtils.leftPad(null, *, *) = null 5164 * StringUtils.leftPad("", 3, "z") = "zzz" 5165 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5166 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5167 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5168 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5169 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5170 * StringUtils.leftPad("bat", 5, null) = " bat" 5171 * StringUtils.leftPad("bat", 5, "") = " bat" 5172 * </pre> 5173 * 5174 * @param str the String to pad out, may be null. 5175 * @param size the size to pad to. 5176 * @param padStr the String to pad with, null or empty treated as single space. 5177 * @return left padded String or original String if no padding is necessary, {@code null} if null String input. 5178 */ 5179 public static String leftPad(final String str, final int size, String padStr) { 5180 if (str == null) { 5181 return null; 5182 } 5183 if (isEmpty(padStr)) { 5184 padStr = SPACE; 5185 } 5186 final int padLen = padStr.length(); 5187 final int strLen = str.length(); 5188 final int pads = size - strLen; 5189 if (pads <= 0) { 5190 return str; // returns original String when possible 5191 } 5192 if (padLen == 1 && pads <= PAD_LIMIT) { 5193 return leftPad(str, size, padStr.charAt(0)); 5194 } 5195 if (pads == padLen) { 5196 return padStr.concat(str); 5197 } 5198 if (pads < padLen) { 5199 return padStr.substring(0, pads).concat(str); 5200 } 5201 final char[] padding = new char[pads]; 5202 final char[] padChars = padStr.toCharArray(); 5203 for (int i = 0; i < pads; i++) { 5204 padding[i] = padChars[i % padLen]; 5205 } 5206 return new String(padding).concat(str); 5207 } 5208 5209 /** 5210 * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}. 5211 * 5212 * @param cs a CharSequence or {@code null}. 5213 * @return CharSequence length or {@code 0} if the CharSequence is {@code null}. 5214 * @since 2.4 5215 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5216 */ 5217 public static int length(final CharSequence cs) { 5218 return cs == null ? 0 : cs.length(); 5219 } 5220 5221 /** 5222 * Converts a String to lower case as per {@link String#toLowerCase()}. 5223 * 5224 * <p> 5225 * A {@code null} input String returns {@code null}. 5226 * </p> 5227 * 5228 * <pre> 5229 * StringUtils.lowerCase(null) = null 5230 * StringUtils.lowerCase("") = "" 5231 * StringUtils.lowerCase("aBc") = "abc" 5232 * </pre> 5233 * 5234 * <p> 5235 * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale. 5236 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g. 5237 * {@link Locale#ENGLISH}). 5238 * </p> 5239 * 5240 * @param str the String to lower case, may be null. 5241 * @return the lower cased String, {@code null} if null String input. 5242 */ 5243 public static String lowerCase(final String str) { 5244 if (str == null) { 5245 return null; 5246 } 5247 return str.toLowerCase(); 5248 } 5249 5250 /** 5251 * Converts a String to lower case as per {@link String#toLowerCase(Locale)}. 5252 * 5253 * <p> 5254 * A {@code null} input String returns {@code null}. 5255 * </p> 5256 * 5257 * <pre> 5258 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5259 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5260 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5261 * </pre> 5262 * 5263 * @param str the String to lower case, may be null. 5264 * @param locale the locale that defines the case transformation rules, must not be null. 5265 * @return the lower cased String, {@code null} if null String input. 5266 * @since 2.5 5267 */ 5268 public static String lowerCase(final String str, final Locale locale) { 5269 if (str == null) { 5270 return null; 5271 } 5272 return str.toLowerCase(LocaleUtils.toLocale(locale)); 5273 } 5274 5275 private static int[] matches(final CharSequence first, final CharSequence second) { 5276 final CharSequence max; 5277 final CharSequence min; 5278 if (first.length() > second.length()) { 5279 max = first; 5280 min = second; 5281 } else { 5282 max = second; 5283 min = first; 5284 } 5285 final int range = Math.max(max.length() / 2 - 1, 0); 5286 final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1); 5287 final boolean[] matchFlags = new boolean[max.length()]; 5288 int matches = 0; 5289 for (int mi = 0; mi < min.length(); mi++) { 5290 final char c1 = min.charAt(mi); 5291 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) { 5292 if (!matchFlags[xi] && c1 == max.charAt(xi)) { 5293 matchIndexes[mi] = xi; 5294 matchFlags[xi] = true; 5295 matches++; 5296 break; 5297 } 5298 } 5299 } 5300 final char[] ms1 = new char[matches]; 5301 final char[] ms2 = new char[matches]; 5302 for (int i = 0, si = 0; i < min.length(); i++) { 5303 if (matchIndexes[i] != -1) { 5304 ms1[si] = min.charAt(i); 5305 si++; 5306 } 5307 } 5308 for (int i = 0, si = 0; i < max.length(); i++) { 5309 if (matchFlags[i]) { 5310 ms2[si] = max.charAt(i); 5311 si++; 5312 } 5313 } 5314 int transpositions = 0; 5315 for (int mi = 0; mi < ms1.length; mi++) { 5316 if (ms1[mi] != ms2[mi]) { 5317 transpositions++; 5318 } 5319 } 5320 int prefix = 0; 5321 for (int mi = 0; mi < min.length(); mi++) { 5322 if (first.charAt(mi) != second.charAt(mi)) { 5323 break; 5324 } 5325 prefix++; 5326 } 5327 return new int[] { matches, transpositions / 2, prefix, max.length() }; 5328 } 5329 5330 /** 5331 * Gets {@code len} characters from the middle of a String. 5332 * 5333 * <p> 5334 * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null}, 5335 * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}. 5336 * </p> 5337 * 5338 * <pre> 5339 * StringUtils.mid(null, *, *) = null 5340 * StringUtils.mid(*, *, -ve) = "" 5341 * StringUtils.mid("", 0, *) = "" 5342 * StringUtils.mid("abc", 0, 2) = "ab" 5343 * StringUtils.mid("abc", 0, 4) = "abc" 5344 * StringUtils.mid("abc", 2, 4) = "c" 5345 * StringUtils.mid("abc", 4, 2) = "" 5346 * StringUtils.mid("abc", -2, 2) = "ab" 5347 * </pre> 5348 * 5349 * @param str the String to get the characters from, may be null. 5350 * @param pos the position to start from, negative treated as zero. 5351 * @param len the length of the required String. 5352 * @return the middle characters, {@code null} if null String input. 5353 */ 5354 public static String mid(final String str, int pos, final int len) { 5355 if (str == null) { 5356 return null; 5357 } 5358 if (len < 0 || pos > str.length()) { 5359 return EMPTY; 5360 } 5361 if (pos < 0) { 5362 pos = 0; 5363 } 5364 if (str.length() <= pos + len) { 5365 return str.substring(pos); 5366 } 5367 return str.substring(pos, pos + len); 5368 } 5369 5370 /** 5371 * Similar to <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize -space</a> 5372 * 5373 * <p> 5374 * This function returns the argument string with whitespace normalized by using {@code {@link #trim(String)}} to remove leading and trailing whitespace and 5375 * then replacing sequences of whitespace characters by a single space. 5376 * </p> 5377 * 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 | 5378 * #x9 | #xD | #xA)+ 5379 * <p> 5380 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 5381 * </p> 5382 * <p> 5383 * For reference: 5384 * </p> 5385 * <ul> 5386 * <li>\x0B = vertical tab</li> 5387 * <li>\f = #xC = form feed</li> 5388 * <li>#x20 = space</li> 5389 * <li>#x9 = \t</li> 5390 * <li>#xA = \n</li> 5391 * <li>#xD = \r</li> 5392 * </ul> 5393 * 5394 * <p> 5395 * The difference is that Java's whitespace includes vertical tab and form feed, which this function will also normalize. Additionally {@code {@link 5396 * #trim(String)}} removes control characters (char <= 32) from both ends of this String. 5397 * </p> 5398 * 5399 * @param str the source String to normalize whitespaces from, may be null. 5400 * @return the modified string with whitespace normalized, {@code null} if null String input. 5401 * @see Pattern 5402 * @see #trim(String) 5403 * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a> 5404 * @since 3.0 5405 */ 5406 public static String normalizeSpace(final String str) { 5407 // LANG-1020: Improved performance significantly by normalizing manually instead of using regex 5408 // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test 5409 if (isEmpty(str)) { 5410 return str; 5411 } 5412 final int size = str.length(); 5413 final char[] newChars = new char[size]; 5414 int count = 0; 5415 int whitespacesCount = 0; 5416 boolean startWhitespaces = true; 5417 for (int i = 0; i < size; i++) { 5418 final char actualChar = str.charAt(i); 5419 final boolean isWhitespace = Character.isWhitespace(actualChar); 5420 if (isWhitespace) { 5421 if (whitespacesCount == 0 && !startWhitespaces) { 5422 newChars[count++] = SPACE.charAt(0); 5423 } 5424 whitespacesCount++; 5425 } else { 5426 startWhitespaces = false; 5427 newChars[count++] = actualChar == 160 ? 32 : actualChar; 5428 whitespacesCount = 0; 5429 } 5430 } 5431 if (startWhitespaces) { 5432 return EMPTY; 5433 } 5434 return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); 5435 } 5436 5437 /** 5438 * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5439 * <p> 5440 * <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 5441 * (unless {@code searchStr} is an empty string, in which case the position is never incremented and {@code 0} is returned immediately). This means that 5442 * matches may overlap. 5443 * </p> 5444 * <p> 5445 * A {@code null} CharSequence will return {@code -1}. 5446 * </p> 5447 * 5448 * <pre> 5449 * StringUtils.ordinalIndexOf(null, *, *) = -1 5450 * StringUtils.ordinalIndexOf(*, null, *) = -1 5451 * StringUtils.ordinalIndexOf("", "", *) = 0 5452 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 5453 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 5454 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 5455 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 5456 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 5457 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 5458 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 5459 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 5460 * </pre> 5461 * 5462 * <p> 5463 * Matches may overlap: 5464 * </p> 5465 * 5466 * <pre> 5467 * StringUtils.ordinalIndexOf("ababab", "aba", 1) = 0 5468 * StringUtils.ordinalIndexOf("ababab", "aba", 2) = 2 5469 * StringUtils.ordinalIndexOf("ababab", "aba", 3) = -1 5470 * 5471 * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0 5472 * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2 5473 * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4 5474 * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1 5475 * </pre> 5476 * 5477 * <p> 5478 * Note that 'head(CharSequence str, int n)' may be implemented as: 5479 * </p> 5480 * 5481 * <pre> 5482 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 5483 * </pre> 5484 * 5485 * @param str the CharSequence to check, may be null. 5486 * @param searchStr the CharSequence to find, may be null. 5487 * @param ordinal the n-th {@code searchStr} to find. 5488 * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5489 * @since 2.1 5490 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 5491 */ 5492 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 5493 return ordinalIndexOf(str, searchStr, ordinal, false); 5494 } 5495 5496 /** 5497 * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible. 5498 * <p> 5499 * Note that matches may overlap. 5500 * <p> 5501 * 5502 * <p> 5503 * A {@code null} CharSequence will return {@code -1}. 5504 * </p> 5505 * 5506 * @param str the CharSequence to check, may be null. 5507 * @param searchStr the CharSequence to find, may be null. 5508 * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed. 5509 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf(). 5510 * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input. 5511 */ 5512 // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int) 5513 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 5514 if (str == null || searchStr == null || ordinal <= 0) { 5515 return INDEX_NOT_FOUND; 5516 } 5517 if (searchStr.length() == 0) { 5518 return lastIndex ? str.length() : 0; 5519 } 5520 int found = 0; 5521 // set the initial index beyond the end of the string 5522 // this is to allow for the initial index decrement/increment 5523 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 5524 do { 5525 if (lastIndex) { 5526 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string 5527 } else { 5528 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string 5529 } 5530 if (index < 0) { 5531 return index; 5532 } 5533 found++; 5534 } while (found < ordinal); 5535 return index; 5536 } 5537 5538 /** 5539 * Overlays part of a String with another String. 5540 * 5541 * <p> 5542 * 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 5543 * length. The start index is always the smaller of the two indices. 5544 * </p> 5545 * 5546 * <pre> 5547 * StringUtils.overlay(null, *, *, *) = null 5548 * StringUtils.overlay("", "abc", 0, 0) = "abc" 5549 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 5550 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 5551 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 5552 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 5553 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 5554 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 5555 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 5556 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 5557 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 5558 * </pre> 5559 * 5560 * @param str the String to do overlaying in, may be null. 5561 * @param overlay the String to overlay, may be null. 5562 * @param start the position to start overlaying at. 5563 * @param end the position to stop overlaying before. 5564 * @return overlayed String, {@code null} if null String input. 5565 * @since 2.0 5566 */ 5567 public static String overlay(final String str, String overlay, int start, int end) { 5568 if (str == null) { 5569 return null; 5570 } 5571 if (overlay == null) { 5572 overlay = EMPTY; 5573 } 5574 final int len = str.length(); 5575 if (start < 0) { 5576 start = 0; 5577 } 5578 if (start > len) { 5579 start = len; 5580 } 5581 if (end < 0) { 5582 end = 0; 5583 } 5584 if (end > len) { 5585 end = len; 5586 } 5587 if (start > end) { 5588 final int temp = start; 5589 start = end; 5590 end = temp; 5591 } 5592 return str.substring(0, start) + overlay + str.substring(end); 5593 } 5594 5595 /** 5596 * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes. 5597 * 5598 * <pre> 5599 * StringUtils.prependIfMissing(null, null) = null 5600 * StringUtils.prependIfMissing("abc", null) = "abc" 5601 * StringUtils.prependIfMissing("", "xyz") = "xyz" 5602 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 5603 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 5604 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 5605 * </pre> 5606 * <p> 5607 * With additional prefixes, 5608 * </p> 5609 * 5610 * <pre> 5611 * StringUtils.prependIfMissing(null, null, null) = null 5612 * StringUtils.prependIfMissing("abc", null, null) = "abc" 5613 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 5614 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5615 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 5616 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 5617 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 5618 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 5619 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 5620 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 5621 * </pre> 5622 * 5623 * @param str The string. 5624 * @param prefix The prefix to prepend to the start of the string. 5625 * @param prefixes Additional prefixes that are valid. 5626 * @return A new String if prefix was prepended, the same string otherwise. 5627 * @since 3.2 5628 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence, 5629 * CharSequence...)}. 5630 */ 5631 @Deprecated 5632 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5633 return Strings.CS.prependIfMissing(str, prefix, prefixes); 5634 } 5635 5636 /** 5637 * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes. 5638 * 5639 * <pre> 5640 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 5641 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 5642 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 5643 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 5644 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 5645 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 5646 * </pre> 5647 * <p> 5648 * With additional prefixes, 5649 * </p> 5650 * 5651 * <pre> 5652 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 5653 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 5654 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 5655 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 5656 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 5657 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 5658 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 5659 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 5660 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 5661 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 5662 * </pre> 5663 * 5664 * @param str The string. 5665 * @param prefix The prefix to prepend to the start of the string. 5666 * @param prefixes Additional prefixes that are valid (optional). 5667 * @return A new String if prefix was prepended, the same string otherwise. 5668 * @since 3.2 5669 * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence, 5670 * CharSequence...)}. 5671 */ 5672 @Deprecated 5673 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 5674 return Strings.CI.prependIfMissing(str, prefix, prefixes); 5675 } 5676 5677 /** 5678 * Removes all occurrences of a character from within the source string. 5679 * 5680 * <p> 5681 * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. 5682 * </p> 5683 * 5684 * <pre> 5685 * StringUtils.remove(null, *) = null 5686 * StringUtils.remove("", *) = "" 5687 * StringUtils.remove("queued", 'u') = "qeed" 5688 * StringUtils.remove("queued", 'z') = "queued" 5689 * </pre> 5690 * 5691 * @param str the source String to search, may be null. 5692 * @param remove the char to search for and remove, may be null. 5693 * @return the substring with the char removed if found, {@code null} if null String input. 5694 * @since 2.1 5695 */ 5696 public static String remove(final String str, final char remove) { 5697 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 5698 return str; 5699 } 5700 final char[] chars = str.toCharArray(); 5701 int pos = 0; 5702 for (int i = 0; i < chars.length; i++) { 5703 if (chars[i] != remove) { 5704 chars[pos++] = chars[i]; 5705 } 5706 } 5707 return new String(chars, 0, pos); 5708 } 5709 5710 /** 5711 * Removes all occurrences of a substring from within the source string. 5712 * 5713 * <p> 5714 * 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 5715 * the source string. An empty ("") remove string will return the source string. 5716 * </p> 5717 * 5718 * <pre> 5719 * StringUtils.remove(null, *) = null 5720 * StringUtils.remove("", *) = "" 5721 * StringUtils.remove(*, null) = * 5722 * StringUtils.remove(*, "") = * 5723 * StringUtils.remove("queued", "ue") = "qd" 5724 * StringUtils.remove("queued", "zz") = "queued" 5725 * </pre> 5726 * 5727 * @param str the source String to search, may be null. 5728 * @param remove the String to search for and remove, may be null. 5729 * @return the substring with the string removed if found, {@code null} if null String input. 5730 * @since 2.1 5731 * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}. 5732 */ 5733 @Deprecated 5734 public static String remove(final String str, final String remove) { 5735 return Strings.CS.remove(str, remove); 5736 } 5737 5738 /** 5739 * Removes each substring of the text String that matches the given regular expression. 5740 * 5741 * This method is a {@code null} safe equivalent to: 5742 * <ul> 5743 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 5744 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 5745 * </ul> 5746 * 5747 * <p> 5748 * A {@code null} reference passed to this method is a no-op. 5749 * </p> 5750 * 5751 * <p> 5752 * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option 5753 * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 5754 * </p> 5755 * 5756 * <pre>{@code 5757 * StringUtils.removeAll(null, *) = null 5758 * StringUtils.removeAll("any", (String) null) = "any" 5759 * StringUtils.removeAll("any", "") = "any" 5760 * StringUtils.removeAll("any", ".*") = "" 5761 * StringUtils.removeAll("any", ".+") = "" 5762 * StringUtils.removeAll("abc", ".?") = "" 5763 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 5764 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 5765 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 5766 * }</pre> 5767 * 5768 * @param text text to remove from, may be null. 5769 * @param regex the regular expression to which this string is to be matched. 5770 * @return the text with any removes processed, {@code null} if null String input. 5771 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 5772 * @see #replaceAll(String, String, String) 5773 * @see #removePattern(String, String) 5774 * @see String#replaceAll(String, String) 5775 * @see java.util.regex.Pattern 5776 * @see java.util.regex.Pattern#DOTALL 5777 * @since 3.5 5778 * @deprecated Use {@link RegExUtils#removeAll(String, String)}. 5779 */ 5780 @Deprecated 5781 public static String removeAll(final String text, final String regex) { 5782 return RegExUtils.removeAll(text, regex); 5783 } 5784 5785 /** 5786 * Removes a substring only if it is at the end of a source string, otherwise returns the source string. 5787 * 5788 * <p> 5789 * 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 5790 * the source string. 5791 * </p> 5792 * 5793 * <pre> 5794 * StringUtils.removeEnd(null, *) = null 5795 * StringUtils.removeEnd("", *) = "" 5796 * StringUtils.removeEnd(*, null) = * 5797 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 5798 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 5799 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 5800 * StringUtils.removeEnd("abc", "") = "abc" 5801 * </pre> 5802 * 5803 * @param str the source String to search, may be null. 5804 * @param remove the String to search for and remove, may be null. 5805 * @return the substring with the string removed if found, {@code null} if null String input. 5806 * @since 2.1 5807 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}. 5808 */ 5809 @Deprecated 5810 public static String removeEnd(final String str, final String remove) { 5811 return Strings.CS.removeEnd(str, remove); 5812 } 5813 5814 /** 5815 * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string. 5816 * 5817 * <p> 5818 * 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 5819 * the source string. 5820 * </p> 5821 * 5822 * <pre> 5823 * StringUtils.removeEndIgnoreCase(null, *) = null 5824 * StringUtils.removeEndIgnoreCase("", *) = "" 5825 * StringUtils.removeEndIgnoreCase(*, null) = * 5826 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 5827 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 5828 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 5829 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 5830 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain" 5831 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain" 5832 * </pre> 5833 * 5834 * @param str the source String to search, may be null. 5835 * @param remove the String to search for (case-insensitive) and remove, may be null. 5836 * @return the substring with the string removed if found, {@code null} if null String input. 5837 * @since 2.4 5838 * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}. 5839 */ 5840 @Deprecated 5841 public static String removeEndIgnoreCase(final String str, final String remove) { 5842 return Strings.CI.removeEnd(str, remove); 5843 } 5844 5845 /** 5846 * Removes the first 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.replaceFirst(regex, StringUtils.EMPTY)}</li> 5851 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(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 * 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 5860 * single-line mode in Perl. 5861 * </p> 5862 * 5863 * <pre>{@code 5864 * StringUtils.removeFirst(null, *) = null 5865 * StringUtils.removeFirst("any", (String) null) = "any" 5866 * StringUtils.removeFirst("any", "") = "any" 5867 * StringUtils.removeFirst("any", ".*") = "" 5868 * StringUtils.removeFirst("any", ".+") = "" 5869 * StringUtils.removeFirst("abc", ".?") = "bc" 5870 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 5871 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 5872 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 5873 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 5874 * }</pre> 5875 * 5876 * @param text text to remove from, may be null. 5877 * @param regex the regular expression to which this string is to be matched. 5878 * @return the text with the first replacement processed, {@code null} if null String input. 5879 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 5880 * @see #replaceFirst(String, String, String) 5881 * @see String#replaceFirst(String, String) 5882 * @see java.util.regex.Pattern 5883 * @see java.util.regex.Pattern#DOTALL 5884 * @since 3.5 5885 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String) RegExUtils.replaceFirst(String, String, EMPTY)}. 5886 */ 5887 @Deprecated 5888 public static String removeFirst(final String text, final String regex) { 5889 return replaceFirst(text, regex, EMPTY); 5890 } 5891 5892 /** 5893 * Case-insensitive removal of all occurrences of a substring from within 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} remove string will return 5897 * the source string. An empty ("") remove string will return the source string. 5898 * </p> 5899 * 5900 * <pre> 5901 * StringUtils.removeIgnoreCase(null, *) = null 5902 * StringUtils.removeIgnoreCase("", *) = "" 5903 * StringUtils.removeIgnoreCase(*, null) = * 5904 * StringUtils.removeIgnoreCase(*, "") = * 5905 * StringUtils.removeIgnoreCase("queued", "ue") = "qd" 5906 * StringUtils.removeIgnoreCase("queued", "zz") = "queued" 5907 * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd" 5908 * StringUtils.removeIgnoreCase("queued", "zZ") = "queued" 5909 * </pre> 5910 * 5911 * @param str the source String to search, may be null. 5912 * @param remove the String to search for (case-insensitive) and remove, may be null. 5913 * @return the substring with the string removed if found, {@code null} if null String input. 5914 * @since 3.5 5915 * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}. 5916 */ 5917 @Deprecated 5918 public static String removeIgnoreCase(final String str, final String remove) { 5919 return Strings.CI.remove(str, remove); 5920 } 5921 5922 /** 5923 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 5924 * 5925 * This call is a {@code null} safe equivalent to: 5926 * <ul> 5927 * <li>{@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 5928 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li> 5929 * </ul> 5930 * 5931 * <p> 5932 * A {@code null} reference passed to this method is a no-op. 5933 * </p> 5934 * 5935 * <pre>{@code 5936 * StringUtils.removePattern(null, *) = null 5937 * StringUtils.removePattern("any", (String) null) = "any" 5938 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 5939 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 5940 * }</pre> 5941 * 5942 * @param source the source string. 5943 * @param regex the regular expression to which this string is to be matched. 5944 * @return The resulting {@link String}. 5945 * @see #replacePattern(String, String, String) 5946 * @see String#replaceAll(String, String) 5947 * @see Pattern#DOTALL 5948 * @since 3.2 5949 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 5950 * @deprecated Use {@link RegExUtils#removePattern(CharSequence, String)}. 5951 */ 5952 @Deprecated 5953 public static String removePattern(final String source, final String regex) { 5954 return RegExUtils.removePattern(source, regex); 5955 } 5956 5957 /** 5958 * Removes a char only if it is at the beginning of a source string, otherwise returns the source string. 5959 * 5960 * <p> 5961 * 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 5962 * the source string. 5963 * </p> 5964 * 5965 * <pre> 5966 * StringUtils.removeStart(null, *) = null 5967 * StringUtils.removeStart("", *) = "" 5968 * StringUtils.removeStart(*, null) = * 5969 * StringUtils.removeStart("/path", '/') = "path" 5970 * StringUtils.removeStart("path", '/') = "path" 5971 * StringUtils.removeStart("path", 0) = "path" 5972 * </pre> 5973 * 5974 * @param str the source String to search, may be null. 5975 * @param remove the char to search for and remove. 5976 * @return the substring with the char removed if found, {@code null} if null String input. 5977 * @since 3.13.0 5978 */ 5979 public static String removeStart(final String str, final char remove) { 5980 if (isEmpty(str)) { 5981 return str; 5982 } 5983 return str.charAt(0) == remove ? str.substring(1) : str; 5984 } 5985 5986 /** 5987 * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string. 5988 * 5989 * <p> 5990 * 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 5991 * the source string. 5992 * </p> 5993 * 5994 * <pre> 5995 * StringUtils.removeStart(null, *) = null 5996 * StringUtils.removeStart("", *) = "" 5997 * StringUtils.removeStart(*, null) = * 5998 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 5999 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 6000 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 6001 * StringUtils.removeStart("abc", "") = "abc" 6002 * </pre> 6003 * 6004 * @param str the source String to search, may be null. 6005 * @param remove the String to search for and remove, may be null. 6006 * @return the substring with the string removed if found, {@code null} if null String input. 6007 * @since 2.1 6008 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}. 6009 */ 6010 @Deprecated 6011 public static String removeStart(final String str, final String remove) { 6012 return Strings.CS.removeStart(str, remove); 6013 } 6014 6015 /** 6016 * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string. 6017 * 6018 * <p> 6019 * 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 6020 * the source string. 6021 * </p> 6022 * 6023 * <pre> 6024 * StringUtils.removeStartIgnoreCase(null, *) = null 6025 * StringUtils.removeStartIgnoreCase("", *) = "" 6026 * StringUtils.removeStartIgnoreCase(*, null) = * 6027 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 6028 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 6029 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 6030 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 6031 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 6032 * </pre> 6033 * 6034 * @param str the source String to search, may be null. 6035 * @param remove the String to search for (case-insensitive) and remove, may be null. 6036 * @return the substring with the string removed if found, {@code null} if null String input. 6037 * @since 2.4 6038 * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}. 6039 */ 6040 @Deprecated 6041 public static String removeStartIgnoreCase(final String str, final String remove) { 6042 return Strings.CI.removeStart(str, remove); 6043 } 6044 6045 /** 6046 * Returns padding using the specified delimiter repeated to a given length. 6047 * 6048 * <pre> 6049 * StringUtils.repeat('e', 0) = "" 6050 * StringUtils.repeat('e', 3) = "eee" 6051 * StringUtils.repeat('e', -2) = "" 6052 * </pre> 6053 * 6054 * <p> 6055 * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 6056 * 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 6057 * {@link #repeat(String, int)} instead. 6058 * </p> 6059 * 6060 * @param repeat character to repeat. 6061 * @param count number of times to repeat char, negative treated as zero. 6062 * @return String with repeated character. 6063 * @see #repeat(String, int) 6064 */ 6065 public static String repeat(final char repeat, final int count) { 6066 if (count <= 0) { 6067 return EMPTY; 6068 } 6069 return new String(ArrayFill.fill(new char[count], repeat)); 6070 } 6071 6072 /** 6073 * Repeats a String {@code repeat} times to form a new String. 6074 * 6075 * <pre> 6076 * StringUtils.repeat(null, 2) = null 6077 * StringUtils.repeat("", 0) = "" 6078 * StringUtils.repeat("", 2) = "" 6079 * StringUtils.repeat("a", 3) = "aaa" 6080 * StringUtils.repeat("ab", 2) = "abab" 6081 * StringUtils.repeat("a", -2) = "" 6082 * </pre> 6083 * 6084 * @param repeat the String to repeat, may be null. 6085 * @param count number of times to repeat str, negative treated as zero. 6086 * @return a new String consisting of the original String repeated, {@code null} if null String input. 6087 */ 6088 public static String repeat(final String repeat, final int count) { 6089 // Performance tuned for 2.0 (JDK1.4) 6090 if (repeat == null) { 6091 return null; 6092 } 6093 if (count <= 0) { 6094 return EMPTY; 6095 } 6096 final int inputLength = repeat.length(); 6097 if (count == 1 || inputLength == 0) { 6098 return repeat; 6099 } 6100 if (inputLength == 1 && count <= PAD_LIMIT) { 6101 return repeat(repeat.charAt(0), count); 6102 } 6103 final int outputLength = inputLength * count; 6104 switch (inputLength) { 6105 case 1: 6106 return repeat(repeat.charAt(0), count); 6107 case 2: 6108 final char ch0 = repeat.charAt(0); 6109 final char ch1 = repeat.charAt(1); 6110 final char[] output2 = new char[outputLength]; 6111 for (int i = count * 2 - 2; i >= 0; i--, i--) { 6112 output2[i] = ch0; 6113 output2[i + 1] = ch1; 6114 } 6115 return new String(output2); 6116 default: 6117 final StringBuilder buf = new StringBuilder(outputLength); 6118 for (int i = 0; i < count; i++) { 6119 buf.append(repeat); 6120 } 6121 return buf.toString(); 6122 } 6123 } 6124 6125 /** 6126 * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time. 6127 * 6128 * <pre> 6129 * StringUtils.repeat(null, null, 2) = null 6130 * StringUtils.repeat(null, "x", 2) = null 6131 * StringUtils.repeat("", null, 0) = "" 6132 * StringUtils.repeat("", "", 2) = "" 6133 * StringUtils.repeat("", "x", 3) = "xx" 6134 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 6135 * </pre> 6136 * 6137 * @param repeat the String to repeat, may be null. 6138 * @param separator the String to inject, may be null. 6139 * @param count number of times to repeat str, negative treated as zero. 6140 * @return a new String consisting of the original String repeated, {@code null} if null String input. 6141 * @since 2.5 6142 */ 6143 public static String repeat(final String repeat, final String separator, final int count) { 6144 if (repeat == null || separator == null) { 6145 return repeat(repeat, count); 6146 } 6147 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 6148 final String result = repeat(repeat + separator, count); 6149 return Strings.CS.removeEnd(result, separator); 6150 } 6151 6152 /** 6153 * Replaces all occurrences of a String within another String. 6154 * 6155 * <p> 6156 * A {@code null} reference passed to this method is a no-op. 6157 * </p> 6158 * 6159 * <pre> 6160 * StringUtils.replace(null, *, *) = null 6161 * StringUtils.replace("", *, *) = "" 6162 * StringUtils.replace("any", null, *) = "any" 6163 * StringUtils.replace("any", *, null) = "any" 6164 * StringUtils.replace("any", "", *) = "any" 6165 * StringUtils.replace("aba", "a", null) = "aba" 6166 * StringUtils.replace("aba", "a", "") = "b" 6167 * StringUtils.replace("aba", "a", "z") = "zbz" 6168 * </pre> 6169 * 6170 * @param text text to search and replace in, may be null. 6171 * @param searchString the String to search for, may be null. 6172 * @param replacement the String to replace it with, may be null. 6173 * @return the text with any replacements processed, {@code null} if null String input. 6174 * @see #replace(String text, String searchString, String replacement, int max) 6175 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}. 6176 */ 6177 @Deprecated 6178 public static String replace(final String text, final String searchString, final String replacement) { 6179 return Strings.CS.replace(text, searchString, replacement); 6180 } 6181 6182 /** 6183 * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6184 * 6185 * <p> 6186 * A {@code null} reference passed to this method is a no-op. 6187 * </p> 6188 * 6189 * <pre> 6190 * StringUtils.replace(null, *, *, *) = null 6191 * StringUtils.replace("", *, *, *) = "" 6192 * StringUtils.replace("any", null, *, *) = "any" 6193 * StringUtils.replace("any", *, null, *) = "any" 6194 * StringUtils.replace("any", "", *, *) = "any" 6195 * StringUtils.replace("any", *, *, 0) = "any" 6196 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 6197 * StringUtils.replace("abaa", "a", "", -1) = "b" 6198 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 6199 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 6200 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 6201 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 6202 * </pre> 6203 * 6204 * @param text text to search and replace in, may be null. 6205 * @param searchString the String to search for, may be null. 6206 * @param replacement the String to replace it with, may be null. 6207 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6208 * @return the text with any replacements processed, {@code null} if null String input. 6209 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}. 6210 */ 6211 @Deprecated 6212 public static String replace(final String text, final String searchString, final String replacement, final int max) { 6213 return Strings.CS.replace(text, searchString, replacement, max); 6214 } 6215 6216 /** 6217 * Replaces each substring of the text String that matches the given regular expression with the given replacement. 6218 * 6219 * This method is a {@code null} safe equivalent to: 6220 * <ul> 6221 * <li>{@code text.replaceAll(regex, replacement)}</li> 6222 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 6223 * </ul> 6224 * 6225 * <p> 6226 * A {@code null} reference passed to this method is a no-op. 6227 * </p> 6228 * 6229 * <p> 6230 * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL 6231 * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl. 6232 * </p> 6233 * 6234 * <pre>{@code 6235 * StringUtils.replaceAll(null, *, *) = null 6236 * StringUtils.replaceAll("any", (String) null, *) = "any" 6237 * StringUtils.replaceAll("any", *, null) = "any" 6238 * StringUtils.replaceAll("", "", "zzz") = "zzz" 6239 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 6240 * StringUtils.replaceAll("", ".+", "zzz") = "" 6241 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 6242 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 6243 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 6244 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 6245 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6246 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6247 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6248 * }</pre> 6249 * 6250 * @param text text to search and replace in, may be null. 6251 * @param regex the regular expression to which this string is to be matched. 6252 * @param replacement the string to be substituted for each match. 6253 * @return the text with any replacements processed, {@code null} if null String input. 6254 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 6255 * @see #replacePattern(String, String, String) 6256 * @see String#replaceAll(String, String) 6257 * @see java.util.regex.Pattern 6258 * @see java.util.regex.Pattern#DOTALL 6259 * @since 3.5 6260 * @deprecated Use {@link RegExUtils#replaceAll(String, String, String)}. 6261 */ 6262 @Deprecated 6263 public static String replaceAll(final String text, final String regex, final String replacement) { 6264 return RegExUtils.replaceAll(text, regex, replacement); 6265 } 6266 6267 /** 6268 * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}. 6269 * 6270 * <p> 6271 * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. 6272 * </p> 6273 * 6274 * <pre> 6275 * StringUtils.replaceChars(null, *, *) = null 6276 * StringUtils.replaceChars("", *, *) = "" 6277 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 6278 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 6279 * </pre> 6280 * 6281 * @param str String to replace characters in, may be null. 6282 * @param searchChar the character to search for, may be null. 6283 * @param replaceChar the character to replace, may be null. 6284 * @return modified String, {@code null} if null string input. 6285 * @since 2.0 6286 */ 6287 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 6288 if (str == null) { 6289 return null; 6290 } 6291 return str.replace(searchChar, replaceChar); 6292 } 6293 6294 /** 6295 * Replaces multiple characters in a String in one go. This method can also be used to delete characters. 6296 * 6297 * <p> 6298 * For example: 6299 * </p> 6300 * <pre> 6301 * replaceChars("hello", "ho", "jy") = jelly. 6302 * </pre> 6303 * 6304 * <p> 6305 * 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 6306 * the input string. 6307 * </p> 6308 * 6309 * <p> 6310 * 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 6311 * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored. 6312 * </p> 6313 * 6314 * <pre> 6315 * StringUtils.replaceChars(null, *, *) = null 6316 * StringUtils.replaceChars("", *, *) = "" 6317 * StringUtils.replaceChars("abc", null, *) = "abc" 6318 * StringUtils.replaceChars("abc", "", *) = "abc" 6319 * StringUtils.replaceChars("abc", "b", null) = "ac" 6320 * StringUtils.replaceChars("abc", "b", "") = "ac" 6321 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 6322 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 6323 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 6324 * </pre> 6325 * 6326 * @param str String to replace characters in, may be null. 6327 * @param searchChars a set of characters to search for, may be null. 6328 * @param replaceChars a set of characters to replace, may be null. 6329 * @return modified String, {@code null} if null string input. 6330 * @since 2.0 6331 */ 6332 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 6333 if (isEmpty(str) || isEmpty(searchChars)) { 6334 return str; 6335 } 6336 replaceChars = ObjectUtils.toString(replaceChars); 6337 boolean modified = false; 6338 final int replaceCharsLength = replaceChars.length(); 6339 final int strLength = str.length(); 6340 final StringBuilder buf = new StringBuilder(strLength); 6341 for (int i = 0; i < strLength; i++) { 6342 final char ch = str.charAt(i); 6343 final int index = searchChars.indexOf(ch); 6344 if (index >= 0) { 6345 modified = true; 6346 if (index < replaceCharsLength) { 6347 buf.append(replaceChars.charAt(index)); 6348 } 6349 } else { 6350 buf.append(ch); 6351 } 6352 } 6353 if (modified) { 6354 return buf.toString(); 6355 } 6356 return str; 6357 } 6358 6359 /** 6360 * Replaces all occurrences of Strings within another String. 6361 * 6362 * <p> 6363 * 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 6364 * will not repeat. For repeating replaces, call the overloaded method. 6365 * </p> 6366 * 6367 * <pre> 6368 * StringUtils.replaceEach(null, *, *) = null 6369 * StringUtils.replaceEach("", *, *) = "" 6370 * StringUtils.replaceEach("aba", null, null) = "aba" 6371 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 6372 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 6373 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 6374 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 6375 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 6376 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6377 * (example of how it does not repeat) 6378 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 6379 * </pre> 6380 * 6381 * @param text text to search and replace in, no-op if null. 6382 * @param searchList the Strings to search for, no-op if null. 6383 * @param replacementList the Strings to replace them with, no-op if null. 6384 * @return the text with any replacements processed, {@code null} if null String input. 6385 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6386 * @since 2.4 6387 */ 6388 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 6389 return replaceEach(text, searchList, replacementList, false, 0); 6390 } 6391 6392 /** 6393 * Replace all occurrences of Strings within another String. This is a private recursive helper method for 6394 * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])} 6395 * 6396 * <p> 6397 * 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. 6398 * </p> 6399 * 6400 * <pre> 6401 * StringUtils.replaceEach(null, *, *, *, *) = null 6402 * StringUtils.replaceEach("", *, *, *, *) = "" 6403 * StringUtils.replaceEach("aba", null, null, *, *) = "aba" 6404 * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba" 6405 * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba" 6406 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba" 6407 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b" 6408 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba" 6409 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte" 6410 * (example of how it repeats) 6411 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte" 6412 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte" 6413 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = Throws {@link IllegalStateException} 6414 * </pre> 6415 * 6416 * @param text text to search and replace in, no-op if null. 6417 * @param searchList the Strings to search for, no-op if null. 6418 * @param replacementList the Strings to replace them with, no-op if null. 6419 * @param repeat if true, then replace repeatedly until there are no more possible replacements or timeToLive < 0. 6420 * @param timeToLive if less than 0 then there is a circular reference and endless loop. 6421 * @return the text with any replacements processed, {@code null} if null String input. 6422 * @throws IllegalStateException if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6423 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6424 * @since 2.4 6425 */ 6426 private static String replaceEach( 6427 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 6428 6429 // Performance note: This creates very few new objects (one major goal) 6430 // let me know if there are performance requests, we can create a harness to measure 6431 if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) { 6432 return text; 6433 } 6434 6435 // if recursing, this shouldn't be less than 0 6436 if (timeToLive < 0) { 6437 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 6438 "output of one loop is the input of another"); 6439 } 6440 6441 final int searchLength = searchList.length; 6442 final int replacementLength = replacementList.length; 6443 6444 // make sure lengths are ok, these need to be equal 6445 if (searchLength != replacementLength) { 6446 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 6447 + searchLength 6448 + " vs " 6449 + replacementLength); 6450 } 6451 6452 // keep track of which still have matches 6453 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 6454 6455 // index on index that the match was found 6456 int textIndex = -1; 6457 int replaceIndex = -1; 6458 int tempIndex; 6459 6460 // index of replace array that will replace the search string found 6461 // NOTE: logic duplicated below START 6462 for (int i = 0; i < searchLength; i++) { 6463 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6464 continue; 6465 } 6466 tempIndex = text.indexOf(searchList[i]); 6467 6468 // see if we need to keep searching for this 6469 if (tempIndex == -1) { 6470 noMoreMatchesForReplIndex[i] = true; 6471 } else if (textIndex == -1 || tempIndex < textIndex) { 6472 textIndex = tempIndex; 6473 replaceIndex = i; 6474 } 6475 } 6476 // NOTE: logic mostly below END 6477 6478 // no search strings found, we are done 6479 if (textIndex == -1) { 6480 return text; 6481 } 6482 6483 int start = 0; 6484 6485 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 6486 int increase = 0; 6487 6488 // count the replacement text elements that are larger than their corresponding text being replaced 6489 for (int i = 0; i < searchList.length; i++) { 6490 if (searchList[i] == null || replacementList[i] == null) { 6491 continue; 6492 } 6493 final int greater = replacementList[i].length() - searchList[i].length(); 6494 if (greater > 0) { 6495 increase += 3 * greater; // assume 3 matches 6496 } 6497 } 6498 // have upper-bound at 20% increase, then let Java take over 6499 increase = Math.min(increase, text.length() / 5); 6500 6501 final StringBuilder buf = new StringBuilder(text.length() + increase); 6502 6503 while (textIndex != -1) { 6504 6505 for (int i = start; i < textIndex; i++) { 6506 buf.append(text.charAt(i)); 6507 } 6508 buf.append(replacementList[replaceIndex]); 6509 6510 start = textIndex + searchList[replaceIndex].length(); 6511 6512 textIndex = -1; 6513 replaceIndex = -1; 6514 // find the next earliest match 6515 // NOTE: logic mostly duplicated above START 6516 for (int i = 0; i < searchLength; i++) { 6517 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) { 6518 continue; 6519 } 6520 tempIndex = text.indexOf(searchList[i], start); 6521 6522 // see if we need to keep searching for this 6523 if (tempIndex == -1) { 6524 noMoreMatchesForReplIndex[i] = true; 6525 } else if (textIndex == -1 || tempIndex < textIndex) { 6526 textIndex = tempIndex; 6527 replaceIndex = i; 6528 } 6529 } 6530 // NOTE: logic duplicated above END 6531 6532 } 6533 final int textLength = text.length(); 6534 for (int i = start; i < textLength; i++) { 6535 buf.append(text.charAt(i)); 6536 } 6537 final String result = buf.toString(); 6538 if (!repeat) { 6539 return result; 6540 } 6541 6542 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 6543 } 6544 6545 /** 6546 * Replaces all occurrences of Strings within another String. 6547 * 6548 * <p> 6549 * 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. 6550 * </p> 6551 * 6552 * <pre> 6553 * StringUtils.replaceEachRepeatedly(null, *, *) = null 6554 * StringUtils.replaceEachRepeatedly("", *, *) = "" 6555 * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba" 6556 * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba" 6557 * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba" 6558 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba" 6559 * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b" 6560 * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba" 6561 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 6562 * (example of how it repeats) 6563 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte" 6564 * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = Throws {@link IllegalStateException} 6565 * </pre> 6566 * 6567 * @param text text to search and replace in, no-op if null. 6568 * @param searchList the Strings to search for, no-op if null. 6569 * @param replacementList the Strings to replace them with, no-op if null. 6570 * @return the text with any replacements processed, {@code null} if null String input. 6571 * @throws IllegalStateException if the search is repeating and there is an endless loop due to outputs of one being inputs to another. 6572 * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0). 6573 * @since 2.4 6574 */ 6575 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 6576 final int timeToLive = Math.max(ArrayUtils.getLength(searchList), DEFAULT_TTL); 6577 return replaceEach(text, searchList, replacementList, true, timeToLive); 6578 } 6579 6580 /** 6581 * Replaces the first substring of the text string that matches the given regular expression with the given replacement. 6582 * 6583 * This method is a {@code null} safe equivalent to: 6584 * <ul> 6585 * <li>{@code text.replaceFirst(regex, replacement)}</li> 6586 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 6587 * </ul> 6588 * 6589 * <p> 6590 * A {@code null} reference passed to this method is a no-op. 6591 * </p> 6592 * 6593 * <p> 6594 * 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 6595 * single-line mode in Perl. 6596 * </p> 6597 * 6598 * <pre>{@code 6599 * StringUtils.replaceFirst(null, *, *) = null 6600 * StringUtils.replaceFirst("any", (String) null, *) = "any" 6601 * StringUtils.replaceFirst("any", *, null) = "any" 6602 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 6603 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 6604 * StringUtils.replaceFirst("", ".+", "zzz") = "" 6605 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 6606 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 6607 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 6608 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 6609 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 6610 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 6611 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 6612 * }</pre> 6613 * 6614 * @param text text to search and replace in, may be null. 6615 * @param regex the regular expression to which this string is to be matched. 6616 * @param replacement the string to be substituted for the first match. 6617 * @return the text with the first replacement processed, {@code null} if null String input. 6618 * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid. 6619 * @see String#replaceFirst(String, String) 6620 * @see java.util.regex.Pattern 6621 * @see java.util.regex.Pattern#DOTALL 6622 * @since 3.5 6623 * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String)}. 6624 */ 6625 @Deprecated 6626 public static String replaceFirst(final String text, final String regex, final String replacement) { 6627 return RegExUtils.replaceFirst(text, regex, replacement); 6628 } 6629 6630 /** 6631 * Case insensitively replaces all occurrences of a String within another String. 6632 * 6633 * <p> 6634 * A {@code null} reference passed to this method is a no-op. 6635 * </p> 6636 * 6637 * <pre> 6638 * StringUtils.replaceIgnoreCase(null, *, *) = null 6639 * StringUtils.replaceIgnoreCase("", *, *) = "" 6640 * StringUtils.replaceIgnoreCase("any", null, *) = "any" 6641 * StringUtils.replaceIgnoreCase("any", *, null) = "any" 6642 * StringUtils.replaceIgnoreCase("any", "", *) = "any" 6643 * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba" 6644 * StringUtils.replaceIgnoreCase("abA", "A", "") = "b" 6645 * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz" 6646 * </pre> 6647 * 6648 * @param text text to search and replace in, may be null. 6649 * @param searchString the String to search for (case-insensitive), may be null. 6650 * @param replacement the String to replace it with, may be null. 6651 * @return the text with any replacements processed, {@code null} if null String input. 6652 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6653 * @since 3.5 6654 * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}. 6655 */ 6656 @Deprecated 6657 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) { 6658 return Strings.CI.replace(text, searchString, replacement); 6659 } 6660 6661 /** 6662 * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String. 6663 * 6664 * <p> 6665 * A {@code null} reference passed to this method is a no-op. 6666 * </p> 6667 * 6668 * <pre> 6669 * StringUtils.replaceIgnoreCase(null, *, *, *) = null 6670 * StringUtils.replaceIgnoreCase("", *, *, *) = "" 6671 * StringUtils.replaceIgnoreCase("any", null, *, *) = "any" 6672 * StringUtils.replaceIgnoreCase("any", *, null, *) = "any" 6673 * StringUtils.replaceIgnoreCase("any", "", *, *) = "any" 6674 * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any" 6675 * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa" 6676 * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b" 6677 * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa" 6678 * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa" 6679 * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza" 6680 * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz" 6681 * </pre> 6682 * 6683 * @param text text to search and replace in, may be null. 6684 * @param searchString the String to search for (case-insensitive), may be null. 6685 * @param replacement the String to replace it with, may be null. 6686 * @param max maximum number of values to replace, or {@code -1} if no maximum. 6687 * @return the text with any replacements processed, {@code null} if null String input. 6688 * @since 3.5 6689 * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}. 6690 */ 6691 @Deprecated 6692 public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) { 6693 return Strings.CI.replace(text, searchString, replacement, max); 6694 } 6695 6696 /** 6697 * Replaces a String with another String inside a larger String, once. 6698 * 6699 * <p> 6700 * A {@code null} reference passed to this method is a no-op. 6701 * </p> 6702 * 6703 * <pre> 6704 * StringUtils.replaceOnce(null, *, *) = null 6705 * StringUtils.replaceOnce("", *, *) = "" 6706 * StringUtils.replaceOnce("any", null, *) = "any" 6707 * StringUtils.replaceOnce("any", *, null) = "any" 6708 * StringUtils.replaceOnce("any", "", *) = "any" 6709 * StringUtils.replaceOnce("aba", "a", null) = "aba" 6710 * StringUtils.replaceOnce("aba", "a", "") = "ba" 6711 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 6712 * </pre> 6713 * 6714 * @param text text to search and replace in, may be null. 6715 * @param searchString the String to search for, may be null. 6716 * @param replacement the String to replace with, may be null. 6717 * @return the text with any replacements processed, {@code null} if null String input. 6718 * @see #replace(String text, String searchString, String replacement, int max) 6719 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}. 6720 */ 6721 @Deprecated 6722 public static String replaceOnce(final String text, final String searchString, final String replacement) { 6723 return Strings.CS.replaceOnce(text, searchString, replacement); 6724 } 6725 6726 /** 6727 * Case insensitively replaces a String with another String inside a larger String, once. 6728 * 6729 * <p> 6730 * A {@code null} reference passed to this method is a no-op. 6731 * </p> 6732 * 6733 * <pre> 6734 * StringUtils.replaceOnceIgnoreCase(null, *, *) = null 6735 * StringUtils.replaceOnceIgnoreCase("", *, *) = "" 6736 * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any" 6737 * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any" 6738 * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any" 6739 * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba" 6740 * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba" 6741 * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba" 6742 * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo" 6743 * </pre> 6744 * 6745 * @param text text to search and replace in, may be null. 6746 * @param searchString the String to search for (case-insensitive), may be null. 6747 * @param replacement the String to replace with, may be null. 6748 * @return the text with any replacements processed, {@code null} if null String input. 6749 * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max) 6750 * @since 3.5 6751 * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}. 6752 */ 6753 @Deprecated 6754 public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) { 6755 return Strings.CI.replaceOnce(text, searchString, replacement); 6756 } 6757 6758 /** 6759 * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL} 6760 * option. DOTALL is also known as single-line mode in Perl. 6761 * 6762 * This call is a {@code null} safe equivalent to: 6763 * <ul> 6764 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 6765 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 6766 * </ul> 6767 * 6768 * <p> 6769 * A {@code null} reference passed to this method is a no-op. 6770 * </p> 6771 * 6772 * <pre>{@code 6773 * StringUtils.replacePattern(null, *, *) = null 6774 * StringUtils.replacePattern("any", (String) null, *) = "any" 6775 * StringUtils.replacePattern("any", *, null) = "any" 6776 * StringUtils.replacePattern("", "", "zzz") = "zzz" 6777 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 6778 * StringUtils.replacePattern("", ".+", "zzz") = "" 6779 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 6780 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 6781 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 6782 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 6783 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 6784 * }</pre> 6785 * 6786 * @param source the source string. 6787 * @param regex the regular expression to which this string is to be matched. 6788 * @param replacement the string to be substituted for each match. 6789 * @return The resulting {@link String}. 6790 * @see #replaceAll(String, String, String) 6791 * @see String#replaceAll(String, String) 6792 * @see Pattern#DOTALL 6793 * @since 3.2 6794 * @since 3.5 Changed {@code null} reference passed to this method is a no-op. 6795 * @deprecated Use {@link RegExUtils#replacePattern(CharSequence, String, String)}. 6796 */ 6797 @Deprecated 6798 public static String replacePattern(final String source, final String regex, final String replacement) { 6799 return RegExUtils.replacePattern(source, regex, replacement); 6800 } 6801 6802 /** 6803 * Reverses a String as per {@link StringBuilder#reverse()}. 6804 * 6805 * <p> 6806 * A {@code null} String returns {@code null}. 6807 * </p> 6808 * 6809 * <pre> 6810 * StringUtils.reverse(null) = null 6811 * StringUtils.reverse("") = "" 6812 * StringUtils.reverse("bat") = "tab" 6813 * </pre> 6814 * 6815 * @param str the String to reverse, may be null. 6816 * @return the reversed String, {@code null} if null String input. 6817 */ 6818 public static String reverse(final String str) { 6819 if (str == null) { 6820 return null; 6821 } 6822 return new StringBuilder(str).reverse().toString(); 6823 } 6824 6825 /** 6826 * Reverses a String that is delimited by a specific character. 6827 * 6828 * <p> 6829 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}). 6830 * </p> 6831 * 6832 * <pre> 6833 * StringUtils.reverseDelimited(null, *) = null 6834 * StringUtils.reverseDelimited("", *) = "" 6835 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 6836 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 6837 * </pre> 6838 * 6839 * @param str the String to reverse, may be null. 6840 * @param separatorChar the separator character to use. 6841 * @return the reversed String, {@code null} if null String input. 6842 * @since 2.0 6843 */ 6844 public static String reverseDelimited(final String str, final char separatorChar) { 6845 final String[] strs = split(str, separatorChar); 6846 ArrayUtils.reverse(strs); 6847 return join(strs, separatorChar); 6848 } 6849 6850 /** 6851 * Gets the rightmost {@code len} characters of a String. 6852 * 6853 * <p> 6854 * 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 6855 * returned if len is negative. 6856 * </p> 6857 * 6858 * <pre> 6859 * StringUtils.right(null, *) = null 6860 * StringUtils.right(*, -ve) = "" 6861 * StringUtils.right("", *) = "" 6862 * StringUtils.right("abc", 0) = "" 6863 * StringUtils.right("abc", 2) = "bc" 6864 * StringUtils.right("abc", 4) = "abc" 6865 * </pre> 6866 * 6867 * @param str the String to get the rightmost characters from, may be null. 6868 * @param len the length of the required String. 6869 * @return the rightmost characters, {@code null} if null String input. 6870 */ 6871 public static String right(final String str, final int len) { 6872 if (str == null) { 6873 return null; 6874 } 6875 if (len < 0) { 6876 return EMPTY; 6877 } 6878 if (str.length() <= len) { 6879 return str; 6880 } 6881 return str.substring(str.length() - len); 6882 } 6883 6884 /** 6885 * Right pad a String with spaces (' '). 6886 * 6887 * <p> 6888 * The String is padded to the size of {@code size}. 6889 * </p> 6890 * 6891 * <pre> 6892 * StringUtils.rightPad(null, *) = null 6893 * StringUtils.rightPad("", 3) = " " 6894 * StringUtils.rightPad("bat", 3) = "bat" 6895 * StringUtils.rightPad("bat", 5) = "bat " 6896 * StringUtils.rightPad("bat", 1) = "bat" 6897 * StringUtils.rightPad("bat", -1) = "bat" 6898 * </pre> 6899 * 6900 * @param str the String to pad out, may be null. 6901 * @param size the size to pad to. 6902 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6903 */ 6904 public static String rightPad(final String str, final int size) { 6905 return rightPad(str, size, ' '); 6906 } 6907 6908 /** 6909 * Right pad a String with a specified character. 6910 * 6911 * <p> 6912 * The String is padded to the size of {@code size}. 6913 * </p> 6914 * 6915 * <pre> 6916 * StringUtils.rightPad(null, *, *) = null 6917 * StringUtils.rightPad("", 3, 'z') = "zzz" 6918 * StringUtils.rightPad("bat", 3, 'z') = "bat" 6919 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 6920 * StringUtils.rightPad("bat", 1, 'z') = "bat" 6921 * StringUtils.rightPad("bat", -1, 'z') = "bat" 6922 * </pre> 6923 * 6924 * @param str the String to pad out, may be null. 6925 * @param size the size to pad to. 6926 * @param padChar the character to pad with. 6927 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6928 * @since 2.0 6929 */ 6930 public static String rightPad(final String str, final int size, final char padChar) { 6931 if (str == null) { 6932 return null; 6933 } 6934 final int pads = size - str.length(); 6935 if (pads <= 0) { 6936 return str; // returns original String when possible 6937 } 6938 if (pads > PAD_LIMIT) { 6939 return rightPad(str, size, String.valueOf(padChar)); 6940 } 6941 return str.concat(repeat(padChar, pads)); 6942 } 6943 6944 /** 6945 * Right pad a String with a specified String. 6946 * 6947 * <p> 6948 * The String is padded to the size of {@code size}. 6949 * </p> 6950 * 6951 * <pre> 6952 * StringUtils.rightPad(null, *, *) = null 6953 * StringUtils.rightPad("", 3, "z") = "zzz" 6954 * StringUtils.rightPad("bat", 3, "yz") = "bat" 6955 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 6956 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 6957 * StringUtils.rightPad("bat", 1, "yz") = "bat" 6958 * StringUtils.rightPad("bat", -1, "yz") = "bat" 6959 * StringUtils.rightPad("bat", 5, null) = "bat " 6960 * StringUtils.rightPad("bat", 5, "") = "bat " 6961 * </pre> 6962 * 6963 * @param str the String to pad out, may be null. 6964 * @param size the size to pad to. 6965 * @param padStr the String to pad with, null or empty treated as single space. 6966 * @return right padded String or original String if no padding is necessary, {@code null} if null String input. 6967 */ 6968 public static String rightPad(final String str, final int size, String padStr) { 6969 if (str == null) { 6970 return null; 6971 } 6972 if (isEmpty(padStr)) { 6973 padStr = SPACE; 6974 } 6975 final int padLen = padStr.length(); 6976 final int strLen = str.length(); 6977 final int pads = size - strLen; 6978 if (pads <= 0) { 6979 return str; // returns original String when possible 6980 } 6981 if (padLen == 1 && pads <= PAD_LIMIT) { 6982 return rightPad(str, size, padStr.charAt(0)); 6983 } 6984 if (pads == padLen) { 6985 return str.concat(padStr); 6986 } 6987 if (pads < padLen) { 6988 return str.concat(padStr.substring(0, pads)); 6989 } 6990 final char[] padding = new char[pads]; 6991 final char[] padChars = padStr.toCharArray(); 6992 for (int i = 0; i < pads; i++) { 6993 padding[i] = padChars[i % padLen]; 6994 } 6995 return str.concat(new String(padding)); 6996 } 6997 6998 /** 6999 * Rotate (circular shift) a String of {@code shift} characters. 7000 * <ul> 7001 * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)</li> 7002 * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)</li> 7003 * </ul> 7004 * 7005 * <pre> 7006 * StringUtils.rotate(null, *) = null 7007 * StringUtils.rotate("", *) = "" 7008 * StringUtils.rotate("abcdefg", 0) = "abcdefg" 7009 * StringUtils.rotate("abcdefg", 2) = "fgabcde" 7010 * StringUtils.rotate("abcdefg", -2) = "cdefgab" 7011 * StringUtils.rotate("abcdefg", 7) = "abcdefg" 7012 * StringUtils.rotate("abcdefg", -7) = "abcdefg" 7013 * StringUtils.rotate("abcdefg", 9) = "fgabcde" 7014 * StringUtils.rotate("abcdefg", -9) = "cdefgab" 7015 * </pre> 7016 * 7017 * @param str the String to rotate, may be null. 7018 * @param shift number of time to shift (positive : right shift, negative : left shift). 7019 * @return the rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input. 7020 * @since 3.5 7021 */ 7022 public static String rotate(final String str, final int shift) { 7023 if (str == null) { 7024 return null; 7025 } 7026 final int strLen = str.length(); 7027 if (shift == 0 || strLen == 0 || shift % strLen == 0) { 7028 return str; 7029 } 7030 final StringBuilder builder = new StringBuilder(strLen); 7031 final int offset = -(shift % strLen); 7032 builder.append(substring(str, offset)); 7033 builder.append(substring(str, 0, offset)); 7034 return builder.toString(); 7035 } 7036 7037 /** 7038 * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 7039 * 7040 * <p> 7041 * 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 7042 * StrTokenizer class. 7043 * </p> 7044 * 7045 * <p> 7046 * A {@code null} input String returns {@code null}. 7047 * </p> 7048 * 7049 * <pre> 7050 * StringUtils.split(null) = null 7051 * StringUtils.split("") = [] 7052 * StringUtils.split("abc def") = ["abc", "def"] 7053 * StringUtils.split("abc def") = ["abc", "def"] 7054 * StringUtils.split(" abc ") = ["abc"] 7055 * </pre> 7056 * 7057 * @param str the String to parse, may be null. 7058 * @return an array of parsed Strings, {@code null} if null String input. 7059 */ 7060 public static String[] split(final String str) { 7061 return split(str, null, -1); 7062 } 7063 7064 /** 7065 * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer. 7066 * 7067 * <p> 7068 * 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 7069 * StrTokenizer class. 7070 * </p> 7071 * 7072 * <p> 7073 * A {@code null} input String returns {@code null}. 7074 * </p> 7075 * 7076 * <pre> 7077 * StringUtils.split(null, *) = null 7078 * StringUtils.split("", *) = [] 7079 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 7080 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 7081 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 7082 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 7083 * </pre> 7084 * 7085 * @param str the String to parse, may be null. 7086 * @param separatorChar the character used as the delimiter. 7087 * @return an array of parsed Strings, {@code null} if null String input. 7088 * @since 2.0 7089 */ 7090 public static String[] split(final String str, final char separatorChar) { 7091 return splitWorker(str, separatorChar, false); 7092 } 7093 7094 /** 7095 * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer. 7096 * 7097 * <p> 7098 * 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 7099 * StrTokenizer class. 7100 * </p> 7101 * 7102 * <p> 7103 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7104 * </p> 7105 * 7106 * <pre> 7107 * StringUtils.split(null, *) = null 7108 * StringUtils.split("", *) = [] 7109 * StringUtils.split("abc def", null) = ["abc", "def"] 7110 * StringUtils.split("abc def", " ") = ["abc", "def"] 7111 * StringUtils.split("abc def", " ") = ["abc", "def"] 7112 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7113 * </pre> 7114 * 7115 * @param str the String to parse, may be null. 7116 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7117 * @return an array of parsed Strings, {@code null} if null String input. 7118 */ 7119 public static String[] split(final String str, final String separatorChars) { 7120 return splitWorker(str, separatorChars, -1, false); 7121 } 7122 7123 /** 7124 * Splits the provided text into an array with a maximum length, separators specified. 7125 * 7126 * <p> 7127 * The separator is not included in the returned String array. Adjacent separators are treated as one separator. 7128 * </p> 7129 * 7130 * <p> 7131 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7132 * </p> 7133 * 7134 * <p> 7135 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7136 * strings (including separator characters). 7137 * </p> 7138 * 7139 * <pre> 7140 * StringUtils.split(null, *, *) = null 7141 * StringUtils.split("", *, *) = [] 7142 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7143 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 7144 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7145 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7146 * </pre> 7147 * 7148 * @param str the String to parse, may be null. 7149 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7150 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7151 * @return an array of parsed Strings, {@code null} if null String input. 7152 */ 7153 public static String[] split(final String str, final String separatorChars, final int max) { 7154 return splitWorker(str, separatorChars, max, false); 7155 } 7156 7157 /** 7158 * 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 7159 * as complete tokens. 7160 * 7161 * <pre> 7162 * StringUtils.splitByCharacterType(null) = null 7163 * StringUtils.splitByCharacterType("") = [] 7164 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7165 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 7166 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7167 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 7168 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 7169 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 7170 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 7171 * </pre> 7172 * 7173 * @param str the String to split, may be {@code null}. 7174 * @return an array of parsed Strings, {@code null} if null String input. 7175 * @since 2.4 7176 */ 7177 public static String[] splitByCharacterType(final String str) { 7178 return splitByCharacterType(str, false); 7179 } 7180 7181 /** 7182 * 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 7183 * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@code Character.UPPERCASE_LETTER}, if any, 7184 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, 7185 * {@code Character.UPPERCASE_LETTER} token. 7186 * 7187 * @param str the String to split, may be {@code null}. 7188 * @param camelCase whether to use so-called "camel-case" for letter types. 7189 * @return an array of parsed Strings, {@code null} if null String input. 7190 * @since 2.4 7191 */ 7192 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 7193 if (str == null) { 7194 return null; 7195 } 7196 if (str.isEmpty()) { 7197 return ArrayUtils.EMPTY_STRING_ARRAY; 7198 } 7199 final char[] c = str.toCharArray(); 7200 final List<String> list = new ArrayList<>(); 7201 int tokenStart = 0; 7202 int currentType = Character.getType(c[tokenStart]); 7203 for (int pos = tokenStart + 1; pos < c.length; pos++) { 7204 final int type = Character.getType(c[pos]); 7205 if (type == currentType) { 7206 continue; 7207 } 7208 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 7209 final int newTokenStart = pos - 1; 7210 if (newTokenStart != tokenStart) { 7211 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 7212 tokenStart = newTokenStart; 7213 } 7214 } else { 7215 list.add(new String(c, tokenStart, pos - tokenStart)); 7216 tokenStart = pos; 7217 } 7218 currentType = type; 7219 } 7220 list.add(new String(c, tokenStart, c.length - tokenStart)); 7221 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7222 } 7223 7224 /** 7225 * 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 7226 * as complete tokens, with the following exception: the character of type {@code Character.UPPERCASE_LETTER}, if any, immediately preceding a token of type 7227 * {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@code Character.UPPERCASE_LETTER} token. 7228 * 7229 * <pre> 7230 * StringUtils.splitByCharacterTypeCamelCase(null) = null 7231 * StringUtils.splitByCharacterTypeCamelCase("") = [] 7232 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7233 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 7234 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 7235 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 7236 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 7237 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 7238 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 7239 * </pre> 7240 * 7241 * @param str the String to split, may be {@code null}. 7242 * @return an array of parsed Strings, {@code null} if null String input. 7243 * @since 2.4 7244 */ 7245 public static String[] splitByCharacterTypeCamelCase(final String str) { 7246 return splitByCharacterType(str, true); 7247 } 7248 7249 /** 7250 * Splits the provided text into an array, separator string specified. 7251 * 7252 * <p> 7253 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7254 * </p> 7255 * 7256 * <p> 7257 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7258 * </p> 7259 * 7260 * <pre> 7261 * StringUtils.splitByWholeSeparator(null, *) = null 7262 * StringUtils.splitByWholeSeparator("", *) = [] 7263 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7264 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 7265 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7266 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7267 * </pre> 7268 * 7269 * @param str the String to parse, may be null. 7270 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7271 * @return an array of parsed Strings, {@code null} if null String was input. 7272 */ 7273 public static String[] splitByWholeSeparator(final String str, final String separator) { 7274 return splitByWholeSeparatorWorker(str, separator, -1, false); 7275 } 7276 7277 /** 7278 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7279 * 7280 * <p> 7281 * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator. 7282 * </p> 7283 * 7284 * <p> 7285 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7286 * </p> 7287 * 7288 * <pre> 7289 * StringUtils.splitByWholeSeparator(null, *, *) = null 7290 * StringUtils.splitByWholeSeparator("", *, *) = [] 7291 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7292 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 7293 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7294 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7295 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7296 * </pre> 7297 * 7298 * @param str the String to parse, may be null. 7299 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7300 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7301 * @return an array of parsed Strings, {@code null} if null String was input. 7302 */ 7303 public static String[] splitByWholeSeparator(final String str, final String separator, final int max) { 7304 return splitByWholeSeparatorWorker(str, separator, max, false); 7305 } 7306 7307 /** 7308 * Splits the provided text into an array, separator string specified. 7309 * 7310 * <p> 7311 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7312 * split use the StrTokenizer class. 7313 * </p> 7314 * 7315 * <p> 7316 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7317 * </p> 7318 * 7319 * <pre> 7320 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 7321 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 7322 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 7323 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 7324 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7325 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 7326 * </pre> 7327 * 7328 * @param str the String to parse, may be null. 7329 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7330 * @return an array of parsed Strings, {@code null} if null String was input. 7331 * @since 2.4 7332 */ 7333 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 7334 return splitByWholeSeparatorWorker(str, separator, -1, true); 7335 } 7336 7337 /** 7338 * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings. 7339 * 7340 * <p> 7341 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7342 * split use the StrTokenizer class. 7343 * </p> 7344 * 7345 * <p> 7346 * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace. 7347 * </p> 7348 * 7349 * <pre> 7350 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 7351 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 7352 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7353 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7354 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7355 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 7356 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 7357 * </pre> 7358 * 7359 * @param str the String to parse, may be null. 7360 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7361 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7362 * @return an array of parsed Strings, {@code null} if null String was input. 7363 * @since 2.4 7364 */ 7365 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 7366 return splitByWholeSeparatorWorker(str, separator, max, true); 7367 } 7368 7369 /** 7370 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 7371 * 7372 * @param str the String to parse, may be {@code null}. 7373 * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace. 7374 * @param max the maximum number of elements to include in the returned array. A zero or negative value implies no limit. 7375 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7376 * one separator. 7377 * @return an array of parsed Strings, {@code null} if null String input. 7378 * @since 2.4 7379 */ 7380 private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) { 7381 if (str == null) { 7382 return null; 7383 } 7384 final int len = str.length(); 7385 if (len == 0) { 7386 return ArrayUtils.EMPTY_STRING_ARRAY; 7387 } 7388 if (separator == null || EMPTY.equals(separator)) { 7389 // Split on whitespace. 7390 return splitWorker(str, null, max, preserveAllTokens); 7391 } 7392 final int separatorLength = separator.length(); 7393 final ArrayList<String> substrings = new ArrayList<>(); 7394 int numberOfSubstrings = 0; 7395 int beg = 0; 7396 int end = 0; 7397 while (end < len) { 7398 end = str.indexOf(separator, beg); 7399 if (end > -1) { 7400 if (end > beg) { 7401 numberOfSubstrings += 1; 7402 if (numberOfSubstrings == max) { 7403 end = len; 7404 substrings.add(str.substring(beg)); 7405 } else { 7406 // The following is OK, because String.substring( beg, end ) excludes 7407 // the character at the position 'end'. 7408 substrings.add(str.substring(beg, end)); 7409 // Set the starting point for the next search. 7410 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 7411 // which is the right calculation: 7412 beg = end + separatorLength; 7413 } 7414 } else { 7415 // We found a consecutive occurrence of the separator, so skip it. 7416 if (preserveAllTokens) { 7417 numberOfSubstrings += 1; 7418 if (numberOfSubstrings == max) { 7419 end = len; 7420 substrings.add(str.substring(beg)); 7421 } else { 7422 substrings.add(EMPTY); 7423 } 7424 } 7425 beg = end + separatorLength; 7426 } 7427 } else { 7428 // String.substring( beg ) goes from 'beg' to the end of the String. 7429 substrings.add(str.substring(beg)); 7430 end = len; 7431 } 7432 } 7433 return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7434 } 7435 7436 /** 7437 * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators. 7438 * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}. 7439 * 7440 * <p> 7441 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7442 * split use the StrTokenizer class. 7443 * </p> 7444 * 7445 * <p> 7446 * A {@code null} input String returns {@code null}. 7447 * </p> 7448 * 7449 * <pre> 7450 * StringUtils.splitPreserveAllTokens(null) = null 7451 * StringUtils.splitPreserveAllTokens("") = [] 7452 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 7453 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 7454 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 7455 * </pre> 7456 * 7457 * @param str the String to parse, may be {@code null}. 7458 * @return an array of parsed Strings, {@code null} if null String input. 7459 * @since 2.1 7460 */ 7461 public static String[] splitPreserveAllTokens(final String str) { 7462 return splitWorker(str, null, -1, true); 7463 } 7464 7465 /** 7466 * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7467 * alternative to using StringTokenizer. 7468 * 7469 * <p> 7470 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7471 * split use the StrTokenizer class. 7472 * </p> 7473 * 7474 * <p> 7475 * A {@code null} input String returns {@code null}. 7476 * </p> 7477 * 7478 * <pre> 7479 * StringUtils.splitPreserveAllTokens(null, *) = null 7480 * StringUtils.splitPreserveAllTokens("", *) = [] 7481 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 7482 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 7483 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 7484 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 7485 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 7486 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 7487 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 7488 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "a", "b", "c"] 7489 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", "a", "b", "c"] 7490 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", "a", "b", "c", ""] 7491 * </pre> 7492 * 7493 * @param str the String to parse, may be {@code null}. 7494 * @param separatorChar the character used as the delimiter, {@code null} splits on whitespace. 7495 * @return an array of parsed Strings, {@code null} if null String input. 7496 * @since 2.1 7497 */ 7498 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 7499 return splitWorker(str, separatorChar, true); 7500 } 7501 7502 /** 7503 * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an 7504 * alternative to using StringTokenizer. 7505 * 7506 * <p> 7507 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the 7508 * split use the StrTokenizer class. 7509 * </p> 7510 * 7511 * <p> 7512 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7513 * </p> 7514 * 7515 * <pre> 7516 * StringUtils.splitPreserveAllTokens(null, *) = null 7517 * StringUtils.splitPreserveAllTokens("", *) = [] 7518 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 7519 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 7520 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", "def"] 7521 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 7522 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 7523 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 7524 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", "cd", "ef"] 7525 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", "cd", "ef"] 7526 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", "cd", "ef"] 7527 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", "cd", "ef", ""] 7528 * </pre> 7529 * 7530 * @param str the String to parse, may be {@code null}. 7531 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7532 * @return an array of parsed Strings, {@code null} if null String input. 7533 * @since 2.1 7534 */ 7535 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 7536 return splitWorker(str, separatorChars, -1, true); 7537 } 7538 7539 /** 7540 * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent 7541 * separators. 7542 * 7543 * <p> 7544 * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are 7545 * treated as one separator. 7546 * </p> 7547 * 7548 * <p> 7549 * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace. 7550 * </p> 7551 * 7552 * <p> 7553 * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned 7554 * strings (including separator characters). 7555 * </p> 7556 * 7557 * <pre> 7558 * StringUtils.splitPreserveAllTokens(null, *, *) = null 7559 * StringUtils.splitPreserveAllTokens("", *, *) = [] 7560 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 7561 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 7562 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 7563 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 7564 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 7565 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 7566 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 7567 * </pre> 7568 * 7569 * @param str the String to parse, may be {@code null}. 7570 * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace. 7571 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7572 * @return an array of parsed Strings, {@code null} if null String input. 7573 * @since 2.1 7574 */ 7575 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 7576 return splitWorker(str, separatorChars, max, true); 7577 } 7578 7579 /** 7580 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length. 7581 * 7582 * @param str the String to parse, may be {@code null}. 7583 * @param separatorChar the separate character. 7584 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7585 * one separator. 7586 * @return an array of parsed Strings, {@code null} if null String input. 7587 */ 7588 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 7589 // Performance tuned for 2.0 (JDK1.4) 7590 if (str == null) { 7591 return null; 7592 } 7593 final int len = str.length(); 7594 if (len == 0) { 7595 return ArrayUtils.EMPTY_STRING_ARRAY; 7596 } 7597 final List<String> list = new ArrayList<>(); 7598 int i = 0; 7599 int start = 0; 7600 boolean match = false; 7601 boolean lastMatch = false; 7602 while (i < len) { 7603 if (str.charAt(i) == separatorChar) { 7604 if (match || preserveAllTokens) { 7605 list.add(str.substring(start, i)); 7606 match = false; 7607 lastMatch = true; 7608 } 7609 start = ++i; 7610 continue; 7611 } 7612 lastMatch = false; 7613 match = true; 7614 i++; 7615 } 7616 if (match || preserveAllTokens && lastMatch) { 7617 list.add(str.substring(start, i)); 7618 } 7619 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7620 } 7621 7622 /** 7623 * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length. 7624 * 7625 * @param str the String to parse, may be {@code null}. 7626 * @param separatorChars the separate character. 7627 * @param max the maximum number of elements to include in the array. A zero or negative value implies no limit. 7628 * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as 7629 * one separator. 7630 * @return an array of parsed Strings, {@code null} if null String input. 7631 */ 7632 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 7633 // Performance tuned for 2.0 (JDK1.4) 7634 // Direct code is quicker than StringTokenizer. 7635 // Also, StringTokenizer uses isSpace() not isWhitespace() 7636 if (str == null) { 7637 return null; 7638 } 7639 final int len = str.length(); 7640 if (len == 0) { 7641 return ArrayUtils.EMPTY_STRING_ARRAY; 7642 } 7643 final List<String> list = new ArrayList<>(); 7644 int sizePlus1 = 1; 7645 int i = 0; 7646 int start = 0; 7647 boolean match = false; 7648 boolean lastMatch = false; 7649 if (separatorChars == null) { 7650 // Null separator means use whitespace 7651 while (i < len) { 7652 if (Character.isWhitespace(str.charAt(i))) { 7653 if (match || preserveAllTokens) { 7654 lastMatch = true; 7655 if (sizePlus1++ == max) { 7656 i = len; 7657 lastMatch = false; 7658 } 7659 list.add(str.substring(start, i)); 7660 match = false; 7661 } 7662 start = ++i; 7663 continue; 7664 } 7665 lastMatch = false; 7666 match = true; 7667 i++; 7668 } 7669 } else if (separatorChars.length() == 1) { 7670 // Optimize 1 character case 7671 final char sep = separatorChars.charAt(0); 7672 while (i < len) { 7673 if (str.charAt(i) == sep) { 7674 if (match || preserveAllTokens) { 7675 lastMatch = true; 7676 if (sizePlus1++ == max) { 7677 i = len; 7678 lastMatch = false; 7679 } 7680 list.add(str.substring(start, i)); 7681 match = false; 7682 } 7683 start = ++i; 7684 continue; 7685 } 7686 lastMatch = false; 7687 match = true; 7688 i++; 7689 } 7690 } else { 7691 // standard case 7692 while (i < len) { 7693 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 7694 if (match || preserveAllTokens) { 7695 lastMatch = true; 7696 if (sizePlus1++ == max) { 7697 i = len; 7698 lastMatch = false; 7699 } 7700 list.add(str.substring(start, i)); 7701 match = false; 7702 } 7703 start = ++i; 7704 continue; 7705 } 7706 lastMatch = false; 7707 match = true; 7708 i++; 7709 } 7710 } 7711 if (match || preserveAllTokens && lastMatch) { 7712 list.add(str.substring(start, i)); 7713 } 7714 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 7715 } 7716 7717 /** 7718 * Tests if a CharSequence starts with a specified prefix. 7719 * 7720 * <p> 7721 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive. 7722 * </p> 7723 * 7724 * <pre> 7725 * StringUtils.startsWith(null, null) = true 7726 * StringUtils.startsWith(null, "abc") = false 7727 * StringUtils.startsWith("abcdef", null) = false 7728 * StringUtils.startsWith("abcdef", "abc") = true 7729 * StringUtils.startsWith("ABCDEF", "abc") = false 7730 * </pre> 7731 * 7732 * @param str the CharSequence to check, may be null. 7733 * @param prefix the prefix to find, may be null. 7734 * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}. 7735 * @see String#startsWith(String) 7736 * @since 2.4 7737 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 7738 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}. 7739 */ 7740 @Deprecated 7741 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7742 return Strings.CS.startsWith(str, prefix); 7743 } 7744 7745 /** 7746 * Tests if a CharSequence starts with any of the provided case-sensitive prefixes. 7747 * 7748 * <pre> 7749 * StringUtils.startsWithAny(null, null) = false 7750 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 7751 * StringUtils.startsWithAny("abcxyz", null) = false 7752 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true 7753 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 7754 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7755 * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false 7756 * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false 7757 * </pre> 7758 * 7759 * @param sequence the CharSequence to check, may be null. 7760 * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}. 7761 * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with 7762 * any of the provided case-sensitive {@code searchStrings}. 7763 * @see StringUtils#startsWith(CharSequence, CharSequence) 7764 * @since 2.5 7765 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 7766 * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)}. 7767 */ 7768 @Deprecated 7769 public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) { 7770 return Strings.CS.startsWithAny(sequence, searchStrings); 7771 } 7772 7773 /** 7774 * Case-insensitive check if a CharSequence starts with a specified prefix. 7775 * 7776 * <p> 7777 * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive. 7778 * </p> 7779 * 7780 * <pre> 7781 * StringUtils.startsWithIgnoreCase(null, null) = true 7782 * StringUtils.startsWithIgnoreCase(null, "abc") = false 7783 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 7784 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 7785 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 7786 * </pre> 7787 * 7788 * @param str the CharSequence to check, may be null. 7789 * @param prefix the prefix to find, may be null. 7790 * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}. 7791 * @see String#startsWith(String) 7792 * @since 2.4 7793 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 7794 * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}. 7795 */ 7796 @Deprecated 7797 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 7798 return Strings.CI.startsWith(str, prefix); 7799 } 7800 7801 /** 7802 * Strips whitespace from the start and end of a String. 7803 * 7804 * <p> 7805 * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 7806 * </p> 7807 * 7808 * <p> 7809 * A {@code null} input String returns {@code null}. 7810 * </p> 7811 * 7812 * <pre> 7813 * StringUtils.strip(null) = null 7814 * StringUtils.strip("") = "" 7815 * StringUtils.strip(" ") = "" 7816 * StringUtils.strip("abc") = "abc" 7817 * StringUtils.strip(" abc") = "abc" 7818 * StringUtils.strip("abc ") = "abc" 7819 * StringUtils.strip(" abc ") = "abc" 7820 * StringUtils.strip(" ab c ") = "ab c" 7821 * </pre> 7822 * 7823 * @param str the String to remove whitespace from, may be null. 7824 * @return the stripped String, {@code null} if null String input. 7825 */ 7826 public static String strip(final String str) { 7827 return strip(str, null); 7828 } 7829 7830 /** 7831 * 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 7832 * to be controlled. 7833 * 7834 * <p> 7835 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7836 * </p> 7837 * 7838 * <p> 7839 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use 7840 * {@link #strip(String)}. 7841 * </p> 7842 * 7843 * <pre> 7844 * StringUtils.strip(null, *) = null 7845 * StringUtils.strip("", *) = "" 7846 * StringUtils.strip("abc", null) = "abc" 7847 * StringUtils.strip(" abc", null) = "abc" 7848 * StringUtils.strip("abc ", null) = "abc" 7849 * StringUtils.strip(" abc ", null) = "abc" 7850 * StringUtils.strip(" abcyx", "xyz") = " abc" 7851 * </pre> 7852 * 7853 * @param str the String to remove characters from, may be null. 7854 * @param stripChars the characters to remove, null treated as whitespace. 7855 * @return the stripped String, {@code null} if null String input. 7856 */ 7857 public static String strip(String str, final String stripChars) { 7858 str = stripStart(str, stripChars); 7859 return stripEnd(str, stripChars); 7860 } 7861 7862 /** 7863 * Removes diacritics (~= accents) from a string. The case will not be altered. 7864 * <p> 7865 * For instance, 'à' will be replaced by 'a'. 7866 * </p> 7867 * <p> 7868 * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a> 7869 * </p> 7870 * 7871 * <pre> 7872 * StringUtils.stripAccents(null) = null 7873 * StringUtils.stripAccents("") = "" 7874 * StringUtils.stripAccents("control") = "control" 7875 * StringUtils.stripAccents("éclair") = "eclair" 7876 * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3") = "abc123" 7877 * StringUtils.stripAccents("\u00BC \u00BD \u00BE") = "1⁄4 1⁄2 3⁄4" 7878 * </pre> 7879 * <p> 7880 * See also <a href="https://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>. 7881 * </p> 7882 * 7883 * @param input String to be stripped. 7884 * @return input text with diacritics removed. 7885 * @since 3.0 7886 */ 7887 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: 7888 // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 7889 public static String stripAccents(final String input) { 7890 if (isEmpty(input)) { 7891 return input; 7892 } 7893 final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD)); 7894 convertRemainingAccentCharacters(decomposed); 7895 return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY); 7896 } 7897 7898 /** 7899 * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}. 7900 * 7901 * <p> 7902 * 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 7903 * {@code null} array entry will be ignored. 7904 * </p> 7905 * 7906 * <pre> 7907 * StringUtils.stripAll(null) = null 7908 * StringUtils.stripAll([]) = [] 7909 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 7910 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 7911 * </pre> 7912 * 7913 * @param strs the array to remove whitespace from, may be null. 7914 * @return the stripped Strings, {@code null} if null array input. 7915 */ 7916 public static String[] stripAll(final String... strs) { 7917 return stripAll(strs, null); 7918 } 7919 7920 /** 7921 * Strips any of a set of characters from the start and end of every String in an array. 7922 * <p> 7923 * Whitespace is defined by {@link Character#isWhitespace(char)}. 7924 * </p> 7925 * 7926 * <p> 7927 * 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 7928 * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}. 7929 * </p> 7930 * 7931 * <pre> 7932 * StringUtils.stripAll(null, *) = null 7933 * StringUtils.stripAll([], *) = [] 7934 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 7935 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 7936 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 7937 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 7938 * </pre> 7939 * 7940 * @param strs the array to remove characters from, may be null. 7941 * @param stripChars the characters to remove, null treated as whitespace. 7942 * @return the stripped Strings, {@code null} if null array input. 7943 */ 7944 public static String[] stripAll(final String[] strs, final String stripChars) { 7945 final int strsLen = ArrayUtils.getLength(strs); 7946 if (strsLen == 0) { 7947 return strs; 7948 } 7949 return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars)); 7950 } 7951 7952 /** 7953 * Strips any of a set of characters from the end of a String. 7954 * 7955 * <p> 7956 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 7957 * </p> 7958 * 7959 * <p> 7960 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 7961 * </p> 7962 * 7963 * <pre> 7964 * StringUtils.stripEnd(null, *) = null 7965 * StringUtils.stripEnd("", *) = "" 7966 * StringUtils.stripEnd("abc", "") = "abc" 7967 * StringUtils.stripEnd("abc", null) = "abc" 7968 * StringUtils.stripEnd(" abc", null) = " abc" 7969 * StringUtils.stripEnd("abc ", null) = "abc" 7970 * StringUtils.stripEnd(" abc ", null) = " abc" 7971 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 7972 * StringUtils.stripEnd("120.00", ".0") = "12" 7973 * </pre> 7974 * 7975 * @param str the String to remove characters from, may be null. 7976 * @param stripChars the set of characters to remove, null treated as whitespace. 7977 * @return the stripped String, {@code null} if null String input. 7978 */ 7979 public static String stripEnd(final String str, final String stripChars) { 7980 int end = length(str); 7981 if (end == 0) { 7982 return str; 7983 } 7984 if (stripChars == null) { 7985 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 7986 end--; 7987 } 7988 } else if (stripChars.isEmpty()) { 7989 return str; 7990 } else { 7991 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 7992 end--; 7993 } 7994 } 7995 return str.substring(0, end); 7996 } 7997 7998 /** 7999 * Strips any of a set of characters from the start of a String. 8000 * 8001 * <p> 8002 * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string. 8003 * </p> 8004 * 8005 * <p> 8006 * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. 8007 * </p> 8008 * 8009 * <pre> 8010 * StringUtils.stripStart(null, *) = null 8011 * StringUtils.stripStart("", *) = "" 8012 * StringUtils.stripStart("abc", "") = "abc" 8013 * StringUtils.stripStart("abc", null) = "abc" 8014 * StringUtils.stripStart(" abc", null) = "abc" 8015 * StringUtils.stripStart("abc ", null) = "abc " 8016 * StringUtils.stripStart(" abc ", null) = "abc " 8017 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 8018 * </pre> 8019 * 8020 * @param str the String to remove characters from, may be null. 8021 * @param stripChars the characters to remove, null treated as whitespace. 8022 * @return the stripped String, {@code null} if null String input. 8023 */ 8024 public static String stripStart(final String str, final String stripChars) { 8025 final int strLen = length(str); 8026 if (strLen == 0) { 8027 return str; 8028 } 8029 int start = 0; 8030 if (stripChars == null) { 8031 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 8032 start++; 8033 } 8034 } else if (stripChars.isEmpty()) { 8035 return str; 8036 } else { 8037 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 8038 start++; 8039 } 8040 } 8041 return str.substring(start); 8042 } 8043 8044 /** 8045 * Strips whitespace from the start and end of a String returning an empty String if {@code null} input. 8046 * 8047 * <p> 8048 * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8049 * </p> 8050 * 8051 * <pre> 8052 * StringUtils.stripToEmpty(null) = "" 8053 * StringUtils.stripToEmpty("") = "" 8054 * StringUtils.stripToEmpty(" ") = "" 8055 * StringUtils.stripToEmpty("abc") = "abc" 8056 * StringUtils.stripToEmpty(" abc") = "abc" 8057 * StringUtils.stripToEmpty("abc ") = "abc" 8058 * StringUtils.stripToEmpty(" abc ") = "abc" 8059 * StringUtils.stripToEmpty(" ab c ") = "ab c" 8060 * </pre> 8061 * 8062 * @param str the String to be stripped, may be null. 8063 * @return the trimmed String, or an empty String if {@code null} input. 8064 * @since 2.0 8065 */ 8066 public static String stripToEmpty(final String str) { 8067 return str == null ? EMPTY : strip(str, null); 8068 } 8069 8070 /** 8071 * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip. 8072 * 8073 * <p> 8074 * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}. 8075 * </p> 8076 * 8077 * <pre> 8078 * StringUtils.stripToNull(null) = null 8079 * StringUtils.stripToNull("") = null 8080 * StringUtils.stripToNull(" ") = null 8081 * StringUtils.stripToNull("abc") = "abc" 8082 * StringUtils.stripToNull(" abc") = "abc" 8083 * StringUtils.stripToNull("abc ") = "abc" 8084 * StringUtils.stripToNull(" abc ") = "abc" 8085 * StringUtils.stripToNull(" ab c ") = "ab c" 8086 * </pre> 8087 * 8088 * @param str the String to be stripped, may be null. 8089 * @return the stripped String, {@code null} if whitespace, empty or null String input. 8090 * @since 2.0 8091 */ 8092 public static String stripToNull(String str) { 8093 if (str == null) { 8094 return null; 8095 } 8096 str = strip(str, null); 8097 return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here 8098 } 8099 8100 /** 8101 * Gets a substring from the specified String avoiding exceptions. 8102 * 8103 * <p> 8104 * A negative start position can be used to start {@code n} characters from the end of the String. 8105 * </p> 8106 * 8107 * <p> 8108 * A {@code null} String will return {@code null}. An empty ("") String will return "". 8109 * </p> 8110 * 8111 * <pre> 8112 * StringUtils.substring(null, *) = null 8113 * StringUtils.substring("", *) = "" 8114 * StringUtils.substring("abc", 0) = "abc" 8115 * StringUtils.substring("abc", 2) = "c" 8116 * StringUtils.substring("abc", 4) = "" 8117 * StringUtils.substring("abc", -2) = "bc" 8118 * StringUtils.substring("abc", -4) = "abc" 8119 * </pre> 8120 * 8121 * @param str the String to get the substring from, may be null. 8122 * @param start the position to start from, negative means count back from the end of the String by this many characters. 8123 * @return substring from start position, {@code null} if null String input. 8124 */ 8125 public static String substring(final String str, int start) { 8126 if (str == null) { 8127 return null; 8128 } 8129 // handle negatives, which means last n characters 8130 if (start < 0) { 8131 start = str.length() + start; // remember start is negative 8132 } 8133 if (start < 0) { 8134 start = 0; 8135 } 8136 if (start > str.length()) { 8137 return EMPTY; 8138 } 8139 return str.substring(start); 8140 } 8141 8142 /** 8143 * Gets a substring from the specified String avoiding exceptions. 8144 * 8145 * <p> 8146 * A negative start position can be used to start/end {@code n} characters from the end of the String. 8147 * </p> 8148 * 8149 * <p> 8150 * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is 8151 * 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 8152 * relative to the end of the String. 8153 * </p> 8154 * 8155 * <p> 8156 * If {@code start} is not strictly to the left of {@code end}, "" is returned. 8157 * </p> 8158 * 8159 * <pre> 8160 * StringUtils.substring(null, *, *) = null 8161 * StringUtils.substring("", * , *) = ""; 8162 * StringUtils.substring("abc", 0, 2) = "ab" 8163 * StringUtils.substring("abc", 2, 0) = "" 8164 * StringUtils.substring("abc", 2, 4) = "c" 8165 * StringUtils.substring("abc", 4, 6) = "" 8166 * StringUtils.substring("abc", 2, 2) = "" 8167 * StringUtils.substring("abc", -2, -1) = "b" 8168 * StringUtils.substring("abc", -4, 2) = "ab" 8169 * </pre> 8170 * 8171 * @param str the String to get the substring from, may be null. 8172 * @param start the position to start from, negative means count back from the end of the String by this many characters. 8173 * @param end the position to end at (exclusive), negative means count back from the end of the String by this many characters. 8174 * @return substring from start position to end position, {@code null} if null String input. 8175 */ 8176 public static String substring(final String str, int start, int end) { 8177 if (str == null) { 8178 return null; 8179 } 8180 // handle negatives 8181 if (end < 0) { 8182 end = str.length() + end; // remember end is negative 8183 } 8184 if (start < 0) { 8185 start = str.length() + start; // remember start is negative 8186 } 8187 // check length next 8188 if (end > str.length()) { 8189 end = str.length(); 8190 } 8191 // if start is greater than end, return "" 8192 if (start > end) { 8193 return EMPTY; 8194 } 8195 if (start < 0) { 8196 start = 0; 8197 } 8198 if (end < 0) { 8199 end = 0; 8200 } 8201 return str.substring(start, end); 8202 } 8203 8204 /** 8205 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8206 * 8207 * <p> 8208 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8209 * </p> 8210 * 8211 * <p> 8212 * If nothing is found, the empty string is returned. 8213 * </p> 8214 * 8215 * <pre> 8216 * StringUtils.substringAfter(null, *) = null 8217 * StringUtils.substringAfter("", *) = "" 8218 * StringUtils.substringAfter("abc", 'a') = "bc" 8219 * StringUtils.substringAfter("abcba", 'b') = "cba" 8220 * StringUtils.substringAfter("abc", 'c') = "" 8221 * StringUtils.substringAfter("abc", 'd') = "" 8222 * StringUtils.substringAfter(" abc", 32) = "abc" 8223 * </pre> 8224 * 8225 * @param str the String to get a substring from, may be null. 8226 * @param find the character (Unicode code point) to find. 8227 * @return the substring after the first occurrence of the specified character, {@code null} if null String input. 8228 * @since 3.11 8229 */ 8230 public static String substringAfter(final String str, final int find) { 8231 if (isEmpty(str)) { 8232 return str; 8233 } 8234 final int pos = str.indexOf(find); 8235 if (pos == INDEX_NOT_FOUND) { 8236 return EMPTY; 8237 } 8238 return str.substring(pos + 1); 8239 } 8240 8241 /** 8242 * Gets the substring after the first occurrence of a separator. The separator is not returned. 8243 * 8244 * <p> 8245 * 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 8246 * empty string if the input string is not {@code null}. 8247 * </p> 8248 * 8249 * <p> 8250 * If nothing is found, the empty string is returned. 8251 * </p> 8252 * 8253 * <pre> 8254 * StringUtils.substringAfter(null, *) = null 8255 * StringUtils.substringAfter("", *) = "" 8256 * StringUtils.substringAfter(*, null) = "" 8257 * StringUtils.substringAfter("abc", "a") = "bc" 8258 * StringUtils.substringAfter("abcba", "b") = "cba" 8259 * StringUtils.substringAfter("abc", "c") = "" 8260 * StringUtils.substringAfter("abc", "d") = "" 8261 * StringUtils.substringAfter("abc", "") = "abc" 8262 * </pre> 8263 * 8264 * @param str the String to get a substring from, may be null. 8265 * @param find the String to find, may be null. 8266 * @return the substring after the first occurrence of the specified string, {@code null} if null String input. 8267 * @since 2.0 8268 */ 8269 public static String substringAfter(final String str, final String find) { 8270 if (isEmpty(str)) { 8271 return str; 8272 } 8273 if (find == null) { 8274 return EMPTY; 8275 } 8276 final int pos = str.indexOf(find); 8277 if (pos == INDEX_NOT_FOUND) { 8278 return EMPTY; 8279 } 8280 return str.substring(pos + find.length()); 8281 } 8282 8283 /** 8284 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8285 * 8286 * <p> 8287 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8288 * </p> 8289 * 8290 * <p> 8291 * If nothing is found, the empty string is returned. 8292 * </p> 8293 * 8294 * <pre> 8295 * StringUtils.substringAfterLast(null, *) = null 8296 * StringUtils.substringAfterLast("", *) = "" 8297 * StringUtils.substringAfterLast("abc", 'a') = "bc" 8298 * StringUtils.substringAfterLast(" bc", 32) = "bc" 8299 * StringUtils.substringAfterLast("abcba", 'b') = "a" 8300 * StringUtils.substringAfterLast("abc", 'c') = "" 8301 * StringUtils.substringAfterLast("a", 'a') = "" 8302 * StringUtils.substringAfterLast("a", 'z') = "" 8303 * </pre> 8304 * 8305 * @param str the String to get a substring from, may be null. 8306 * @param find the character (Unicode code point) to find. 8307 * @return the substring after the last occurrence of the specified character, {@code null} if null String input. 8308 * @since 3.11 8309 */ 8310 public static String substringAfterLast(final String str, final int find) { 8311 if (isEmpty(str)) { 8312 return str; 8313 } 8314 final int pos = str.lastIndexOf(find); 8315 if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) { 8316 return EMPTY; 8317 } 8318 return str.substring(pos + 1); 8319 } 8320 8321 /** 8322 * Gets the substring after the last occurrence of a separator. The separator is not returned. 8323 * 8324 * <p> 8325 * 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 8326 * return the empty string if the input string is not {@code null}. 8327 * </p> 8328 * 8329 * <p> 8330 * If nothing is found, the empty string is returned. 8331 * </p> 8332 * 8333 * <pre> 8334 * StringUtils.substringAfterLast(null, *) = null 8335 * StringUtils.substringAfterLast("", *) = "" 8336 * StringUtils.substringAfterLast(*, "") = "" 8337 * StringUtils.substringAfterLast(*, null) = "" 8338 * StringUtils.substringAfterLast("abc", "a") = "bc" 8339 * StringUtils.substringAfterLast("abcba", "b") = "a" 8340 * StringUtils.substringAfterLast("abc", "c") = "" 8341 * StringUtils.substringAfterLast("a", "a") = "" 8342 * StringUtils.substringAfterLast("a", "z") = "" 8343 * </pre> 8344 * 8345 * @param str the String to get a substring from, may be null. 8346 * @param find the String to find, may be null. 8347 * @return the substring after the last occurrence of the specified string, {@code null} if null String input. 8348 * @since 2.0 8349 */ 8350 public static String substringAfterLast(final String str, final String find) { 8351 if (isEmpty(str)) { 8352 return str; 8353 } 8354 if (isEmpty(find)) { 8355 return EMPTY; 8356 } 8357 final int pos = str.lastIndexOf(find); 8358 if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) { 8359 return EMPTY; 8360 } 8361 return str.substring(pos + find.length()); 8362 } 8363 8364 /** 8365 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8366 * 8367 * <p> 8368 * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. 8369 * </p> 8370 * 8371 * <p> 8372 * If nothing is found, the string input is returned. 8373 * </p> 8374 * 8375 * <pre> 8376 * StringUtils.substringBefore(null, *) = null 8377 * StringUtils.substringBefore("", *) = "" 8378 * StringUtils.substringBefore("abc", 'a') = "" 8379 * StringUtils.substringBefore("abcba", 'b') = "a" 8380 * StringUtils.substringBefore("abc", 'c') = "ab" 8381 * StringUtils.substringBefore("abc", 'd') = "abc" 8382 * </pre> 8383 * 8384 * @param str the String to get a substring from, may be null. 8385 * @param find the character (Unicode code point) to find. 8386 * @return the substring before the first occurrence of the specified character, {@code null} if null String input. 8387 * @since 3.12.0 8388 */ 8389 public static String substringBefore(final String str, final int find) { 8390 if (isEmpty(str)) { 8391 return str; 8392 } 8393 final int pos = str.indexOf(find); 8394 if (pos == INDEX_NOT_FOUND) { 8395 return str; 8396 } 8397 return str.substring(0, pos); 8398 } 8399 8400 /** 8401 * Gets the substring before the first occurrence of a separator. The separator is not returned. 8402 * 8403 * <p> 8404 * 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 8405 * input string. 8406 * </p> 8407 * 8408 * <p> 8409 * If nothing is found, the string input is returned. 8410 * </p> 8411 * 8412 * <pre> 8413 * StringUtils.substringBefore(null, *) = null 8414 * StringUtils.substringBefore("", *) = "" 8415 * StringUtils.substringBefore("abc", "a") = "" 8416 * StringUtils.substringBefore("abcba", "b") = "a" 8417 * StringUtils.substringBefore("abc", "c") = "ab" 8418 * StringUtils.substringBefore("abc", "d") = "abc" 8419 * StringUtils.substringBefore("abc", "") = "" 8420 * StringUtils.substringBefore("abc", null) = "abc" 8421 * </pre> 8422 * 8423 * @param str the String to get a substring from, may be null. 8424 * @param find the String to find, may be null. 8425 * @return the substring before the first occurrence of the specified string, {@code null} if null String input. 8426 * @since 2.0 8427 */ 8428 public static String substringBefore(final String str, final String find) { 8429 if (isEmpty(str) || find == null) { 8430 return str; 8431 } 8432 if (find.isEmpty()) { 8433 return EMPTY; 8434 } 8435 final int pos = str.indexOf(find); 8436 if (pos == INDEX_NOT_FOUND) { 8437 return str; 8438 } 8439 return str.substring(0, pos); 8440 } 8441 8442 /** 8443 * Gets the substring before the last occurrence of a separator. The separator is not returned. 8444 * 8445 * <p> 8446 * 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 8447 * return the input string. 8448 * </p> 8449 * 8450 * <p> 8451 * If nothing is found, the string input is returned. 8452 * </p> 8453 * 8454 * <pre> 8455 * StringUtils.substringBeforeLast(null, *) = null 8456 * StringUtils.substringBeforeLast("", *) = "" 8457 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 8458 * StringUtils.substringBeforeLast("abc", "c") = "ab" 8459 * StringUtils.substringBeforeLast("a", "a") = "" 8460 * StringUtils.substringBeforeLast("a", "z") = "a" 8461 * StringUtils.substringBeforeLast("a", null) = "a" 8462 * StringUtils.substringBeforeLast("a", "") = "a" 8463 * </pre> 8464 * 8465 * @param str the String to get a substring from, may be null. 8466 * @param find the String to find, may be null. 8467 * @return the substring before the last occurrence of the specified string, {@code null} if null String input. 8468 * @since 2.0 8469 */ 8470 public static String substringBeforeLast(final String str, final String find) { 8471 if (isEmpty(str) || isEmpty(find)) { 8472 return str; 8473 } 8474 final int pos = str.lastIndexOf(find); 8475 if (pos == INDEX_NOT_FOUND) { 8476 return str; 8477 } 8478 return str.substring(0, pos); 8479 } 8480 8481 /** 8482 * Gets the String that is nested in between two instances of the same String. 8483 * 8484 * <p> 8485 * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}. 8486 * </p> 8487 * 8488 * <pre> 8489 * StringUtils.substringBetween(null, *) = null 8490 * StringUtils.substringBetween("", "") = "" 8491 * StringUtils.substringBetween("", "tag") = null 8492 * StringUtils.substringBetween("tagabctag", null) = null 8493 * StringUtils.substringBetween("tagabctag", "") = "" 8494 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 8495 * </pre> 8496 * 8497 * @param str the String containing the substring, may be null. 8498 * @param tag the String before and after the substring, may be null. 8499 * @return the substring, {@code null} if no match. 8500 * @since 2.0 8501 */ 8502 public static String substringBetween(final String str, final String tag) { 8503 return substringBetween(str, tag, tag); 8504 } 8505 8506 /** 8507 * Gets the String that is nested in between two Strings. Only the first match is returned. 8508 * 8509 * <p> 8510 * 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 8511 * empty string. 8512 * </p> 8513 * 8514 * <pre> 8515 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 8516 * StringUtils.substringBetween(null, *, *) = null 8517 * StringUtils.substringBetween(*, null, *) = null 8518 * StringUtils.substringBetween(*, *, null) = null 8519 * StringUtils.substringBetween("", "", "") = "" 8520 * StringUtils.substringBetween("", "", "]") = null 8521 * StringUtils.substringBetween("", "[", "]") = null 8522 * StringUtils.substringBetween("yabcz", "", "") = "" 8523 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 8524 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 8525 * </pre> 8526 * 8527 * @param str the String containing the substring, may be null. 8528 * @param open the String before the substring, may be null. 8529 * @param close the String after the substring, may be null. 8530 * @return the substring, {@code null} if no match. 8531 * @since 2.0 8532 */ 8533 public static String substringBetween(final String str, final String open, final String close) { 8534 if (!ObjectUtils.allNotNull(str, open, close)) { 8535 return null; 8536 } 8537 final int start = str.indexOf(open); 8538 if (start != INDEX_NOT_FOUND) { 8539 final int end = str.indexOf(close, start + open.length()); 8540 if (end != INDEX_NOT_FOUND) { 8541 return str.substring(start + open.length(), end); 8542 } 8543 } 8544 return null; 8545 } 8546 8547 /** 8548 * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array. 8549 * 8550 * <p> 8551 * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns 8552 * {@code null} (no match). 8553 * </p> 8554 * 8555 * <pre> 8556 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 8557 * StringUtils.substringsBetween(null, *, *) = null 8558 * StringUtils.substringsBetween(*, null, *) = null 8559 * StringUtils.substringsBetween(*, *, null) = null 8560 * StringUtils.substringsBetween("", "[", "]") = [] 8561 * </pre> 8562 * 8563 * @param str the String containing the substrings, null returns null, empty returns empty. 8564 * @param open the String identifying the start of the substring, empty returns null. 8565 * @param close the String identifying the end of the substring, empty returns null. 8566 * @return a String Array of substrings, or {@code null} if no match. 8567 * @since 2.3 8568 */ 8569 public static String[] substringsBetween(final String str, final String open, final String close) { 8570 if (str == null || isEmpty(open) || isEmpty(close)) { 8571 return null; 8572 } 8573 final int strLen = str.length(); 8574 if (strLen == 0) { 8575 return ArrayUtils.EMPTY_STRING_ARRAY; 8576 } 8577 final int closeLen = close.length(); 8578 final int openLen = open.length(); 8579 final List<String> list = new ArrayList<>(); 8580 int pos = 0; 8581 while (pos < strLen - closeLen) { 8582 int start = str.indexOf(open, pos); 8583 if (start < 0) { 8584 break; 8585 } 8586 start += openLen; 8587 final int end = str.indexOf(close, start); 8588 if (end < 0) { 8589 break; 8590 } 8591 list.add(str.substring(start, end)); 8592 pos = end + closeLen; 8593 } 8594 if (list.isEmpty()) { 8595 return null; 8596 } 8597 return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); 8598 } 8599 8600 /** 8601 * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case. 8602 * 8603 * <ul> 8604 * <li>Upper case character converts to Lower case</li> 8605 * <li>Title case character converts to Lower case</li> 8606 * <li>Lower case character converts to Upper case</li> 8607 * </ul> 8608 * 8609 * <p> 8610 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}. 8611 * </p> 8612 * 8613 * <pre> 8614 * StringUtils.swapCase(null) = null 8615 * StringUtils.swapCase("") = "" 8616 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 8617 * </pre> 8618 * 8619 * <p> 8620 * 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 8621 * functionality is available in org.apache.commons.lang3.text.WordUtils. 8622 * </p> 8623 * 8624 * @param str the String to swap case, may be null. 8625 * @return the changed String, {@code null} if null String input. 8626 */ 8627 public static String swapCase(final String str) { 8628 if (isEmpty(str)) { 8629 return str; 8630 } 8631 final int strLen = str.length(); 8632 final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array 8633 int outOffset = 0; 8634 for (int i = 0; i < strLen;) { 8635 final int oldCodepoint = str.codePointAt(i); 8636 final int newCodePoint; 8637 if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) { 8638 newCodePoint = Character.toLowerCase(oldCodepoint); 8639 } else if (Character.isLowerCase(oldCodepoint)) { 8640 newCodePoint = Character.toUpperCase(oldCodepoint); 8641 } else { 8642 newCodePoint = oldCodepoint; 8643 } 8644 newCodePoints[outOffset++] = newCodePoint; 8645 i += Character.charCount(newCodePoint); 8646 } 8647 return new String(newCodePoints, 0, outOffset); 8648 } 8649 8650 /** 8651 * Converts a {@link CharSequence} into an array of code points. 8652 * 8653 * <p> 8654 * 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 8655 * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is. 8656 * </p> 8657 * 8658 * <pre> 8659 * StringUtils.toCodePoints(null) = null 8660 * StringUtils.toCodePoints("") = [] // empty array 8661 * </pre> 8662 * 8663 * @param cs the character sequence to convert. 8664 * @return an array of code points. 8665 * @since 3.6 8666 */ 8667 public static int[] toCodePoints(final CharSequence cs) { 8668 if (cs == null) { 8669 return null; 8670 } 8671 if (cs.length() == 0) { 8672 return ArrayUtils.EMPTY_INT_ARRAY; 8673 } 8674 return cs.toString().codePoints().toArray(); 8675 } 8676 8677 /** 8678 * Converts a {@code byte[]} to a String using the specified character encoding. 8679 * 8680 * @param bytes the byte array to read from. 8681 * @param charset the encoding to use, if null then use the platform default. 8682 * @return a new String. 8683 * @throws NullPointerException if {@code bytes} is null 8684 * @since 3.2 8685 * @since 3.3 No longer throws {@link UnsupportedEncodingException}. 8686 */ 8687 public static String toEncodedString(final byte[] bytes, final Charset charset) { 8688 return new String(bytes, Charsets.toCharset(charset)); 8689 } 8690 8691 /** 8692 * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner. 8693 * 8694 * @param source A source String or null. 8695 * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null. 8696 * @since 3.10 8697 */ 8698 public static String toRootLowerCase(final String source) { 8699 return source == null ? null : source.toLowerCase(Locale.ROOT); 8700 } 8701 8702 /** 8703 * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner. 8704 * 8705 * @param source A source String or null. 8706 * @return the given source String as an upper-case using the {@link Locale#ROOT} locale or null. 8707 * @since 3.10 8708 */ 8709 public static String toRootUpperCase(final String source) { 8710 return source == null ? null : source.toUpperCase(Locale.ROOT); 8711 } 8712 8713 /** 8714 * Converts a {@code byte[]} to a String using the specified character encoding. 8715 * 8716 * @param bytes the byte array to read from. 8717 * @param charsetName the encoding to use, if null then use the platform default. 8718 * @return a new String. 8719 * @throws NullPointerException if the input is null. 8720 * @since 3.1 8721 * @deprecated Use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code. 8722 */ 8723 @Deprecated 8724 public static String toString(final byte[] bytes, final String charsetName) { 8725 return new String(bytes, Charsets.toCharset(charsetName)); 8726 } 8727 8728 /** 8729 * Removes control characters (char <= 32) from both ends of this String, handling {@code null} by returning {@code null}. 8730 * 8731 * <p> 8732 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #strip(String)}. 8733 * </p> 8734 * 8735 * <p> 8736 * To trim your choice of characters, use the {@link #strip(String, String)} methods. 8737 * </p> 8738 * 8739 * <pre> 8740 * StringUtils.trim(null) = null 8741 * StringUtils.trim("") = "" 8742 * StringUtils.trim(" ") = "" 8743 * StringUtils.trim("abc") = "abc" 8744 * StringUtils.trim(" abc ") = "abc" 8745 * </pre> 8746 * 8747 * @param str the String to be trimmed, may be null. 8748 * @return the trimmed string, {@code null} if null String input. 8749 */ 8750 public static String trim(final String str) { 8751 return str == null ? null : str.trim(); 8752 } 8753 8754 /** 8755 * 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 8756 * it is {@code null}. 8757 * 8758 * <p> 8759 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToEmpty(String)}. 8760 * </p> 8761 * 8762 * <pre> 8763 * StringUtils.trimToEmpty(null) = "" 8764 * StringUtils.trimToEmpty("") = "" 8765 * StringUtils.trimToEmpty(" ") = "" 8766 * StringUtils.trimToEmpty("abc") = "abc" 8767 * StringUtils.trimToEmpty(" abc ") = "abc" 8768 * </pre> 8769 * 8770 * @param str the String to be trimmed, may be null. 8771 * @return the trimmed String, or an empty String if {@code null} input. 8772 * @since 2.0 8773 */ 8774 public static String trimToEmpty(final String str) { 8775 return str == null ? EMPTY : str.trim(); 8776 } 8777 8778 /** 8779 * 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 8780 * {@code null}. 8781 * 8782 * <p> 8783 * The String is trimmed using {@link String#trim()}. Trim removes start and end characters <= 32. To strip whitespace use {@link #stripToNull(String)}. 8784 * </p> 8785 * 8786 * <pre> 8787 * StringUtils.trimToNull(null) = null 8788 * StringUtils.trimToNull("") = null 8789 * StringUtils.trimToNull(" ") = null 8790 * StringUtils.trimToNull("abc") = "abc" 8791 * StringUtils.trimToNull(" abc ") = "abc" 8792 * </pre> 8793 * 8794 * @param str the String to be trimmed, may be null. 8795 * @return the trimmed String, {@code null} if only chars <= 32, empty or null String input. 8796 * @since 2.0 8797 */ 8798 public static String trimToNull(final String str) { 8799 final String ts = trim(str); 8800 return isEmpty(ts) ? null : ts; 8801 } 8802 8803 /** 8804 * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for". 8805 * 8806 * <p> 8807 * Specifically: 8808 * </p> 8809 * <ul> 8810 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 8811 * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li> 8812 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8813 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 8814 * </ul> 8815 * 8816 * <pre> 8817 * StringUtils.truncate(null, 0) = null 8818 * StringUtils.truncate(null, 2) = null 8819 * StringUtils.truncate("", 4) = "" 8820 * StringUtils.truncate("abcdefg", 4) = "abcd" 8821 * StringUtils.truncate("abcdefg", 6) = "abcdef" 8822 * StringUtils.truncate("abcdefg", 7) = "abcdefg" 8823 * StringUtils.truncate("abcdefg", 8) = "abcdefg" 8824 * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException 8825 * </pre> 8826 * 8827 * @param str the String to truncate, may be null. 8828 * @param maxWidth maximum length of result String, must be non-negative. 8829 * @return truncated String, {@code null} if null String input. 8830 * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}. 8831 * @since 3.5 8832 */ 8833 public static String truncate(final String str, final int maxWidth) { 8834 return truncate(str, 0, maxWidth); 8835 } 8836 8837 /** 8838 * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all". 8839 * 8840 * <p> 8841 * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset. 8842 * </p> 8843 * 8844 * <p> 8845 * Specifically: 8846 * </p> 8847 * <ul> 8848 * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li> 8849 * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li> 8850 * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8851 * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li> 8852 * <li>In no case will it return a String of length greater than {@code maxWidth}.</li> 8853 * </ul> 8854 * 8855 * <pre> 8856 * StringUtils.truncate(null, 0, 0) = null 8857 * StringUtils.truncate(null, 2, 4) = null 8858 * StringUtils.truncate("", 0, 10) = "" 8859 * StringUtils.truncate("", 2, 10) = "" 8860 * StringUtils.truncate("abcdefghij", 0, 3) = "abc" 8861 * StringUtils.truncate("abcdefghij", 5, 6) = "fghij" 8862 * StringUtils.truncate("raspberry peach", 10, 15) = "peach" 8863 * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" 8864 * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException 8865 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException 8866 * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException 8867 * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" 8868 * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" 8869 * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" 8870 * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" 8871 * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" 8872 * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" 8873 * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" 8874 * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" 8875 * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" 8876 * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" 8877 * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" 8878 * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" 8879 * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" 8880 * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" 8881 * StringUtils.truncate("abcdefghijklmno", 15, 1) = "" 8882 * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" 8883 * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" 8884 * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException 8885 * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException 8886 * </pre> 8887 * 8888 * @param str the String to truncate, may be null. 8889 * @param offset left edge of source String. 8890 * @param maxWidth maximum length of result String, must be non-negative. 8891 * @return truncated String, {@code null} if null String input. 8892 * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}. 8893 * @since 3.5 8894 */ 8895 public static String truncate(final String str, final int offset, final int maxWidth) { 8896 if (offset < 0) { 8897 throw new IllegalArgumentException("offset cannot be negative"); 8898 } 8899 if (maxWidth < 0) { 8900 throw new IllegalArgumentException("maxWidth cannot be negative"); 8901 } 8902 if (str == null) { 8903 return null; 8904 } 8905 final int len = str.length(); 8906 final int start = Math.min(offset, len); 8907 final int end = offset > len - maxWidth ? len : offset + maxWidth; 8908 return str.substring(start, Math.min(end, len)); 8909 } 8910 8911 /** 8912 * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed. 8913 * 8914 * <p> 8915 * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}. 8916 * </p> 8917 * 8918 * <pre> 8919 * StringUtils.uncapitalize(null) = null 8920 * StringUtils.uncapitalize("") = "" 8921 * StringUtils.uncapitalize("cat") = "cat" 8922 * StringUtils.uncapitalize("Cat") = "cat" 8923 * StringUtils.uncapitalize("CAT") = "cAT" 8924 * </pre> 8925 * 8926 * @param str the String to uncapitalize, may be null. 8927 * @return the uncapitalized String, {@code null} if null String input. 8928 * @see org.apache.commons.text.WordUtils#uncapitalize(String) 8929 * @see #capitalize(String) 8930 * @since 2.0 8931 */ 8932 public static String uncapitalize(final String str) { 8933 final int strLen = length(str); 8934 if (strLen == 0) { 8935 return str; 8936 } 8937 final int firstCodePoint = str.codePointAt(0); 8938 final int newCodePoint = Character.toLowerCase(firstCodePoint); 8939 if (firstCodePoint == newCodePoint) { 8940 // already uncapitalized 8941 return str; 8942 } 8943 final int[] newCodePoints = str.codePoints().toArray(); 8944 newCodePoints[0] = newCodePoint; // copy the first code point 8945 return new String(newCodePoints, 0, newCodePoints.length); 8946 } 8947 8948 /** 8949 * Unwraps a given string from a character. 8950 * 8951 * <pre> 8952 * StringUtils.unwrap(null, null) = null 8953 * StringUtils.unwrap(null, '\0') = null 8954 * StringUtils.unwrap(null, '1') = null 8955 * StringUtils.unwrap("a", 'a') = "a" 8956 * StringUtils.unwrap("aa", 'a') = "" 8957 * StringUtils.unwrap("\'abc\'", '\'') = "abc" 8958 * StringUtils.unwrap("AABabcBAA", 'A') = "ABabcBA" 8959 * StringUtils.unwrap("A", '#') = "A" 8960 * StringUtils.unwrap("#A", '#') = "#A" 8961 * StringUtils.unwrap("A#", '#') = "A#" 8962 * </pre> 8963 * 8964 * @param str the String to be unwrapped, can be null. 8965 * @param wrapChar the character used to unwrap. 8966 * @return unwrapped String or the original string if it is not quoted properly with the wrapChar. 8967 * @since 3.6 8968 */ 8969 public static String unwrap(final String str, final char wrapChar) { 8970 if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) { 8971 return str; 8972 } 8973 if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) { 8974 final int startIndex = 0; 8975 final int endIndex = str.length() - 1; 8976 return str.substring(startIndex + 1, endIndex); 8977 } 8978 return str; 8979 } 8980 8981 /** 8982 * Unwraps a given string from another string. 8983 * 8984 * <pre> 8985 * StringUtils.unwrap(null, null) = null 8986 * StringUtils.unwrap(null, "") = null 8987 * StringUtils.unwrap(null, "1") = null 8988 * StringUtils.unwrap("a", "a") = "a" 8989 * StringUtils.unwrap("aa", "a") = "" 8990 * StringUtils.unwrap("\'abc\'", "\'") = "abc" 8991 * StringUtils.unwrap("\"abc\"", "\"") = "abc" 8992 * StringUtils.unwrap("AABabcBAA", "AA") = "BabcB" 8993 * StringUtils.unwrap("A", "#") = "A" 8994 * StringUtils.unwrap("#A", "#") = "#A" 8995 * StringUtils.unwrap("A#", "#") = "A#" 8996 * </pre> 8997 * 8998 * @param str the String to be unwrapped, can be null. 8999 * @param wrapToken the String used to unwrap. 9000 * @return unwrapped String or the original string if it is not quoted properly with the wrapToken. 9001 * @since 3.6 9002 */ 9003 public static String unwrap(final String str, final String wrapToken) { 9004 if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) { 9005 return str; 9006 } 9007 if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) { 9008 return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken)); 9009 } 9010 return str; 9011 } 9012 9013 /** 9014 * Converts a String to upper case as per {@link String#toUpperCase()}. 9015 * 9016 * <p> 9017 * A {@code null} input String returns {@code null}. 9018 * </p> 9019 * 9020 * <pre> 9021 * StringUtils.upperCase(null) = null 9022 * StringUtils.upperCase("") = "" 9023 * StringUtils.upperCase("aBc") = "ABC" 9024 * </pre> 9025 * 9026 * <p> 9027 * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale. 9028 * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g. 9029 * {@link Locale#ENGLISH}). 9030 * </p> 9031 * 9032 * @param str the String to upper case, may be null. 9033 * @return the upper-cased String, {@code null} if null String input. 9034 */ 9035 public static String upperCase(final String str) { 9036 if (str == null) { 9037 return null; 9038 } 9039 return str.toUpperCase(); 9040 } 9041 9042 /** 9043 * Converts a String to upper case as per {@link String#toUpperCase(Locale)}. 9044 * 9045 * <p> 9046 * A {@code null} input String returns {@code null}. 9047 * </p> 9048 * 9049 * <pre> 9050 * StringUtils.upperCase(null, Locale.ENGLISH) = null 9051 * StringUtils.upperCase("", Locale.ENGLISH) = "" 9052 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 9053 * </pre> 9054 * 9055 * @param str the String to upper case, may be null. 9056 * @param locale the locale that defines the case transformation rules, must not be null. 9057 * @return the upper-cased String, {@code null} if null String input. 9058 * @since 2.5 9059 */ 9060 public static String upperCase(final String str, final Locale locale) { 9061 if (str == null) { 9062 return null; 9063 } 9064 return str.toUpperCase(LocaleUtils.toLocale(locale)); 9065 } 9066 9067 /** 9068 * Returns the string representation of the {@code char} array or null. 9069 * 9070 * @param value the character array. 9071 * @return a String or null. 9072 * @see String#valueOf(char[]) 9073 * @since 3.9 9074 */ 9075 public static String valueOf(final char[] value) { 9076 return value == null ? null : String.valueOf(value); 9077 } 9078 9079 /** 9080 * Wraps a string with a char. 9081 * 9082 * <pre> 9083 * StringUtils.wrap(null, *) = null 9084 * StringUtils.wrap("", *) = "" 9085 * StringUtils.wrap("ab", '\0') = "ab" 9086 * StringUtils.wrap("ab", 'x') = "xabx" 9087 * StringUtils.wrap("ab", '\'') = "'ab'" 9088 * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\"" 9089 * </pre> 9090 * 9091 * @param str the string to be wrapped, may be {@code null}. 9092 * @param wrapWith the char that will wrap {@code str}. 9093 * @return the wrapped string, or {@code null} if {@code str == null}. 9094 * @since 3.4 9095 */ 9096 public static String wrap(final String str, final char wrapWith) { 9097 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9098 return str; 9099 } 9100 return wrapWith + str + wrapWith; 9101 } 9102 9103 /** 9104 * Wraps a String with another String. 9105 * 9106 * <p> 9107 * A {@code null} input String returns {@code null}. 9108 * </p> 9109 * 9110 * <pre> 9111 * StringUtils.wrap(null, *) = null 9112 * StringUtils.wrap("", *) = "" 9113 * StringUtils.wrap("ab", null) = "ab" 9114 * StringUtils.wrap("ab", "x") = "xabx" 9115 * StringUtils.wrap("ab", "\"") = "\"ab\"" 9116 * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\"" 9117 * StringUtils.wrap("ab", "'") = "'ab'" 9118 * StringUtils.wrap("'abcd'", "'") = "''abcd''" 9119 * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'" 9120 * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\"" 9121 * </pre> 9122 * 9123 * @param str the String to be wrapper, may be null. 9124 * @param wrapWith the String that will wrap str. 9125 * @return wrapped String, {@code null} if null String input. 9126 * @since 3.4 9127 */ 9128 public static String wrap(final String str, final String wrapWith) { 9129 if (isEmpty(str) || isEmpty(wrapWith)) { 9130 return str; 9131 } 9132 return wrapWith.concat(str).concat(wrapWith); 9133 } 9134 9135 /** 9136 * Wraps a string with a char if that char is missing from the start or end of the given string. 9137 * 9138 * <p> 9139 * A new {@link String} will not be created if {@code str} is already wrapped. 9140 * </p> 9141 * 9142 * <pre> 9143 * StringUtils.wrapIfMissing(null, *) = null 9144 * StringUtils.wrapIfMissing("", *) = "" 9145 * StringUtils.wrapIfMissing("ab", '\0') = "ab" 9146 * StringUtils.wrapIfMissing("ab", 'x') = "xabx" 9147 * StringUtils.wrapIfMissing("ab", '\'') = "'ab'" 9148 * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\"" 9149 * StringUtils.wrapIfMissing("/", '/') = "/" 9150 * StringUtils.wrapIfMissing("a/b/c", '/') = "/a/b/c/" 9151 * StringUtils.wrapIfMissing("/a/b/c", '/') = "/a/b/c/" 9152 * StringUtils.wrapIfMissing("a/b/c/", '/') = "/a/b/c/" 9153 * </pre> 9154 * 9155 * @param str the string to be wrapped, may be {@code null}. 9156 * @param wrapWith the char that will wrap {@code str}. 9157 * @return the wrapped string, or {@code null} if {@code str == null}. 9158 * @since 3.5 9159 */ 9160 public static String wrapIfMissing(final String str, final char wrapWith) { 9161 if (isEmpty(str) || wrapWith == CharUtils.NUL) { 9162 return str; 9163 } 9164 final boolean wrapStart = str.charAt(0) != wrapWith; 9165 final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith; 9166 if (!wrapStart && !wrapEnd) { 9167 return str; 9168 } 9169 final StringBuilder builder = new StringBuilder(str.length() + 2); 9170 if (wrapStart) { 9171 builder.append(wrapWith); 9172 } 9173 builder.append(str); 9174 if (wrapEnd) { 9175 builder.append(wrapWith); 9176 } 9177 return builder.toString(); 9178 } 9179 9180 /** 9181 * Wraps a string with a string if that string is missing from the start or end of the given string. 9182 * 9183 * <p> 9184 * A new {@link String} will not be created if {@code str} is already wrapped. 9185 * </p> 9186 * 9187 * <pre> 9188 * StringUtils.wrapIfMissing(null, *) = null 9189 * StringUtils.wrapIfMissing("", *) = "" 9190 * StringUtils.wrapIfMissing("ab", null) = "ab" 9191 * StringUtils.wrapIfMissing("ab", "x") = "xabx" 9192 * StringUtils.wrapIfMissing("ab", "\"") = "\"ab\"" 9193 * StringUtils.wrapIfMissing("\"ab\"", "\"") = "\"ab\"" 9194 * StringUtils.wrapIfMissing("ab", "'") = "'ab'" 9195 * StringUtils.wrapIfMissing("'abcd'", "'") = "'abcd'" 9196 * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'" 9197 * StringUtils.wrapIfMissing("'abcd'", "\"") = "\"'abcd'\"" 9198 * StringUtils.wrapIfMissing("/", "/") = "/" 9199 * StringUtils.wrapIfMissing("a/b/c", "/") = "/a/b/c/" 9200 * StringUtils.wrapIfMissing("/a/b/c", "/") = "/a/b/c/" 9201 * StringUtils.wrapIfMissing("a/b/c/", "/") = "/a/b/c/" 9202 * </pre> 9203 * 9204 * @param str the string to be wrapped, may be {@code null}. 9205 * @param wrapWith the string that will wrap {@code str}. 9206 * @return the wrapped string, or {@code null} if {@code str == null}. 9207 * @since 3.5 9208 */ 9209 public static String wrapIfMissing(final String str, final String wrapWith) { 9210 if (isEmpty(str) || isEmpty(wrapWith)) { 9211 return str; 9212 } 9213 final boolean wrapStart = !str.startsWith(wrapWith); 9214 final boolean wrapEnd = !str.endsWith(wrapWith); 9215 if (!wrapStart && !wrapEnd) { 9216 return str; 9217 } 9218 final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length()); 9219 if (wrapStart) { 9220 builder.append(wrapWith); 9221 } 9222 builder.append(str); 9223 if (wrapEnd) { 9224 builder.append(wrapWith); 9225 } 9226 return builder.toString(); 9227 } 9228 9229 /** 9230 * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}. 9231 * 9232 * <p> 9233 * This constructor is public to permit tools that require a JavaBean instance to operate. 9234 * </p> 9235 * 9236 * @deprecated TODO Make private in 4.0. 9237 */ 9238 @Deprecated 9239 public StringUtils() { 9240 // empty 9241 } 9242 9243}