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