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