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